001package org.apache.commons.ssl.org.bouncycastle.asn1.esf;
002
003import java.util.Enumeration;
004
005import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1EncodableVector;
006import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Object;
007import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Primitive;
008import org.apache.commons.ssl.org.bouncycastle.asn1.ASN1Sequence;
009import org.apache.commons.ssl.org.bouncycastle.asn1.DERSequence;
010import org.apache.commons.ssl.org.bouncycastle.asn1.DERTaggedObject;
011import org.apache.commons.ssl.org.bouncycastle.asn1.DERUTF8String;
012import org.apache.commons.ssl.org.bouncycastle.asn1.x500.DirectoryString;
013
014/**
015 * Signer-Location attribute (RFC3126).
016 * 
017 * <pre>
018 *   SignerLocation ::= SEQUENCE {
019 *       countryName        [0] DirectoryString OPTIONAL,
020 *       localityName       [1] DirectoryString OPTIONAL,
021 *       postalAddress      [2] PostalAddress OPTIONAL }
022 *
023 *   PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
024 * </pre>
025 */
026public class SignerLocation
027    extends ASN1Object
028{
029    private DERUTF8String   countryName;
030    private DERUTF8String   localityName;
031    private ASN1Sequence    postalAddress;
032    
033    private SignerLocation(
034        ASN1Sequence seq)
035    {
036        Enumeration     e = seq.getObjects();
037
038        while (e.hasMoreElements())
039        {
040            DERTaggedObject o = (DERTaggedObject)e.nextElement();
041
042            switch (o.getTagNo())
043            {
044            case 0:
045                DirectoryString countryNameDirectoryString = DirectoryString.getInstance(o, true);
046                this.countryName = new DERUTF8String(countryNameDirectoryString.getString());
047                break;
048            case 1:
049                DirectoryString localityNameDirectoryString = DirectoryString.getInstance(o, true);
050                this.localityName = new DERUTF8String(localityNameDirectoryString.getString());
051                break;
052            case 2:
053                if (o.isExplicit())
054                {
055                    this.postalAddress = ASN1Sequence.getInstance(o, true);
056                }
057                else    // handle erroneous implicitly tagged sequences
058                {
059                    this.postalAddress = ASN1Sequence.getInstance(o, false);
060                }
061                if (postalAddress != null && postalAddress.size() > 6)
062                {
063                    throw new IllegalArgumentException("postal address must contain less than 6 strings");
064                }
065                break;
066            default:
067                throw new IllegalArgumentException("illegal tag");
068            }
069        }
070    }
071
072    public SignerLocation(
073        DERUTF8String   countryName,
074        DERUTF8String   localityName,
075        ASN1Sequence    postalAddress)
076    {
077        if (postalAddress != null && postalAddress.size() > 6)
078        {
079            throw new IllegalArgumentException("postal address must contain less than 6 strings");
080        }
081
082        if (countryName != null)
083        {
084            this.countryName = DERUTF8String.getInstance(countryName.toASN1Primitive());
085        }
086
087        if (localityName != null)
088        {
089            this.localityName = DERUTF8String.getInstance(localityName.toASN1Primitive());
090        }
091
092        if (postalAddress != null)
093        {
094            this.postalAddress = ASN1Sequence.getInstance(postalAddress.toASN1Primitive());
095        }
096    }
097
098    public static SignerLocation getInstance(
099        Object obj)
100    {
101        if (obj == null || obj instanceof SignerLocation)
102        {
103            return (SignerLocation)obj;
104        }
105
106        return new SignerLocation(ASN1Sequence.getInstance(obj));
107    }
108
109    public DERUTF8String getCountryName()
110    {
111        return countryName;
112    }
113
114    public DERUTF8String getLocalityName()
115    {
116        return localityName;
117    }
118
119    public ASN1Sequence getPostalAddress()
120    {
121        return postalAddress;
122    }
123
124    /**
125     * <pre>
126     *   SignerLocation ::= SEQUENCE {
127     *       countryName        [0] DirectoryString OPTIONAL,
128     *       localityName       [1] DirectoryString OPTIONAL,
129     *       postalAddress      [2] PostalAddress OPTIONAL }
130     *
131     *   PostalAddress ::= SEQUENCE SIZE(1..6) OF DirectoryString
132     *   
133     *   DirectoryString ::= CHOICE {
134     *         teletexString           TeletexString (SIZE (1..MAX)),
135     *         printableString         PrintableString (SIZE (1..MAX)),
136     *         universalString         UniversalString (SIZE (1..MAX)),
137     *         utf8String              UTF8String (SIZE (1.. MAX)),
138     *         bmpString               BMPString (SIZE (1..MAX)) }
139     * </pre>
140     */
141    public ASN1Primitive toASN1Primitive()
142    {
143        ASN1EncodableVector  v = new ASN1EncodableVector();
144
145        if (countryName != null)
146        {
147            v.add(new DERTaggedObject(true, 0, countryName));
148        }
149
150        if (localityName != null)
151        {
152            v.add(new DERTaggedObject(true, 1, localityName));
153        }
154
155        if (postalAddress != null)
156        {
157            v.add(new DERTaggedObject(true, 2, postalAddress));
158        }
159
160        return new DERSequence(v);
161    }
162}