1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package net.sf.ldaptemplate.support;
18
19 import java.net.URI;
20 import java.net.URISyntaxException;
21 import java.util.regex.Matcher;
22 import java.util.regex.Pattern;
23
24 import net.sf.ldaptemplate.BadLdapGrammarException;
25
26 import org.apache.commons.lang.StringUtils;
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30 /***
31 * Datatype for a LDAP name, a part of a path.
32 *
33 * The name: uid=adam.skogman Key: uid Value: adam.skogman
34 *
35 * @author Adam Skogman
36 */
37 public class LdapRdn {
38
39 private String key;
40
41 private String value;
42
43 private String ldapEncoded;
44
45 protected static final Pattern RDN_PATTERN = Pattern
46 .compile("//s*(//p{Alnum}+)//s*=//s*((//////p{XDigit}{2}|////.|[^////])+?)//s*");
47
48 private static final Log log = LogFactory.getLog(LdapRdn.class);
49
50 /***
51 * Constructs a RDN from an ldap encoded rdn "foo=bar".
52 *
53 * The key will be forced to lowercase. The value is kept as is.
54 *
55 * The ldapEncoded value will not be the same, but rather a reencoded value,
56 * so that all looks the same.
57 *
58 * @param ldapRdn
59 * @throws BadLdapGrammarException
60 * If the rdn could not be parsed.
61 */
62 public LdapRdn(String ldapRdn) throws BadLdapGrammarException {
63
64 parseLdap(ldapRdn);
65
66 }
67
68 /***
69 * Constructs a RDN from a key and a value.
70 *
71 * The key will be forced to lowercase. The value is kept as is.
72 *
73 * @param key
74 * Not blank
75 * @param value
76 * Not blank
77 */
78 public LdapRdn(String key, String value) {
79
80 if (StringUtils.isBlank(key))
81 throw new IllegalArgumentException("Key may not be blank");
82
83 if (StringUtils.isBlank(value))
84 throw new IllegalArgumentException("Value may not be blank");
85
86 this.key = key.toLowerCase();
87 this.value = value;
88
89 this.ldapEncoded = encodeLdap();
90
91 }
92
93 /***
94 * Encode key and value to ldap
95 *
96 * @return The ldap encoded rdn
97 */
98 protected String encodeLdap() {
99
100 StringBuffer buff = new StringBuffer(key.length() + value.length() * 2);
101
102 buff.append(key);
103 buff.append('=');
104 buff.append(LdapEncoder.nameEncode(value));
105
106 return buff.toString();
107 }
108
109 /***
110 * @param rdn
111 * The ldap rdn to parse
112 */
113 protected void parseLdap(String rdn) throws BadLdapGrammarException {
114
115 Matcher matcher = RDN_PATTERN.matcher(rdn);
116
117 if (!matcher.matches()) {
118 throw new BadLdapGrammarException(
119 "Not a proper name (such as key=value): " + rdn);
120 }
121
122 String rawKey = matcher.group(1);
123 String rawValue = matcher.group(2);
124
125 this.key = StringUtils.lowerCase(rawKey);
126 this.value = LdapEncoder.nameDecode(rawValue);
127
128 if (key == null) {
129 throw new BadLdapGrammarException("Key empty in rdn '" + rdn + "'");
130 }
131 if (value == null) {
132 throw new BadLdapGrammarException("Value empty in rdn '" + rdn
133 + "'");
134 }
135
136 this.ldapEncoded = encodeLdap();
137
138 }
139
140 /***
141 * Parse the supplied String for a valid LdapRdn. Swallow any exceptions.
142 *
143 * @param rdn
144 * the String to parse.
145 * @return an LdapRdn corresponding to the supplied String if the format was
146 * valid, null otherwise.
147 */
148 public static LdapRdn parse(String rdn) {
149
150 try {
151 return new LdapRdn(rdn);
152 } catch (BadLdapGrammarException e) {
153 return null;
154 }
155
156 }
157
158 public String getKey() {
159 return key;
160 }
161
162 public String getValue() {
163 return value;
164 }
165
166 /***
167 *
168 *
169 * @see java.lang.Object#toString()
170 */
171 public String toString() {
172 return ldapEncoded;
173 }
174
175 /***
176 * @see java.lang.Object#equals(java.lang.Object)
177 */
178 public boolean equals(Object obj) {
179
180
181 if (obj == null || obj.getClass() != this.getClass()) {
182 return false;
183 }
184
185 LdapRdn rdn = (LdapRdn) obj;
186
187 return StringUtils.equalsIgnoreCase(rdn.key, this.key)
188 && StringUtils.equalsIgnoreCase(rdn.value, this.value);
189 }
190
191 public Object encodeUrl() {
192
193 try {
194 URI valueUri = new URI(null, null, value, null);
195 return key + "=" + valueUri.toString();
196 } catch (URISyntaxException e) {
197
198 log.error("Failed to URL encode value " + value, e);
199 return key + "=" + "value";
200 }
201 }
202
203 /***
204 * @see java.lang.Object#hashCode()
205 */
206 public int hashCode() {
207 return key.hashCode() ^ value.hashCode();
208 }
209
210 /***
211 * @return The LdapRdn as a string where the value is LDAP-encoded.
212 */
213 public String getLdapEncoded() {
214 return ldapEncoded;
215 }
216 }