001package org.apache.commons.ssl.org.bouncycastle.asn1.x509;
002
003import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Encodable;
004import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1String;
009import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1TaggedObject;
010import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
011import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
012
013/**
014 * Implementation of the RoleSyntax object as specified by the RFC3281.
015 * 
016 * <pre>
017 * RoleSyntax ::= SEQUENCE {
018 *                 roleAuthority  [0] GeneralNames OPTIONAL,
019 *                 roleName       [1] GeneralName
020 *           } 
021 * </pre>
022 */
023public class RoleSyntax 
024    extends ASN1Object
025{
026    private GeneralNames roleAuthority;
027    private GeneralName roleName;
028
029    /**
030     * RoleSyntax factory method.
031     * @param obj the object used to construct an instance of <code>
032     * RoleSyntax</code>. It must be an instance of <code>RoleSyntax
033     * </code> or <code>ASN1Sequence</code>.
034     * @return the instance of <code>RoleSyntax</code> built from the
035     * supplied object.
036     * @throws java.lang.IllegalArgumentException if the object passed
037     * to the factory is not an instance of <code>RoleSyntax</code> or
038     * <code>ASN1Sequence</code>.
039     */
040    public static RoleSyntax getInstance(
041        Object obj)
042    {
043        
044        if (obj instanceof RoleSyntax)
045        {
046            return (RoleSyntax)obj;
047        }
048        else if (obj != null)
049        {
050            return new RoleSyntax(ASN1Sequence.getInstance(obj));
051        }
052
053        return null;
054    }
055    
056    /**
057     * Constructor.
058     * @param roleAuthority the role authority of this RoleSyntax.
059     * @param roleName    the role name of this RoleSyntax.
060     */
061    public RoleSyntax(
062        GeneralNames roleAuthority,
063        GeneralName roleName)
064    {
065        if(roleName == null || 
066                roleName.getTagNo() != GeneralName.uniformResourceIdentifier ||
067                ((ASN1String)roleName.getName()).getString().equals(""))
068        {
069            throw new IllegalArgumentException("the role name MUST be non empty and MUST " +
070                    "use the URI option of GeneralName");
071        }
072        this.roleAuthority = roleAuthority;
073        this.roleName = roleName;
074    }
075    
076    /**
077     * Constructor. Invoking this constructor is the same as invoking
078     * <code>new RoleSyntax(null, roleName)</code>.
079     * @param roleName    the role name of this RoleSyntax.
080     */
081    public RoleSyntax(
082        GeneralName roleName)
083    {
084        this(null, roleName);
085    }
086
087    /**
088     * Utility constructor. Takes a <code>String</code> argument representing
089     * the role name, builds a <code>GeneralName</code> to hold the role name
090     * and calls the constructor that takes a <code>GeneralName</code>.
091     * @param roleName
092     */
093    public RoleSyntax(
094        String roleName)
095    {
096        this(new GeneralName(GeneralName.uniformResourceIdentifier,
097                (roleName == null)? "": roleName));
098    }
099    
100    /**
101     * Constructor that builds an instance of <code>RoleSyntax</code> by
102     * extracting the encoded elements from the <code>ASN1Sequence</code>
103     * object supplied.
104     * @param seq    an instance of <code>ASN1Sequence</code> that holds
105     * the encoded elements used to build this <code>RoleSyntax</code>.
106     */
107    private RoleSyntax(
108        ASN1Sequence seq)
109    {
110        if (seq.size() < 1 || seq.size() > 2)
111        {
112            throw new IllegalArgumentException("Bad sequence size: "
113                    + seq.size());
114        }
115
116        for (int i = 0; i != seq.size(); i++)
117        {
118            ASN1TaggedObject taggedObject = ASN1TaggedObject.getInstance(seq.getObjectAt(i));
119            switch (taggedObject.getTagNo())
120            {
121            case 0:
122                roleAuthority = GeneralNames.getInstance(taggedObject, false);
123                break;
124            case 1:
125                roleName = GeneralName.getInstance(taggedObject, true);
126                break;
127            default:
128                throw new IllegalArgumentException("Unknown tag in RoleSyntax");
129            }
130        }
131    }
132
133    /**
134     * Gets the role authority of this RoleSyntax.
135     * @return    an instance of <code>GeneralNames</code> holding the
136     * role authority of this RoleSyntax.
137     */
138    public GeneralNames getRoleAuthority()
139    {
140        return this.roleAuthority;
141    }
142    
143    /**
144     * Gets the role name of this RoleSyntax.
145     * @return    an instance of <code>GeneralName</code> holding the
146     * role name of this RoleSyntax.
147     */
148    public GeneralName getRoleName()
149    {
150        return this.roleName;
151    }
152    
153    /**
154     * Gets the role name as a <code>java.lang.String</code> object.
155     * @return    the role name of this RoleSyntax represented as a 
156     * <code>java.lang.String</code> object.
157     */
158    public String getRoleNameAsString()
159    {
160        ASN1String str = (ASN1String)this.roleName.getName();
161        
162        return str.getString();
163    }
164    
165    /**
166     * Gets the role authority as a <code>String[]</code> object.
167     * @return the role authority of this RoleSyntax represented as a
168     * <code>String[]</code> array.
169     */
170    public String[] getRoleAuthorityAsString() 
171    {
172        if(roleAuthority == null) 
173        {
174            return new String[0];
175        }
176        
177        GeneralName[] names = roleAuthority.getNames();
178        String[] namesString = new String[names.length];
179        for(int i = 0; i < names.length; i++) 
180        {
181            ASN1Encodable value = names[i].getName();
182            if(value instanceof ASN1String)
183            {
184                namesString[i] = ((ASN1String)value).getString();
185            }
186            else
187            {
188                namesString[i] = value.toString();
189            }
190        }
191        return namesString;
192    }
193    
194    /**
195     * Implementation of the method <code>toASN1Object</code> as
196     * required by the superclass <code>ASN1Encodable</code>.
197     * 
198     * <pre>
199     * RoleSyntax ::= SEQUENCE {
200     *                 roleAuthority  [0] GeneralNames OPTIONAL,
201     *                 roleName       [1] GeneralName
202     *           } 
203     * </pre>
204     */
205    public ASN1Primitive toASN1Primitive()
206    {
207        ASN1EncodableVector v = new ASN1EncodableVector();
208        if(this.roleAuthority != null)
209        {
210            v.add(new DERTaggedObject(false, 0, roleAuthority));
211        }
212        v.add(new DERTaggedObject(true, 1, roleName));
213        
214        return new DERSequence(v);
215    }
216    
217    public String toString() 
218    {
219        StringBuffer buff = new StringBuffer("Name: " + this.getRoleNameAsString() +
220                " - Auth: ");
221        if(this.roleAuthority == null || roleAuthority.getNames().length == 0)
222        {
223            buff.append("N/A");
224        }
225        else 
226        {
227            String[] names = this.getRoleAuthorityAsString();
228            buff.append('[').append(names[0]);
229            for(int i = 1; i < names.length; i++) 
230            {
231                    buff.append(", ").append(names[i]);
232            }
233            buff.append(']');
234        }
235        return buff.toString();
236    }
237}