001package org.apache.commons.ssl.org.bouncycastle.asn1.x509;
002
003import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Choice;
004import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
007import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
008
009/**
010 * Target structure used in target information extension for attribute
011 * certificates from RFC 3281.
012 * 
013 * <pre>
014 *     Target  ::= CHOICE {
015 *       targetName          [0] GeneralName,
016 *       targetGroup         [1] GeneralName,
017 *       targetCert          [2] TargetCert
018 *     }
019 * </pre>
020 * 
021 * <p>
022 * The targetCert field is currently not supported and must not be used
023 * according to RFC 3281.
024 */
025public class Target
026    extends ASN1Object
027    implements ASN1Choice
028{
029    public static final int targetName = 0;
030    public static final int targetGroup = 1;
031
032    private GeneralName targName;
033    private GeneralName targGroup;
034
035    /**
036     * Creates an instance of a Target from the given object.
037     * <p>
038     * <code>obj</code> can be a Target or a {@link ASN1TaggedObject}
039     * 
040     * @param obj The object.
041     * @return A Target instance.
042     * @throws IllegalArgumentException if the given object cannot be
043     *             interpreted as Target.
044     */
045    public static Target getInstance(Object obj)
046    {
047        if (obj == null || obj instanceof Target)
048        {
049            return (Target) obj;
050        }
051        else if (obj instanceof ASN1TaggedObject)
052        {
053            return new Target((ASN1TaggedObject)obj);
054        }
055
056        throw new IllegalArgumentException("unknown object in factory: "
057            + obj.getClass());
058    }
059
060    /**
061     * Constructor from ASN1TaggedObject.
062     * 
063     * @param tagObj The tagged object.
064     * @throws IllegalArgumentException if the encoding is wrong.
065     */
066    private Target(ASN1TaggedObject tagObj)
067    {
068        switch (tagObj.getTagNo())
069        {
070        case targetName:     // GeneralName is already a choice so explicit
071            targName = GeneralName.getInstance(tagObj, true);
072            break;
073        case targetGroup:
074            targGroup = GeneralName.getInstance(tagObj, true);
075            break;
076        default:
077            throw new IllegalArgumentException("unknown tag: " + tagObj.getTagNo());
078        }
079    }
080
081    /**
082     * Constructor from given details.
083     * <p>
084     * Exactly one of the parameters must be not <code>null</code>.
085     *
086     * @param type the choice type to apply to the name.
087     * @param name the general name.
088     * @throws IllegalArgumentException if type is invalid.
089     */
090    public Target(int type, GeneralName name)
091    {
092        this(new DERTaggedObject(type, name));
093    }
094
095    /**
096     * @return Returns the targetGroup.
097     */
098    public GeneralName getTargetGroup()
099    {
100        return targGroup;
101    }
102
103    /**
104     * @return Returns the targetName.
105     */
106    public GeneralName getTargetName()
107    {
108        return targName;
109    }
110
111    /**
112     * Produce an object suitable for an ASN1OutputStream.
113     * 
114     * Returns:
115     * 
116     * <pre>
117     *     Target  ::= CHOICE {
118     *       targetName          [0] GeneralName,
119     *       targetGroup         [1] GeneralName,
120     *       targetCert          [2] TargetCert
121     *     }
122     * </pre>
123     * 
124     * @return a ASN1Primitive
125     */
126    public ASN1Primitive toASN1Primitive()
127    {
128        // GeneralName is a choice already so most be explicitly tagged
129        if (targName != null)
130        {
131            return new DERTaggedObject(true, 0, targName);
132        }
133        else
134        {
135            return new DERTaggedObject(true, 1, targGroup);
136        }
137    }
138}