OSDN Git Service

original
[gb-231r1-is01/Gingerbread_2.3.3_r1_IS01.git] / libcore / luni / src / main / java / org / apache / harmony / security / x501 / Name.java
1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17
18 /**
19 * @author Alexander V. Esin
20 * @version $Revision$
21 */
22
23 package org.apache.harmony.security.x501;
24
25 import java.io.IOException;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.Iterator;
29 import java.util.LinkedList;
30 import java.util.List;
31 import java.util.Locale;
32 import javax.security.auth.x500.X500Principal;
33 import org.apache.harmony.security.asn1.ASN1SequenceOf;
34 import org.apache.harmony.security.asn1.ASN1SetOf;
35 import org.apache.harmony.security.asn1.BerInputStream;
36 import org.apache.harmony.security.asn1.DerInputStream;
37 import org.apache.harmony.security.x509.DNParser;
38
39
40 /**
41  * X.501 Name
42  */
43 public class Name {
44
45     //ASN.1 DER encoding of Name
46     private volatile byte[] encoded;
47
48     // RFC1779 string
49     private String rfc1779String;
50
51     // RFC2253 string
52     private String rfc2253String;
53
54     //CANONICAL string
55     private String canonicalString;
56
57     //Collection of RDNs
58     private List rdn;
59
60     /**
61      * Creates new <code>Name</code> instance from its DER encoding
62      *
63      * @param encoding - ASN.1 DER encoding
64      * @throws IOException - if encoding is wrong
65      */
66     public Name(byte[] encoding) throws IOException {
67
68         DerInputStream in = new DerInputStream(encoding);
69
70         if (in.getEndOffset() != encoding.length) {
71             throw new IOException("Wrong content length");
72         }
73
74         ASN1.decode(in);
75
76         this.rdn = (List) in.content;
77     }
78
79     /**
80      * Creates new <code>Name</code> instance
81      *
82      * @param name - Name as String
83      * @throws IOException - if string is wrong
84      */
85     public Name(String name) throws IOException {
86         rdn = new DNParser(name).parse();
87     }
88
89     // Creates Name instance
90     private Name(List rdn) {
91         this.rdn = rdn;
92     }
93
94     /**
95      * Returns <code>X500Principal</code> instance corresponding to this
96      * <code>Name</code> instance
97      *
98      * @return equivalent X500Principal object
99      */
100     public X500Principal getX500Principal(){
101         return new X500Principal(getName0(X500Principal.RFC2253));
102     }
103
104     /**
105      * Returns Relative Distinguished Name as <code>String</code> according
106      * the format requested
107      *
108      * @param format
109      *            Name format requested
110      * @return Relative Distinguished Name as <code>String</code> according
111      *         the format requested
112      */
113     public String getName(String format) {
114
115         //
116         // check X500Principal constants first
117         //
118         if (X500Principal.RFC1779.equals(format)) {
119
120             if (rfc1779String == null) {
121                 rfc1779String = getName0(format);
122             }
123             return rfc1779String;
124
125         } else if (X500Principal.RFC2253.equals(format)) {
126
127             if (rfc2253String == null) {
128                 rfc2253String = getName0(format);
129             }
130             return rfc2253String;
131
132         } else if (X500Principal.CANONICAL.equals(format)) {
133
134             if (canonicalString == null) {
135                 canonicalString = getName0(format);
136             }
137             return canonicalString;
138
139         }
140         //
141         // compare ignore case
142         //
143         else if (X500Principal.RFC1779.equalsIgnoreCase(format)) {
144
145             if (rfc1779String == null) {
146                 rfc1779String = getName0(X500Principal.RFC1779);
147             }
148             return rfc1779String;
149
150         } else if (X500Principal.RFC2253.equalsIgnoreCase(format)) {
151
152             if (rfc2253String == null) {
153                 rfc2253String = getName0(X500Principal.RFC2253);
154             }
155             return rfc2253String;
156
157         } else if (X500Principal.CANONICAL.equalsIgnoreCase(format)) {
158
159             if (canonicalString == null) {
160                 canonicalString = getName0(X500Principal.CANONICAL);
161             }
162             return canonicalString;
163
164         } else {
165             throw new IllegalArgumentException("Illegal format: " + format);
166         }
167     }
168
169     /**
170      * Returns Relative Distinguished Name as <code>String</code> according
171      * the format requested, format is int value
172      *
173      * @param format
174      *            Name format requested
175      * @return Relative Distinguished Name as <code>String</code> according
176      *         the format requested
177      */
178     private String getName0(String format) {
179
180         StringBuffer name = new StringBuffer();
181
182         // starting with the last element and moving to the first.
183         for (int i = rdn.size() - 1; i >= 0; i--) {
184             List atavList = (List) rdn.get(i);
185
186             if (X500Principal.CANONICAL == format) {
187                 List sortedList = new LinkedList(atavList);
188                 Collections.sort(sortedList,
189                         new AttributeTypeAndValueComparator());
190                 atavList = sortedList;
191             }
192
193             // Relative Distinguished Name to string
194             Iterator it = atavList.iterator();
195             while (it.hasNext()) {
196                 AttributeTypeAndValue _ava = (AttributeTypeAndValue) it.next();
197                 _ava.appendName(format, name);
198                 if (it.hasNext()) {
199                     // multi-valued RDN
200                     if (X500Principal.RFC1779 == format) {
201                         name.append(" + ");
202                     } else {
203                         name.append('+');
204                     }
205                 }
206             }
207
208             if (i != 0) {
209                 name.append(',');
210                 if (format == X500Principal.RFC1779) {
211                     name.append(' ');
212                 }
213             }
214         }
215
216         String sName = name.toString();
217         if (X500Principal.CANONICAL.equals(format)) {
218             sName = sName.toLowerCase(Locale.US);
219         }
220         return sName;
221     }
222
223     /**
224      * Gets encoded form of DN
225      *
226      * @return return encoding, no copying is performed
227      */
228     public byte[] getEncoded() {
229         if (encoded == null) {
230             encoded = ASN1.encode(this);
231         }
232         return encoded;
233     }
234
235     /**
236      * According to RFC 3280 (http://www.ietf.org/rfc/rfc3280.txt)
237      * X.501 Name structure is defined as follows:
238      *
239      * Name ::= CHOICE {
240      *     RDNSequence }
241      *
242      * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName
243      *
244      * RelativeDistinguishedName ::=
245      *     SET OF AttributeTypeAndValue
246      *
247      */
248
249     public static final ASN1SetOf ASN1_RDN = new ASN1SetOf(
250             AttributeTypeAndValue.ASN1);
251
252     public static final ASN1SequenceOf ASN1 = new ASN1SequenceOf(ASN1_RDN) {
253
254         public Object getDecodedObject(BerInputStream in) {
255             return new Name((List) in.content);
256         }
257
258         public Collection getValues(Object object) {
259             return ((Name) object).rdn; //FIXME what about get method?
260         }
261     };
262 }