001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package javax.naming.ldap;
019:
020: import java.io.IOException;
021: import java.io.ObjectInputStream;
022: import java.io.ObjectOutputStream;
023: import java.io.Serializable;
024: import java.util.ArrayList;
025: import java.util.Enumeration;
026: import java.util.Iterator;
027: import java.util.List;
028:
029: import javax.naming.InvalidNameException;
030: import javax.naming.NamingEnumeration;
031: import javax.naming.NamingException;
032: import javax.naming.directory.Attribute;
033: import javax.naming.directory.Attributes;
034: import javax.naming.directory.BasicAttribute;
035: import javax.naming.directory.BasicAttributes;
036:
037: import org.apache.harmony.jndi.internal.nls.Messages;
038: import org.apache.harmony.jndi.internal.parser.LdapRdnParser;
039: import org.apache.harmony.jndi.internal.parser.LdapTypeAndValueList;
040:
041: /**
042: * TODO: JavaDoc
043: */
044: public class Rdn implements Serializable, Comparable<Object> {
045:
046: private static final long serialVersionUID = -5994465067210009656L;
047:
048: public static String escapeValue(Object val) {
049: if (val == null) {
050: throw new NullPointerException("val "
051: + Messages.getString("ldap.00"));
052: }
053: return LdapRdnParser.escapeValue(val);
054: }
055:
056: public static Object unescapeValue(String val) {
057: if (val == null) {
058: throw new NullPointerException("val "
059: + Messages.getString("ldap.00"));
060: }
061: return LdapRdnParser.unescapeValue(val);
062: }
063:
064: private transient List<Attribute> list;
065:
066: private transient LdapRdnParser parser;
067:
068: public Rdn(Attributes attrSet) throws InvalidNameException {
069: if (attrSet == null) {
070: throw new NullPointerException("attrSet "
071: + Messages.getString("ldap.00"));
072: }
073:
074: if (attrSet.size() == 0) {
075: throw new InvalidNameException("atrrSet "
076: + Messages.getString("ldap.03"));
077: }
078:
079: // check all the elements to follow RI's behavior
080: NamingEnumeration<? extends Attribute> ne = attrSet.getAll();
081: while (ne.hasMoreElements()) {
082: Attribute at = ne.nextElement();
083: try {
084: at.get();
085: } catch (NamingException e) {
086: }
087: }
088:
089: list = convertToAttributeArrayList(attrSet);
090: }
091:
092: public Rdn(Rdn rdn) {
093: if (rdn == null) {
094: throw new NullPointerException("rdn "
095: + Messages.getString("ldap.00"));
096: }
097:
098: list = convertToAttributeArrayList(rdn.toAttributes());
099: }
100:
101: public Rdn(String rdnString) throws InvalidNameException {
102: if (rdnString == null) {
103: throw new NullPointerException("rdnString "
104: + Messages.getString("ldap.00"));
105: }
106:
107: if (rdnString.length() != 0) {
108: parser = new LdapRdnParser(rdnString);
109: list = parser.getList();
110: } else {
111: list = new ArrayList<Attribute>();
112: }
113: }
114:
115: public Rdn(String type, Object value) throws InvalidNameException {
116: if (type == null) {
117: throw new NullPointerException("type "
118: + Messages.getString("ldap.00"));
119: }
120:
121: if (value == null) {
122: throw new NullPointerException("value "
123: + Messages.getString("ldap.00"));
124: }
125:
126: if (type.length() == 0) {
127: throw new InvalidNameException("type "
128: + Messages.getString("ldap.04"));
129: }
130:
131: if (value instanceof String && ((String) value).length() == 0) {
132: throw new InvalidNameException("value "
133: + Messages.getString("ldap.04"));
134: }
135:
136: list = convertToAttributeArrayList(new BasicAttributes(type,
137: value, true));
138: }
139:
140: public int compareTo(Object obj) {
141: if (!(obj instanceof Rdn)) {
142: throw new ClassCastException(Messages.getString("ldap.06")); //$NON-NLS-1$
143: }
144: Rdn rdn = (Rdn) obj;
145: String s1 = ""; //$NON-NLS-1$
146: String s2 = ""; //$NON-NLS-1$
147:
148: for (Enumeration<?> iter = toAttributes().getAll(); iter
149: .hasMoreElements();) {
150: s1 = s1 + escapeValue(iter.nextElement().toString());
151:
152: /*
153: * this one does not seem necessary. Spec does not require it, if
154: * there are apps that depend on commas, uncomment it
155: */
156: // if (iter.hasMoreElements()) {
157: // s1 = s1 + ",";
158: // }
159: }
160: for (Enumeration<?> iter = rdn.toAttributes().getAll(); iter
161: .hasMoreElements();) {
162: s2 = s2 + escapeValue(iter.nextElement().toString());
163:
164: /*
165: * this one does not seem necessary. Spec does not require it, if
166: * there are apps that depend on commas, uncomment it
167: */
168: // if (iter.hasMoreElements()) {
169: // s2 = s2 + ",";
170: // }
171: }
172: return s1.toLowerCase().compareTo(s2.toLowerCase());
173: }
174:
175: private List<Attribute> convertToAttributeArrayList(
176: Attributes attrList) {
177: LdapTypeAndValueList myList = new LdapTypeAndValueList();
178:
179: NamingEnumeration<? extends Attribute> ne = attrList.getAll();
180: try {
181: while (ne.hasMoreElements()) {
182: Attribute attr = ne.nextElement();
183: myList.put(attr.getID(), attr.get());
184: }
185: } catch (NamingException e) {
186:
187: }
188: return myList.toAttributeList();
189: }
190:
191: public boolean equals(Object obj) {
192:
193: if (!(obj instanceof Rdn) || this .size() != ((Rdn) obj).size()) {
194: return false;
195: }
196:
197: if (this == obj) {
198: return true;
199: }
200:
201: NamingEnumeration<? extends Attribute> iter1 = toAttributes()
202: .getAll();
203: NamingEnumeration<? extends Attribute> iter2 = ((Rdn) obj)
204: .toAttributes().getAll();
205:
206: while (iter1.hasMoreElements()) {
207: Attribute a1 = iter1.nextElement();
208: Attribute a2 = iter2.nextElement();
209:
210: if (!(a1.getID().toLowerCase().equals(a2.getID()
211: .toLowerCase()))
212: || a1.size() != a2.size()) {
213: return false;
214: }
215:
216: Enumeration<?> en1 = null;
217: Enumeration<?> en2 = null;
218: try {
219: en1 = a1.getAll();
220: en2 = a2.getAll();
221: } catch (NamingException e) {
222: // what is the correct way for this?
223: return false;
224: }
225:
226: while (en1.hasMoreElements()) {
227: Object o1 = en1.nextElement();
228: String s1 = (o1 instanceof String) ? (String) o1
229: : escapeValue(o1);
230:
231: Object o2 = en2.nextElement();
232: String s2 = (o2 instanceof String) ? (String) o2
233: : escapeValue(o2);
234:
235: if (!(s1.toLowerCase().equals(s2.toLowerCase()))) {
236: return false;
237: }
238: }
239: }
240: return true;
241: }
242:
243: public String getType() {
244: return list.get(0).getID();
245: }
246:
247: public Object getValue() {
248: Object a = null;
249: try {
250: a = list.get(0).get();
251: } catch (NamingException e) {
252: } catch (NullPointerException e) {
253: }
254: return a;
255: }
256:
257: public int hashCode() {
258: int sum = 0;
259:
260: for (Iterator<Attribute> attr = list.iterator(); attr.hasNext();) {
261: Attribute a = attr.next();
262: NamingEnumeration<?> en = null;
263: sum += a.getID().toLowerCase().hashCode();
264:
265: try {
266: en = a.getAll();
267: } catch (NamingException e) {
268: continue;
269: }
270:
271: while (en.hasMoreElements()) {
272: Object obj = en.nextElement();
273: if (obj instanceof byte[]) {
274: obj = new String((byte[]) obj);
275: }
276: try {
277: String s = (String) obj;
278: sum += escapeValue(s.toLowerCase()).hashCode();
279: } catch (ClassCastException e) {
280: sum += obj.hashCode();
281: }
282: }
283: }
284: return sum;
285: }
286:
287: public int size() {
288: int result = 0;
289: for (Iterator<Attribute> iter = list.iterator(); iter.hasNext();) {
290: result += iter.next().size();
291: }
292: return result;
293: }
294:
295: public Attributes toAttributes() {
296: BasicAttributes bas = new BasicAttributes(true);
297: for (Iterator<Attribute> iter = list.iterator(); iter.hasNext();) {
298: Attribute attr = iter.next();
299: BasicAttribute ba = new BasicAttribute(attr.getID(), false);
300: try {
301: NamingEnumeration nameEnum = attr.getAll();
302: while (nameEnum.hasMore()) {
303: ba.add(nameEnum.next());
304: }
305: } catch (NamingException ne) {
306:
307: }
308: bas.put(ba);
309: }
310: return bas;
311: }
312:
313: public String toString() {
314: StringBuffer sb = new StringBuffer();
315: for (Iterator<Attribute> iter = list.iterator(); iter.hasNext();) {
316: Attribute element = iter.next();
317: NamingEnumeration<?> ne = null;
318:
319: try {
320: ne = element.getAll();
321: } catch (NamingException e) {
322: }
323:
324: while (ne.hasMoreElements()) {
325: sb.append(element.getID());
326: sb.append('=');
327: sb.append(escapeValue(ne.nextElement()));
328:
329: if (ne.hasMoreElements()) {
330: sb.append('+');
331: }
332: }
333:
334: if (iter.hasNext()) {
335: sb.append('+');
336: }
337: }
338: return sb.toString();
339: }
340:
341: private void readObject(ObjectInputStream ois) throws IOException,
342: ClassNotFoundException, InvalidNameException {
343: ois.defaultReadObject();
344: String rdnString = (String) ois.readObject();
345: if (rdnString == null) {
346: throw new NullPointerException("rdnString "
347: + Messages.getString("ldap.00"));
348: }
349: if (rdnString.length() != 0) {
350: parser = new LdapRdnParser(rdnString);
351: list = parser.getList();
352: } else {
353: list = new ArrayList<Attribute>();
354: }
355: }
356:
357: private void writeObject(ObjectOutputStream oos) throws IOException {
358: oos.defaultWriteObject();
359: oos.writeObject(this.toString());
360: }
361:
362: }
|