137 |
* LDAP port. |
* LDAP port. |
138 |
* @param host the host |
* @param host the host |
139 |
*/ |
*/ |
140 |
public LDAPConnection (String host) |
public LDAPConnection(String host) |
141 |
throws IOException |
throws IOException |
142 |
{ |
{ |
143 |
this (host, DEFAULT_PORT, 0, 0); |
this(host, DEFAULT_PORT, 0, 0); |
144 |
} |
} |
145 |
|
|
146 |
/** |
/** |
148 |
* @param host the host |
* @param host the host |
149 |
* @param port the port |
* @param port the port |
150 |
*/ |
*/ |
151 |
public LDAPConnection (String host, int port) |
public LDAPConnection(String host, int port) |
152 |
throws IOException |
throws IOException |
153 |
{ |
{ |
154 |
this (host, port, 0, 0); |
this(host, port, 0, 0); |
155 |
} |
} |
156 |
|
|
157 |
/** |
/** |
161 |
* @param connectionTimeout the connection timeout in ms |
* @param connectionTimeout the connection timeout in ms |
162 |
* @param timeout the socket I/O timeout in ms |
* @param timeout the socket I/O timeout in ms |
163 |
*/ |
*/ |
164 |
public LDAPConnection (String host, int port, |
public LDAPConnection(String host, int port, |
165 |
int connectionTimeout, int timeout) |
int connectionTimeout, int timeout) |
166 |
throws IOException |
throws IOException |
167 |
{ |
{ |
168 |
this.host = host; |
this.host = host; |
172 |
} |
} |
173 |
this.port = port; |
this.port = port; |
174 |
messageId = 0; |
messageId = 0; |
175 |
asyncResponses = new HashMap (); |
asyncResponses = new HashMap(); |
176 |
version = 3; |
version = 3; |
177 |
|
|
178 |
// Connect |
// Connect |
179 |
socket = new Socket (); |
socket = new Socket(); |
180 |
SocketAddress address = new InetSocketAddress (host, port); |
SocketAddress address = new InetSocketAddress(host, port); |
181 |
if (connectionTimeout > 0) |
if (connectionTimeout > 0) |
182 |
{ |
{ |
183 |
socket.connect (address, connectionTimeout); |
socket.connect(address, connectionTimeout); |
184 |
} |
} |
185 |
else |
else |
186 |
{ |
{ |
187 |
socket.connect (address); |
socket.connect(address); |
188 |
} |
} |
189 |
in = new BufferedInputStream (socket.getInputStream ()); |
in = new BufferedInputStream(socket.getInputStream()); |
190 |
out = new BufferedOutputStream (socket.getOutputStream ()); |
out = new BufferedOutputStream(socket.getOutputStream()); |
191 |
} |
} |
192 |
|
|
193 |
/** |
/** |
195 |
* This implementation supports versions 2 and 3. |
* This implementation supports versions 2 and 3. |
196 |
* @param version the LDAP version |
* @param version the LDAP version |
197 |
*/ |
*/ |
198 |
public void setVersion (int version) |
public void setVersion(int version) |
199 |
{ |
{ |
200 |
if (version < 2 || version > 3) |
if (version < 2 || version > 3) |
201 |
{ |
{ |
202 |
throw new IllegalArgumentException (Integer.toString(version)); |
throw new IllegalArgumentException(Integer.toString(version)); |
203 |
} |
} |
204 |
this.version = version; |
this.version = version; |
205 |
} |
} |
213 |
* @param credentials the security credentials to use |
* @param credentials the security credentials to use |
214 |
* @return the LDAP result |
* @return the LDAP result |
215 |
*/ |
*/ |
216 |
public LDAPResult bind (String name, String mechanism, |
public LDAPResult bind(String name, String mechanism, |
217 |
byte[] credentials, Control[] controls) |
byte[] credentials, Control[] controls) |
218 |
throws IOException |
throws IOException |
219 |
{ |
{ |
220 |
int id = messageId++; |
int id = messageId++; |
221 |
boolean utf8 = (version == 3); |
boolean utf8 = (version == 3); |
222 |
BEREncoder bind = new BEREncoder (utf8); |
BEREncoder bind = new BEREncoder(utf8); |
223 |
if (mechanism == null) |
if (mechanism == null) |
224 |
{ |
{ |
225 |
bind.append (version); |
bind.append(version); |
226 |
bind.append (name); |
bind.append(name); |
227 |
if (credentials != null) |
if (credentials != null) |
228 |
{ |
{ |
229 |
bind.append (credentials); |
bind.append(credentials); |
230 |
} |
} |
231 |
} |
} |
232 |
else |
else |
233 |
{ |
{ |
234 |
bind.append (version); |
bind.append(version); |
235 |
bind.append (name); |
bind.append(name); |
236 |
// SASL credentials |
// SASL credentials |
237 |
BEREncoder saslCredentials = new BEREncoder (utf8); |
BEREncoder saslCredentials = new BEREncoder(utf8); |
238 |
saslCredentials.append (mechanism); |
saslCredentials.append(mechanism); |
239 |
if (credentials != null) |
if (credentials != null) |
240 |
{ |
{ |
241 |
saslCredentials.append (credentials); |
saslCredentials.append(credentials); |
242 |
} |
} |
243 |
bind.append (saslCredentials.toByteArray (), BERConstants.SEQUENCE); |
bind.append(saslCredentials.toByteArray(), BERConstants.SEQUENCE); |
244 |
} |
} |
245 |
// Request controls |
// Request controls |
246 |
BEREncoder ctls = new BEREncoder (utf8); |
BEREncoder ctls = new BEREncoder(utf8); |
247 |
if (controls != null) |
if (controls != null) |
248 |
{ |
{ |
249 |
for (int i = 0; i < controls.length; i++) |
for (int i = 0; i < controls.length; i++) |
250 |
{ |
{ |
251 |
ctls.append (controlSequence (controls[i], utf8), |
ctls.append(controlSequence(controls[i], utf8), |
252 |
BERConstants.SEQUENCE); |
BERConstants.SEQUENCE); |
253 |
} |
} |
254 |
} |
} |
255 |
bind.append (ctls.toByteArray (), BERConstants.CONTEXT); |
bind.append(ctls.toByteArray(), BERConstants.CONTEXT); |
256 |
// Write request |
// Write request |
257 |
write (id, BIND_REQUEST, bind.toByteArray ()); |
write(id, BIND_REQUEST, bind.toByteArray()); |
258 |
// Read response |
// Read response |
259 |
BERDecoder response = read (id); |
BERDecoder response = read(id); |
260 |
BERDecoder resultSequence = response.parseSequence (BIND_RESPONSE); |
BERDecoder resultSequence = response.parseSequence(BIND_RESPONSE); |
261 |
LDAPResult result = parseResult (resultSequence); |
LDAPResult result = parseResult(resultSequence); |
262 |
if (resultSequence.available ()) |
if (resultSequence.available()) |
263 |
{ |
{ |
264 |
byte[] serverCreds = resultSequence.parseOctetString (); |
byte[] serverCreds = resultSequence.parseOctetString(); |
265 |
// TODO |
// TODO |
266 |
} |
} |
267 |
// TODO response controls |
// TODO response controls |
273 |
* has no more requests to issue and will terminate the connection. After |
* has no more requests to issue and will terminate the connection. After |
274 |
* invoking this method, no further methods may be invoked. |
* invoking this method, no further methods may be invoked. |
275 |
*/ |
*/ |
276 |
public void unbind () |
public void unbind() |
277 |
throws IOException |
throws IOException |
278 |
{ |
{ |
279 |
int id = messageId++; |
int id = messageId++; |
280 |
boolean utf8 = (version == 3); |
boolean utf8 = (version == 3); |
281 |
BEREncoder unbind = new BEREncoder (utf8); |
BEREncoder unbind = new BEREncoder(utf8); |
282 |
unbind.appendNull (); |
unbind.appendNull(); |
283 |
write (id, UNBIND_REQUEST, unbind.toByteArray ()); |
write(id, UNBIND_REQUEST, unbind.toByteArray()); |
284 |
// Close socket |
// Close socket |
285 |
socket.close (); |
socket.close(); |
286 |
} |
} |
287 |
|
|
288 |
/** |
/** |
296 |
* restriction |
* restriction |
297 |
* @param timeLimit the maximum time in seconds permitted for the search, |
* @param timeLimit the maximum time in seconds permitted for the search, |
298 |
* or 0 for no restriction |
* or 0 for no restriction |
299 |
* @param typesOnly whether to return only attribute types (true) or both |
* @param typesOnly whether to return only attribute types(true) or both |
300 |
* attribute types and values (false) |
* attribute types and values(false) |
301 |
* @param filter the search filter in RFC2254 format |
* @param filter the search filter in RFC2254 format |
302 |
* @param attributes the IDs of the attributes to return |
* @param attributes the IDs of the attributes to return |
303 |
* @param controls the request controls |
* @param controls the request controls |
304 |
* @param handler the result handler to receive notification of results |
* @param handler the result handler to receive notification of results |
305 |
* @return the LDAP result |
* @return the LDAP result |
306 |
*/ |
*/ |
307 |
public LDAPResult search (String name, int scope, int derefAliases, |
public LDAPResult search(String name, int scope, int derefAliases, |
308 |
int sizeLimit, int timeLimit, |
int sizeLimit, int timeLimit, |
309 |
boolean typesOnly, String filter, |
boolean typesOnly, String filter, |
310 |
String[] attributes, Control[] controls, |
String[] attributes, Control[] controls, |
311 |
ResultHandler handler) |
ResultHandler handler) |
312 |
throws IOException |
throws IOException |
313 |
{ |
{ |
314 |
if (filter == null || filter.length () == 0) |
if (filter == null || filter.length() == 0) |
315 |
{ |
{ |
316 |
filter = "(objectClass=*)"; |
filter = "(objectClass=*)"; |
317 |
} |
} |
318 |
int id = messageId++; |
int id = messageId++; |
319 |
boolean utf8 = (version == 3); |
boolean utf8 = (version == 3); |
320 |
BEREncoder search = new BEREncoder (utf8); |
BEREncoder search = new BEREncoder(utf8); |
321 |
search.append (name); |
search.append(name); |
322 |
search.append (scope, BERConstants.ENUMERATED); |
search.append(scope, BERConstants.ENUMERATED); |
323 |
search.append (derefAliases, BERConstants.ENUMERATED); |
search.append(derefAliases, BERConstants.ENUMERATED); |
324 |
search.append (sizeLimit); |
search.append(sizeLimit); |
325 |
search.append (timeLimit); |
search.append(timeLimit); |
326 |
search.append (typesOnly); |
search.append(typesOnly); |
327 |
search.appendFilter (filter); |
search.appendFilter(filter); |
328 |
BEREncoder attributeSequence = new BEREncoder (utf8); |
BEREncoder attributeSequence = new BEREncoder(utf8); |
329 |
if (attributes != null) |
if (attributes != null) |
330 |
{ |
{ |
331 |
for (int i = 0; i < attributes.length; i++) |
for (int i = 0; i < attributes.length; i++) |
332 |
{ |
{ |
333 |
attributeSequence.append (attributes[i]); |
attributeSequence.append(attributes[i]); |
334 |
} |
} |
335 |
} |
} |
336 |
search.append (attributeSequence.toByteArray (), BERConstants.SEQUENCE); |
search.append(attributeSequence.toByteArray(), BERConstants.SEQUENCE); |
337 |
// Request controls |
// Request controls |
338 |
BEREncoder ctls = new BEREncoder (utf8); |
BEREncoder ctls = new BEREncoder(utf8); |
339 |
if (controls != null) |
if (controls != null) |
340 |
{ |
{ |
341 |
for (int i = 0; i < controls.length; i++) |
for (int i = 0; i < controls.length; i++) |
342 |
{ |
{ |
343 |
ctls.append (controlSequence (controls[i], utf8), |
ctls.append(controlSequence(controls[i], utf8), |
344 |
BERConstants.SEQUENCE); |
BERConstants.SEQUENCE); |
345 |
} |
} |
346 |
} |
} |
347 |
search.append (ctls.toByteArray (), BERConstants.SEQUENCE); |
search.append(ctls.toByteArray(), BERConstants.SEQUENCE); |
348 |
// Write request |
// Write request |
349 |
write (id, SEARCH_REQUEST, search.toByteArray ()); |
write(id, SEARCH_REQUEST, search.toByteArray()); |
350 |
do |
do |
351 |
{ |
{ |
352 |
BERDecoder response = read (id); |
BERDecoder response = read(id); |
353 |
int code = response.parseType (); |
int code = response.parseType(); |
354 |
switch (code) |
switch (code) |
355 |
{ |
{ |
356 |
case SEARCH_RESULT: |
case SEARCH_RESULT: |
357 |
BERDecoder entry = response.parseSequence (code); |
BERDecoder entry = response.parseSequence(code); |
358 |
String objectName = entry.parseString (); |
String objectName = entry.parseString(); |
359 |
BERDecoder attributeSeq = entry.parseSequence (0x30); |
BERDecoder attributeSeq = entry.parseSequence(0x30); |
360 |
Map attrs = new TreeMap (); |
Map attrs = new TreeMap(); |
361 |
while (attributeSeq.available ()) |
while (attributeSeq.available()) |
362 |
{ |
{ |
363 |
BERDecoder attribute = attributeSeq.parseSequence (0x30); |
BERDecoder attribute = attributeSeq.parseSequence(0x30); |
364 |
String type = attribute.parseString (); |
String type = attribute.parseString(); |
365 |
BERDecoder values = attribute.parseSet (0x31); |
BERDecoder values = attribute.parseSet(0x31); |
366 |
List acc = new ArrayList (); |
List acc = new ArrayList(); |
367 |
while (values.available ()) |
while (values.available()) |
368 |
{ |
{ |
369 |
int valueType = values.parseType (); |
int valueType = values.parseType(); |
370 |
switch (valueType) |
switch (valueType) |
371 |
{ |
{ |
372 |
case BERConstants.BOOLEAN: |
case BERConstants.BOOLEAN: |
373 |
acc.add (Boolean.valueOf (values.parseBoolean ())); |
acc.add(Boolean.valueOf(values.parseBoolean())); |
374 |
break; |
break; |
375 |
case BERConstants.INTEGER: |
case BERConstants.INTEGER: |
376 |
case BERConstants.ENUMERATED: |
case BERConstants.ENUMERATED: |
377 |
acc.add (new Integer (values.parseInt ())); |
acc.add(new Integer(values.parseInt())); |
378 |
break; |
break; |
379 |
// TODO float |
// TODO float |
380 |
case BERConstants.UTF8_STRING: |
case BERConstants.UTF8_STRING: |
381 |
acc.add (values.parseString ()); |
acc.add(values.parseString()); |
382 |
break; |
break; |
383 |
case BERConstants.OCTET_STRING: |
case BERConstants.OCTET_STRING: |
384 |
acc.add (values.parseOctetString ()); |
acc.add(values.parseOctetString()); |
385 |
break; |
break; |
386 |
} |
} |
387 |
} |
} |
388 |
attrs.put (type, acc); |
attrs.put(type, acc); |
389 |
} |
} |
390 |
handler.searchResultEntry (objectName, attrs); |
handler.searchResultEntry(objectName, attrs); |
391 |
break; |
break; |
392 |
case SEARCH_REFERENCE: |
case SEARCH_REFERENCE: |
393 |
List acc = new ArrayList (); |
List acc = new ArrayList(); |
394 |
BERDecoder urls = response.parseSequence (code); |
BERDecoder urls = response.parseSequence(code); |
395 |
while (urls.available ()) |
while (urls.available()) |
396 |
{ |
{ |
397 |
acc.add (urls.parseString ()); |
acc.add(urls.parseString()); |
398 |
} |
} |
399 |
handler.searchResultReference (acc); |
handler.searchResultReference(acc); |
400 |
break; |
break; |
401 |
case SEARCH_RESULT_DONE: |
case SEARCH_RESULT_DONE: |
402 |
return parseResult (response.parseSequence (code)); |
return parseResult(response.parseSequence(code)); |
403 |
default: |
default: |
404 |
throw new ProtocolException ("Unexpected response: " + code); |
throw new ProtocolException("Unexpected response: " + code); |
405 |
} |
} |
406 |
} |
} |
407 |
while (true); |
while (true); |
409 |
|
|
410 |
/** |
/** |
411 |
* Issues a modify request. |
* Issues a modify request. |
412 |
* @param name the LDAP DN of the object to be modified (alias |
* @param name the LDAP DN of the object to be modified(alias |
413 |
* dereferencing will not be performed) |
* dereferencing will not be performed) |
414 |
* @param modifications a sequence of modifications to be executed |
* @param modifications a sequence of modifications to be executed |
415 |
* to be executed |
* to be executed |
416 |
* @see Modification |
* @see Modification |
417 |
*/ |
*/ |
418 |
public LDAPResult modify (String name, final Modification[] modifications) |
public LDAPResult modify(String name, final Modification[] modifications) |
419 |
throws IOException |
throws IOException |
420 |
{ |
{ |
421 |
int id = messageId++; |
int id = messageId++; |
422 |
boolean utf8 = (version == 3); |
boolean utf8 = (version == 3); |
423 |
BEREncoder modify = new BEREncoder (utf8); |
BEREncoder modify = new BEREncoder(utf8); |
424 |
modify.append (name); |
modify.append(name); |
425 |
BEREncoder modSeq = new BEREncoder (utf8); |
BEREncoder modSeq = new BEREncoder(utf8); |
426 |
for (int i = 0; i < modifications.length; i++) |
for (int i = 0; i < modifications.length; i++) |
427 |
{ |
{ |
428 |
BEREncoder mod = new BEREncoder (utf8); |
BEREncoder mod = new BEREncoder(utf8); |
429 |
mod.append (modifications[i].operation); |
mod.append(modifications[i].operation); |
430 |
BEREncoder typeAndValues = new BEREncoder (utf8); |
BEREncoder typeAndValues = new BEREncoder(utf8); |
431 |
typeAndValues.append (modifications[i].type); |
typeAndValues.append(modifications[i].type); |
432 |
BEREncoder values = new BEREncoder (utf8); |
BEREncoder values = new BEREncoder(utf8); |
433 |
appendValues (values, modifications[i].values); |
appendValues(values, modifications[i].values); |
434 |
typeAndValues.append (values.toByteArray (), BERConstants.SET); |
typeAndValues.append(values.toByteArray(), BERConstants.SET); |
435 |
mod.append (typeAndValues.toByteArray (), BERConstants.SEQUENCE); |
mod.append(typeAndValues.toByteArray(), BERConstants.SEQUENCE); |
436 |
modSeq.append (mod.toByteArray (), BERConstants.SEQUENCE); |
modSeq.append(mod.toByteArray(), BERConstants.SEQUENCE); |
437 |
} |
} |
438 |
modify.append (modSeq.toByteArray (), BERConstants.SEQUENCE); |
modify.append(modSeq.toByteArray(), BERConstants.SEQUENCE); |
439 |
// Write request |
// Write request |
440 |
write (id, MODIFY_REQUEST, modify.toByteArray ()); |
write(id, MODIFY_REQUEST, modify.toByteArray()); |
441 |
// Read response |
// Read response |
442 |
BERDecoder response = read (id); |
BERDecoder response = read(id); |
443 |
BERDecoder resultSequence = response.parseSequence (MODIFY_RESPONSE); |
BERDecoder resultSequence = response.parseSequence(MODIFY_RESPONSE); |
444 |
LDAPResult result = parseResult (resultSequence); |
LDAPResult result = parseResult(resultSequence); |
445 |
return result; |
return result; |
446 |
} |
} |
447 |
|
|
450 |
* @param name the LDAP DN of the new entry |
* @param name the LDAP DN of the new entry |
451 |
* @param attributes a sequence of attributes to assign to the new entry |
* @param attributes a sequence of attributes to assign to the new entry |
452 |
*/ |
*/ |
453 |
public LDAPResult add (String name, AttributeValues[] attributes) |
public LDAPResult add(String name, AttributeValues[] attributes) |
454 |
throws IOException |
throws IOException |
455 |
{ |
{ |
456 |
int id = messageId++; |
int id = messageId++; |
457 |
boolean utf8 = (version == 3); |
boolean utf8 = (version == 3); |
458 |
BEREncoder add = new BEREncoder (utf8); |
BEREncoder add = new BEREncoder(utf8); |
459 |
add.append (name); |
add.append(name); |
460 |
BEREncoder attrSeq = new BEREncoder (utf8); |
BEREncoder attrSeq = new BEREncoder(utf8); |
461 |
for (int i = 0; i < attributes.length; i++) |
for (int i = 0; i < attributes.length; i++) |
462 |
{ |
{ |
463 |
BEREncoder attr = new BEREncoder (utf8); |
BEREncoder attr = new BEREncoder(utf8); |
464 |
attr.append (attributes[i].type); |
attr.append(attributes[i].type); |
465 |
BEREncoder values = new BEREncoder (utf8); |
BEREncoder values = new BEREncoder(utf8); |
466 |
appendValues (values, attributes[i].values); |
appendValues(values, attributes[i].values); |
467 |
attr.append (values.toByteArray (), BERConstants.SET); |
attr.append(values.toByteArray(), BERConstants.SET); |
468 |
attrSeq.append (attr.toByteArray (), BERConstants.SEQUENCE); |
attrSeq.append(attr.toByteArray(), BERConstants.SEQUENCE); |
469 |
} |
} |
470 |
add.append (attrSeq.toByteArray (), BERConstants.SEQUENCE); |
add.append(attrSeq.toByteArray(), BERConstants.SEQUENCE); |
471 |
// Write request |
// Write request |
472 |
write (id, ADD_REQUEST, add.toByteArray ()); |
write(id, ADD_REQUEST, add.toByteArray()); |
473 |
// Read response |
// Read response |
474 |
BERDecoder response = read (id); |
BERDecoder response = read(id); |
475 |
BERDecoder resultSequence = response.parseSequence (ADD_RESPONSE); |
BERDecoder resultSequence = response.parseSequence(ADD_RESPONSE); |
476 |
LDAPResult result = parseResult (resultSequence); |
LDAPResult result = parseResult(resultSequence); |
477 |
return result; |
return result; |
478 |
} |
} |
479 |
|
|
481 |
* Requests the removal of an entry from the directory. |
* Requests the removal of an entry from the directory. |
482 |
* @param name the LDAP DN of the entry to remove |
* @param name the LDAP DN of the entry to remove |
483 |
*/ |
*/ |
484 |
public LDAPResult delete (String name) |
public LDAPResult delete(String name) |
485 |
throws IOException |
throws IOException |
486 |
{ |
{ |
487 |
int id = messageId++; |
int id = messageId++; |
488 |
boolean utf8 = (version == 3); |
boolean utf8 = (version == 3); |
489 |
BEREncoder del = new BEREncoder (utf8); |
BEREncoder del = new BEREncoder(utf8); |
490 |
del.append (name); |
del.append(name); |
491 |
// Write request |
// Write request |
492 |
write (id, DELETE_REQUEST, del.toByteArray ()); |
write(id, DELETE_REQUEST, del.toByteArray()); |
493 |
// Read response |
// Read response |
494 |
BERDecoder response = read (id); |
BERDecoder response = read(id); |
495 |
int code = response.parseType (); |
int code = response.parseType(); |
496 |
if (code != DELETE_RESPONSE) |
if (code != DELETE_RESPONSE) |
497 |
{ |
{ |
498 |
throw new ProtocolException ("Unexpected response type: " + |
throw new ProtocolException("Unexpected response type: " + |
499 |
code); |
code); |
500 |
} |
} |
501 |
BERDecoder resultSequence = response.parseSequence (); |
BERDecoder resultSequence = response.parseSequence(); |
502 |
LDAPResult result = parseResult (resultSequence); |
LDAPResult result = parseResult(resultSequence); |
503 |
return result; |
return result; |
504 |
} |
} |
505 |
|
|
506 |
/** |
/** |
507 |
* Changes the leftmost (least significant) component of the name of an |
* Changes the leftmost(least significant) component of the name of an |
508 |
* entry in the directory, or move a subtree of entries to a new location |
* entry in the directory, or move a subtree of entries to a new location |
509 |
* in the directory. |
* in the directory. |
510 |
* @param name the LDAP DN of the entry to be changed |
* @param name the LDAP DN of the entry to be changed |
515 |
* @param newSuperior if non-null, the DN of the entry to become the |
* @param newSuperior if non-null, the DN of the entry to become the |
516 |
* immediate superior of the existing entry |
* immediate superior of the existing entry |
517 |
*/ |
*/ |
518 |
public LDAPResult modifyDN (String name, String newRDN, |
public LDAPResult modifyDN(String name, String newRDN, |
519 |
boolean deleteOldRDN, String newSuperior) |
boolean deleteOldRDN, String newSuperior) |
520 |
throws IOException |
throws IOException |
521 |
{ |
{ |
522 |
int id = messageId++; |
int id = messageId++; |
523 |
boolean utf8 = (version == 3); |
boolean utf8 = (version == 3); |
524 |
BEREncoder modifyDN = new BEREncoder (utf8); |
BEREncoder modifyDN = new BEREncoder(utf8); |
525 |
modifyDN.append (name); |
modifyDN.append(name); |
526 |
modifyDN.append (newRDN); |
modifyDN.append(newRDN); |
527 |
modifyDN.append (deleteOldRDN); |
modifyDN.append(deleteOldRDN); |
528 |
if (newSuperior != null) |
if (newSuperior != null) |
529 |
{ |
{ |
530 |
modifyDN.append (newSuperior); |
modifyDN.append(newSuperior); |
531 |
} |
} |
532 |
// Write request |
// Write request |
533 |
write (id, MODIFY_DN_REQUEST, modifyDN.toByteArray ()); |
write(id, MODIFY_DN_REQUEST, modifyDN.toByteArray()); |
534 |
// Read response |
// Read response |
535 |
BERDecoder response = read (id); |
BERDecoder response = read(id); |
536 |
BERDecoder resultSequence = response.parseSequence (MODIFY_DN_RESPONSE); |
BERDecoder resultSequence = response.parseSequence(MODIFY_DN_RESPONSE); |
537 |
LDAPResult result = parseResult (resultSequence); |
LDAPResult result = parseResult(resultSequence); |
538 |
return result; |
return result; |
539 |
} |
} |
540 |
|
|
549 |
/** |
/** |
550 |
* Appends the specified set of values to the given encoder. |
* Appends the specified set of values to the given encoder. |
551 |
*/ |
*/ |
552 |
void appendValues (BEREncoder encoder, Set values) |
void appendValues(BEREncoder encoder, Set values) |
553 |
throws BERException |
throws BERException |
554 |
{ |
{ |
555 |
if (values != null) |
if (values != null) |
556 |
{ |
{ |
557 |
for (Iterator i = values.iterator (); i.hasNext (); ) |
for (Iterator i = values.iterator(); i.hasNext(); ) |
558 |
{ |
{ |
559 |
Object value = i.next (); |
Object value = i.next(); |
560 |
if (value == null) |
if (value == null) |
561 |
{ |
{ |
562 |
encoder.appendNull (); |
encoder.appendNull(); |
563 |
} |
} |
564 |
else if (value instanceof String) |
else if (value instanceof String) |
565 |
{ |
{ |
566 |
encoder.append ((String) value); |
encoder.append((String) value); |
567 |
} |
} |
568 |
else if (value instanceof Integer) |
else if (value instanceof Integer) |
569 |
{ |
{ |
570 |
encoder.append (((Integer) value).intValue ()); |
encoder.append(((Integer) value).intValue()); |
571 |
} |
} |
572 |
else if (value instanceof Boolean) |
else if (value instanceof Boolean) |
573 |
{ |
{ |
574 |
encoder.append (((Boolean) value).booleanValue ()); |
encoder.append(((Boolean) value).booleanValue()); |
575 |
} |
} |
576 |
else if (value instanceof byte[]) |
else if (value instanceof byte[]) |
577 |
{ |
{ |
578 |
encoder.append ((byte[]) value); |
encoder.append((byte[]) value); |
579 |
} |
} |
580 |
// TODO float |
// TODO float |
581 |
else |
else |
582 |
{ |
{ |
583 |
throw new ClassCastException (value.getClass ().getName ()); |
throw new ClassCastException(value.getClass().getName()); |
584 |
} |
} |
585 |
} |
} |
586 |
} |
} |
589 |
/** |
/** |
590 |
* Encode a control. |
* Encode a control. |
591 |
*/ |
*/ |
592 |
byte[] controlSequence (final Control control, boolean utf8) |
byte[] controlSequence(final Control control, boolean utf8) |
593 |
throws IOException |
throws IOException |
594 |
{ |
{ |
595 |
BEREncoder encoder = new BEREncoder (utf8); |
BEREncoder encoder = new BEREncoder(utf8); |
596 |
encoder.append (control.getID ()); |
encoder.append(control.getID()); |
597 |
if (control.isCritical ()) |
if (control.isCritical()) |
598 |
{ |
{ |
599 |
encoder.append (true); |
encoder.append(true); |
600 |
} |
} |
601 |
return encoder.toByteArray (); |
return encoder.toByteArray(); |
602 |
} |
} |
603 |
|
|
604 |
/** |
/** |
605 |
* Parse a response into an LDAP result object. |
* Parse a response into an LDAP result object. |
606 |
*/ |
*/ |
607 |
LDAPResult parseResult (BERDecoder response) |
LDAPResult parseResult(BERDecoder response) |
608 |
throws IOException |
throws IOException |
609 |
{ |
{ |
610 |
int status = response.parseInt (); |
int status = response.parseInt(); |
611 |
String matchingDN = response.parseString (); |
String matchingDN = response.parseString(); |
612 |
String errorMessage = response.parseString (); |
String errorMessage = response.parseString(); |
613 |
String[] referrals = null; |
String[] referrals = null; |
614 |
if (response.available ()) |
if (response.available()) |
615 |
{ |
{ |
616 |
int type = response.parseType (); |
int type = response.parseType(); |
617 |
if (type == BERConstants.SEQUENCE) |
if (type == BERConstants.SEQUENCE) |
618 |
{ |
{ |
619 |
ArrayList list = new ArrayList (); |
ArrayList list = new ArrayList(); |
620 |
BERDecoder sequence = response.parseSequence (); |
BERDecoder sequence = response.parseSequence(); |
621 |
type = sequence.parseType (); |
type = sequence.parseType(); |
622 |
while (type != -1) |
while (type != -1) |
623 |
{ |
{ |
624 |
list.add (sequence.parseString ()); |
list.add(sequence.parseString()); |
625 |
} |
} |
626 |
referrals = new String[list.size ()]; |
referrals = new String[list.size()]; |
627 |
list.toArray (referrals); |
list.toArray(referrals); |
628 |
} |
} |
629 |
} |
} |
630 |
return new LDAPResult (status, matchingDN, errorMessage, referrals); |
return new LDAPResult(status, matchingDN, errorMessage, referrals); |
631 |
} |
} |
632 |
|
|
633 |
/** |
/** |
636 |
* @param code the operation code |
* @param code the operation code |
637 |
* @param request the request body |
* @param request the request body |
638 |
*/ |
*/ |
639 |
void write (int id, int code, byte[] request) |
void write(int id, int code, byte[] request) |
640 |
throws IOException |
throws IOException |
641 |
{ |
{ |
642 |
boolean utf8 = (version == 3); |
boolean utf8 = (version == 3); |
643 |
BEREncoder envelope = new BEREncoder (utf8); |
BEREncoder envelope = new BEREncoder(utf8); |
644 |
envelope.append (id); |
envelope.append(id); |
645 |
envelope.append (request, code); |
envelope.append(request, code); |
646 |
BEREncoder message = new BEREncoder (utf8); |
BEREncoder message = new BEREncoder(utf8); |
647 |
message.append (envelope.toByteArray (), MESSAGE); |
message.append(envelope.toByteArray(), MESSAGE); |
648 |
byte[] toSend = message.toByteArray (); |
byte[] toSend = message.toByteArray(); |
649 |
// Write to socket |
// Write to socket |
650 |
out.write (toSend); |
out.write(toSend); |
651 |
out.flush (); |
out.flush(); |
652 |
} |
} |
653 |
|
|
654 |
/** |
/** |
656 |
* @param id the message ID |
* @param id the message ID |
657 |
* @return a BERDecoder for the content of the message |
* @return a BERDecoder for the content of the message |
658 |
*/ |
*/ |
659 |
BERDecoder read (int id) |
BERDecoder read(int id) |
660 |
throws IOException |
throws IOException |
661 |
{ |
{ |
662 |
// Check for an already received async response |
// Check for an already received async response |
663 |
Integer key = new Integer (id); |
Integer key = new Integer(id); |
664 |
List responses = (List) asyncResponses.get (key); |
List responses = (List) asyncResponses.get(key); |
665 |
if (responses != null) |
if (responses != null) |
666 |
{ |
{ |
667 |
BERDecoder response = (BERDecoder) responses.remove (0); |
BERDecoder response = (BERDecoder) responses.remove(0); |
668 |
if (responses.size () == 0) |
if (responses.size() == 0) |
669 |
{ |
{ |
670 |
asyncResponses.remove (key); |
asyncResponses.remove(key); |
671 |
} |
} |
672 |
return response; |
return response; |
673 |
} |
} |
674 |
do |
do |
675 |
{ |
{ |
676 |
// Read LDAP message |
// Read LDAP message |
677 |
byte[] bytes = readMessage (); |
byte[] bytes = readMessage(); |
678 |
boolean utf8 = (version == 3); |
boolean utf8 = (version == 3); |
679 |
BERDecoder message = new BERDecoder (bytes, utf8); |
BERDecoder message = new BERDecoder(bytes, utf8); |
680 |
message = message.parseSequence (MESSAGE); |
message = message.parseSequence(MESSAGE); |
681 |
// Check message ID |
// Check message ID |
682 |
int msgId = message.parseInt (); |
int msgId = message.parseInt(); |
683 |
if (msgId == id) |
if (msgId == id) |
684 |
{ |
{ |
685 |
return message; |
return message; |
687 |
else |
else |
688 |
{ |
{ |
689 |
// Store this message for later processing |
// Store this message for later processing |
690 |
key = new Integer (msgId); |
key = new Integer(msgId); |
691 |
responses = (List) asyncResponses.get (key); |
responses = (List) asyncResponses.get(key); |
692 |
if (responses == null) |
if (responses == null) |
693 |
{ |
{ |
694 |
responses = new ArrayList (); |
responses = new ArrayList(); |
695 |
asyncResponses.put (key, responses); |
asyncResponses.put(key, responses); |
696 |
} |
} |
697 |
responses.add (message); |
responses.add(message); |
698 |
} |
} |
699 |
} |
} |
700 |
while (true); |
while (true); |
703 |
/** |
/** |
704 |
* Read an LDAP message. |
* Read an LDAP message. |
705 |
*/ |
*/ |
706 |
byte[] readMessage () |
byte[] readMessage() |
707 |
throws IOException |
throws IOException |
708 |
{ |
{ |
709 |
// Peek at the length part of the BER encoding to determine the length |
// Peek at the length part of the BER encoding to determine the length |
711 |
// TODO normalize this with functionality in BERDecoder |
// TODO normalize this with functionality in BERDecoder |
712 |
byte[] header = new byte[6]; |
byte[] header = new byte[6]; |
713 |
int offset = 0; |
int offset = 0; |
714 |
header[offset++] = (byte) readByte (); // type |
header[offset++] = (byte) readByte(); // type |
715 |
int len = readByte (); // length 0 |
int len = readByte(); // length 0 |
716 |
header[offset++] = (byte) len; |
header[offset++] = (byte) len; |
717 |
if ((len & 0x80) != 0) |
if ((len & 0x80) != 0) |
718 |
{ |
{ |
719 |
int lsize = len - 0x80; |
int lsize = len - 0x80; |
720 |
if (lsize > 4) |
if (lsize > 4) |
721 |
{ |
{ |
722 |
throw new BERException ("Data too long: " + lsize); |
throw new BERException("Data too long: " + lsize); |
723 |
} |
} |
724 |
len = 0; |
len = 0; |
725 |
for (int i = 0; i < lsize; i++) |
for (int i = 0; i < lsize; i++) |
726 |
{ |
{ |
727 |
int c = readByte (); |
int c = readByte(); |
728 |
header[offset++] = (byte) c; |
header[offset++] = (byte) c; |
729 |
len = (len << 8) + c; |
len = (len << 8) + c; |
730 |
} |
} |
731 |
} |
} |
732 |
// Allocate message array |
// Allocate message array |
733 |
byte[] message = new byte[offset + len]; |
byte[] message = new byte[offset + len]; |
734 |
System.arraycopy (header, 0, message, 0, offset); |
System.arraycopy(header, 0, message, 0, offset); |
735 |
if (len == 0) |
if (len == 0) |
736 |
{ |
{ |
737 |
return message; |
return message; |
740 |
// Read message content |
// Read message content |
741 |
do |
do |
742 |
{ |
{ |
743 |
int l = in.read (message, offset, len); |
int l = in.read(message, offset, len); |
744 |
if (l == -1) |
if (l == -1) |
745 |
{ |
{ |
746 |
throw new IOException ("EOF"); |
throw new IOException("EOF"); |
747 |
} |
} |
748 |
offset += l; |
offset += l; |
749 |
len -= l; |
len -= l; |
755 |
/** |
/** |
756 |
* Read a single byte. |
* Read a single byte. |
757 |
*/ |
*/ |
758 |
int readByte () |
int readByte() |
759 |
throws IOException |
throws IOException |
760 |
{ |
{ |
761 |
int ret = in.read (); |
int ret = in.read(); |
762 |
if (ret == -1) |
if (ret == -1) |
763 |
{ |
{ |
764 |
throw new IOException ("EOF"); |
throw new IOException("EOF"); |
765 |
} |
} |
766 |
return ret & 0xff; |
return ret & 0xff; |
767 |
} |
} |
768 |
|
|
769 |
} |
} |
770 |
|
|