View Javadoc

1   /*
2    * Copyright 2005-2008 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.ldap.core;
18  
19  import java.io.Serializable;
20  import java.util.ArrayList;
21  import java.util.Collections;
22  import java.util.Comparator;
23  import java.util.Iterator;
24  import java.util.LinkedList;
25  import java.util.List;
26  
27  import org.apache.commons.lang.StringUtils;
28  import org.springframework.ldap.BadLdapGrammarException;
29  import org.springframework.ldap.support.ListComparator;
30  
31  /**
32   * Datatype for a LDAP name, a part of a path.
33   * 
34   * The name: uid=adam.skogman Key: uid Value: adam.skogman
35   * 
36   * @author Adam Skogman
37   * @author Mattias Hellborg Arthursson
38   */
39  public class LdapRdn implements Serializable, Comparable {
40  	private static final long serialVersionUID = 5681397547245228750L;
41  
42  	private List components = new LinkedList();
43  
44  	/**
45  	 * Default constructor. Create an empty, uninitialized LdapRdn.
46  	 */
47  	public LdapRdn() {
48  	}
49  
50  	/**
51  	 * Parse the supplied string and construct this instance accordingly.
52  	 * 
53  	 * @param string the string to parse.
54  	 */
55  	public LdapRdn(String string) {
56  		DnParser parser = DefaultDnParserFactory.createDnParser(string);
57  		LdapRdn rdn;
58  		try {
59  			rdn = parser.rdn();
60  		}
61  		catch (ParseException e) {
62  			throw new BadLdapGrammarException("Failed to parse Rdn", e);
63  		}
64  		catch (TokenMgrError e) {
65  			throw new BadLdapGrammarException("Failed to parse Rdn", e);
66  		}
67  		this.components = rdn.components;
68  	}
69  
70  	/**
71  	 * Construct an LdapRdn using the supplied key and value.
72  	 * 
73  	 * @param key the attribute name.
74  	 * @param value the attribute value.
75  	 */
76  	public LdapRdn(String key, String value) {
77  		components.add(new LdapRdnComponent(key, value));
78  	}
79  
80  	/**
81  	 * Add an LdapRdnComponent to this LdapRdn.
82  	 * 
83  	 * @param rdnComponent the LdapRdnComponent to add.s
84  	 */
85  	public void addComponent(LdapRdnComponent rdnComponent) {
86  		components.add(rdnComponent);
87  	}
88  
89  	/**
90  	 * Gets all components in this LdapRdn.
91  	 * 
92  	 * @return the List of all LdapRdnComponents composing this LdapRdn.
93  	 */
94  	public List getComponents() {
95  		return components;
96  	}
97  
98  	/**
99  	 * Gets the first LdapRdnComponent of this LdapRdn.
100 	 * 
101 	 * @return The first LdapRdnComponent of this LdapRdn.
102 	 * @throws IndexOutOfBoundsException if there are no components in this Rdn.
103 	 */
104 	public LdapRdnComponent getComponent() {
105 		return (LdapRdnComponent) components.get(0);
106 	}
107 
108 	/**
109 	 * Get the LdapRdnComponent at index <code>idx</code>.
110 	 * 
111 	 * @param idx the 0-based index of the component to get.
112 	 * @return the LdapRdnComponent at index <code>idx</code>.
113 	 * @throws IndexOutOfBoundsException if there are no components in this Rdn.
114 	 */
115 	public LdapRdnComponent getComponent(int idx) {
116 		return (LdapRdnComponent) components.get(idx);
117 	}
118 
119 	/**
120 	 * Get a properly rfc2253-encoded String representation of this LdapRdn.
121 	 * 
122 	 * @return an escaped String corresponding to this LdapRdn.
123 	 * @throws IndexOutOfBoundsException if there are no components in this Rdn.
124 	 */
125 	public String getLdapEncoded() {
126 		if (components.size() == 0) {
127 			throw new IndexOutOfBoundsException("No components in Rdn.");
128 		}
129 		StringBuffer sb = new StringBuffer(100);
130 		for (Iterator iter = components.iterator(); iter.hasNext();) {
131 			LdapRdnComponent component = (LdapRdnComponent) iter.next();
132 			sb.append(component.encodeLdap());
133 			if (iter.hasNext()) {
134 				sb.append("+");
135 			}
136 		}
137 
138 		return sb.toString();
139 	}
140 
141 	/**
142 	 * Get a String representation of this LdapRdn for use in urls.
143 	 * 
144 	 * @return a String representation of this LdapRdn for use in urls.
145 	 */
146 	public String encodeUrl() {
147 		StringBuffer sb = new StringBuffer(100);
148 		for (Iterator iter = components.iterator(); iter.hasNext();) {
149 			LdapRdnComponent component = (LdapRdnComponent) iter.next();
150 			sb.append(component.encodeUrl());
151 			if (iter.hasNext()) {
152 				sb.append("+");
153 			}
154 		}
155 
156 		return sb.toString();
157 	}
158 
159 	/**
160 	 * Compare this LdapRdn to another object.
161 	 * 
162 	 * @param obj the object to compare to.
163 	 * @throws ClassCastException if the supplied object is not an LdapRdn
164 	 * instance.
165 	 */
166 	public int compareTo(Object obj) {
167 		LdapRdn that = (LdapRdn) obj;
168 		Comparator comparator = new ListComparator();
169 		return comparator.compare(this.components, that.components);
170 	}
171 
172 	/*
173 	 * (non-Javadoc)
174 	 * 
175 	 * @see java.lang.Object#equals(java.lang.Object)
176 	 */
177 	public boolean equals(Object obj) {
178 		if (obj == null || obj.getClass() != this.getClass()) {
179 			return false;
180 		}
181 
182 		LdapRdn that = (LdapRdn) obj;
183 		return this.getComponents().equals(that.getComponents());
184 	}
185 
186 	/*
187 	 * (non-Javadoc)
188 	 * 
189 	 * @see java.lang.Object#hashCode()
190 	 */
191 	public int hashCode() {
192 		return this.getClass().hashCode() ^ getComponents().hashCode();
193 	}
194 
195 	/*
196 	 * (non-Javadoc)
197 	 * 
198 	 * @see java.lang.Object#toString()
199 	 */
200 	public String toString() {
201 		return getLdapEncoded();
202 	}
203 
204 	/**
205 	 * Get the value of this LdapRdn. Note that if this Rdn is multi-value the
206 	 * first value will be returned. E.g. for the Rdn
207 	 * <code>cn=john doe+sn=doe</code>, the return value would be
208 	 * <code>john doe</code>.
209 	 * 
210 	 * @return the (first) value of this LdapRdn.
211 	 * @throws IndexOutOfBoundsException if there are no components in this Rdn.
212 	 */
213 	public String getValue() {
214 		return getComponent().getValue();
215 	}
216 
217 	/**
218 	 * Get the key of this LdapRdn. Note that if this Rdn is multi-value the
219 	 * first key will be returned. E.g. for the Rdn
220 	 * <code>cn=john doe+sn=doe</code>, the return value would be
221 	 * <code>cn</code>.
222 	 * 
223 	 * @return the (first) key of this LdapRdn.
224 	 * @throws IndexOutOfBoundsException if there are no components in this Rdn.
225 	 */
226 	public String getKey() {
227 		return getComponent().getKey();
228 	}
229 
230 	/**
231 	 * Get the value of the LdapComponent with the specified key (Attribute
232 	 * name).
233 	 * 
234 	 * @param key the key
235 	 * @return the value.
236 	 * @throws IllegalArgumentException if there is no component with the
237 	 * specified key.
238 	 */
239 	public String getValue(String key) {
240 		for (Iterator iter = components.iterator(); iter.hasNext();) {
241 			LdapRdnComponent component = (LdapRdnComponent) iter.next();
242 			if (StringUtils.equals(component.getKey(), key)) {
243 				return component.getValue();
244 			}
245 		}
246 
247 		throw new IllegalArgumentException("No RdnComponent with the key " + key);
248 	}
249 
250 	/**
251 	 * Create an immutable copy of this instance. It will not be possible to add
252 	 * or remove components or modify the keys and values of these components.
253 	 * 
254 	 * @return an immutable copy of this instance.
255 	 * @since 1.3
256 	 */
257 	public LdapRdn immutableLdapRdn() {
258 		List listWithImmutableRdns = new ArrayList(components.size());
259 		for (Iterator iterator = components.iterator(); iterator.hasNext();) {
260 			LdapRdnComponent rdnComponent = (LdapRdnComponent) iterator.next();
261 			listWithImmutableRdns.add(rdnComponent.immutableLdapRdnComponent());
262 		}
263 		List unmodifiableListOfImmutableRdns = Collections.unmodifiableList(listWithImmutableRdns);
264 		LdapRdn immutableRdn = new LdapRdn();
265 		immutableRdn.components = unmodifiableListOfImmutableRdns;
266 		return immutableRdn;
267 	}
268 }