001 /*
002 * CDDL HEADER START
003 *
004 * The contents of this file are subject to the terms of the
005 * Common Development and Distribution License, Version 1.0 only
006 * (the "License"). You may not use this file except in compliance
007 * with the License.
008 *
009 * You can obtain a copy of the license at
010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012 * See the License for the specific language governing permissions
013 * and limitations under the License.
014 *
015 * When distributing Covered Code, include this CDDL HEADER in each
016 * file and include the License file at
017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable,
018 * add the following below this CDDL HEADER, with the fields enclosed
019 * by brackets "[]" replaced with your own identifying information:
020 * Portions Copyright [yyyy] [name of copyright owner]
021 *
022 * CDDL HEADER END
023 *
024 *
025 * Copyright 2006-2008 Sun Microsystems, Inc.
026 */
027 package org.opends.server.protocols.ldap;
028 import org.opends.messages.Message;
029
030
031
032 import java.util.ArrayList;
033 import java.util.Iterator;
034 import java.util.List;
035
036 import org.opends.server.protocols.asn1.ASN1Element;
037 import org.opends.server.protocols.asn1.ASN1Enumerated;
038 import org.opends.server.protocols.asn1.ASN1OctetString;
039 import org.opends.server.protocols.asn1.ASN1Sequence;
040 import org.opends.server.types.DebugLogLevel;
041 import org.opends.server.types.DN;
042 import org.opends.server.types.LDAPException;
043
044 import static org.opends.server.loggers.debug.DebugLogger.*;
045 import org.opends.server.loggers.debug.DebugTracer;
046 import static org.opends.messages.ProtocolMessages.*;
047 import static org.opends.server.protocols.ldap.LDAPConstants.*;
048 import static org.opends.server.protocols.ldap.LDAPResultCode.*;
049 import static org.opends.server.util.ServerConstants.*;
050
051
052
053 /**
054 * This class defines the structures and methods for an LDAP extended response
055 * protocol op, which is used to provide information about the result of
056 * processing a extended request.
057 */
058 public class ExtendedResponseProtocolOp
059 extends ProtocolOp
060 {
061 /**
062 * The tracer object for the debug logger.
063 */
064 private static final DebugTracer TRACER = getTracer();
065
066 // The value for this extended response.
067 private ASN1OctetString value;
068
069 // The matched DN for this response.
070 private DN matchedDN;
071
072 // The result code for this response.
073 private int resultCode;
074
075 // The set of referral URLs for this response.
076 private List<String> referralURLs;
077
078 // The error message for this response.
079 private Message errorMessage;
080
081 // The OID for this extended response.
082 private String oid;
083
084
085
086 /**
087 * Creates a new extended response protocol op with the provided result code.
088 *
089 * @param resultCode The result code for this response.
090 */
091 public ExtendedResponseProtocolOp(int resultCode)
092 {
093 this.resultCode = resultCode;
094
095 errorMessage = null;
096 matchedDN = null;
097 referralURLs = null;
098 oid = null;
099 value = null;
100 }
101
102
103
104 /**
105 * Creates a new extended response protocol op with the provided result code
106 * and error message.
107 *
108 * @param resultCode The result code for this response.
109 * @param errorMessage The error message for this response.
110 */
111 public ExtendedResponseProtocolOp(int resultCode, Message errorMessage)
112 {
113 this.resultCode = resultCode;
114 this.errorMessage = errorMessage;
115
116 matchedDN = null;
117 referralURLs = null;
118 oid = null;
119 value = null;
120 }
121
122
123
124 /**
125 * Creates a new extended response protocol op with the provided information.
126 *
127 * @param resultCode The result code for this response.
128 * @param errorMessage The error message for this response.
129 * @param matchedDN The matched DN for this response.
130 * @param referralURLs The referral URLs for this response.
131 */
132 public ExtendedResponseProtocolOp(int resultCode, Message errorMessage,
133 DN matchedDN, List<String> referralURLs)
134 {
135 this.resultCode = resultCode;
136 this.errorMessage = errorMessage;
137 this.matchedDN = matchedDN;
138 this.referralURLs = referralURLs;
139
140 oid = null;
141 value = null;
142 }
143
144
145
146 /**
147 * Creates a new extended response protocol op with the provided information.
148 *
149 * @param resultCode The result code for this response.
150 * @param errorMessage The error message for this response.
151 * @param matchedDN The matched DN for this response.
152 * @param referralURLs The referral URLs for this response.
153 * @param oid The OID for this extended response.
154 * @param value The value for this extended response.
155 */
156 public ExtendedResponseProtocolOp(int resultCode, Message errorMessage,
157 DN matchedDN, List<String> referralURLs,
158 String oid, ASN1OctetString value)
159 {
160 this.resultCode = resultCode;
161 this.errorMessage = errorMessage;
162 this.matchedDN = matchedDN;
163 this.referralURLs = referralURLs;
164 this.oid = oid;
165 this.value = value;
166 }
167
168
169
170 /**
171 * Retrieves the result code for this response.
172 *
173 * @return The result code for this response.
174 */
175 public int getResultCode()
176 {
177 return resultCode;
178 }
179
180
181
182 /**
183 * Specifies the result code for this response.
184 *
185 * @param resultCode The result code for this response.
186 */
187 public void setResultCode(int resultCode)
188 {
189 this.resultCode = resultCode;
190 }
191
192
193
194 /**
195 * Retrieves the error message for this response.
196 *
197 * @return The error message for this response, or <CODE>null</CODE> if none
198 * is available.
199 */
200 public Message getErrorMessage()
201 {
202 return errorMessage;
203 }
204
205
206
207 /**
208 * Specifies the error message for this response.
209 *
210 * @param errorMessage The error message for this response.
211 */
212 public void setErrorMessage(Message errorMessage)
213 {
214 this.errorMessage = errorMessage;
215 }
216
217
218
219 /**
220 * Retrieves the matched DN for this response.
221 *
222 * @return The matched DN for this response, or <CODE>null</CODE> if none is
223 * available.
224 */
225 public DN getMatchedDN()
226 {
227 return matchedDN;
228 }
229
230
231
232 /**
233 * Specifies the matched DN for this response.
234 *
235 * @param matchedDN The matched DN for this response.
236 */
237 public void setMatchedDN(DN matchedDN)
238 {
239 this.matchedDN = matchedDN;
240 }
241
242
243
244 /**
245 * Retrieves the set of referral URLs for this response.
246 *
247 * @return The set of referral URLs for this response, or <CODE>null</CODE>
248 * if none are available.
249 */
250 public List<String> getReferralURLs()
251 {
252 return referralURLs;
253 }
254
255
256
257 /**
258 * Specifies the set of referral URLs for this response.
259 *
260 * @param referralURLs The set of referral URLs for this response.
261 */
262 public void setReferralURLs(List<String> referralURLs)
263 {
264 this.referralURLs = referralURLs;
265 }
266
267
268
269 /**
270 * Retrieves the OID for this extended response.
271 *
272 * @return The OID for this extended response, or <CODE>null</CODE> if none
273 * was provided.
274 */
275 public String getOID()
276 {
277 return oid;
278 }
279
280
281
282 /**
283 * Specifies the OID for this extended response.
284 *
285 * @param oid The OID for this extended response.
286 */
287 public void setOID(String oid)
288 {
289 this.oid = oid;
290 }
291
292
293
294 /**
295 * Retrieves the value for this extended response.
296 *
297 * @return The value for this extended response, or <CODE>null</CODE> if none
298 * was provided.
299 */
300 public ASN1OctetString getValue()
301 {
302 return value;
303 }
304
305
306
307 /**
308 * Specifies the value for this extended response.
309 *
310 * @param value The value for this extended response.
311 */
312 public void setValue(ASN1OctetString value)
313 {
314 this.value = value;
315 }
316
317
318
319 /**
320 * Retrieves the BER type for this protocol op.
321 *
322 * @return The BER type for this protocol op.
323 */
324 public byte getType()
325 {
326 return OP_TYPE_EXTENDED_RESPONSE;
327 }
328
329
330
331 /**
332 * Retrieves the name for this protocol op type.
333 *
334 * @return The name for this protocol op type.
335 */
336 public String getProtocolOpName()
337 {
338 return "Extended Response";
339 }
340
341
342
343 /**
344 * Encodes this protocol op to an ASN.1 element suitable for including in an
345 * LDAP message.
346 *
347 * @return The ASN.1 element containing the encoded protocol op.
348 */
349 public ASN1Element encode()
350 {
351 ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(6);
352 elements.add(new ASN1Enumerated(resultCode));
353
354 if (matchedDN == null)
355 {
356 elements.add(new ASN1OctetString());
357 }
358 else
359 {
360 elements.add(new ASN1OctetString(matchedDN.toString()));
361 }
362
363 elements.add(new ASN1OctetString(errorMessage));
364
365 if ((referralURLs != null) && (! referralURLs.isEmpty()))
366 {
367 ArrayList<ASN1Element> referralElements =
368 new ArrayList<ASN1Element>(referralURLs.size());
369
370 for (String s : referralURLs)
371 {
372 referralElements.add(new ASN1OctetString(s));
373 }
374
375 elements.add(new ASN1Sequence(TYPE_REFERRAL_SEQUENCE, referralElements));
376 }
377
378 if ((oid != null) && (oid.length() > 0))
379 {
380 elements.add(new ASN1OctetString(TYPE_EXTENDED_RESPONSE_OID, oid));
381 }
382
383 if (value != null)
384 {
385 value.setType(TYPE_EXTENDED_RESPONSE_VALUE);
386 elements.add(value);
387 }
388
389 return new ASN1Sequence(OP_TYPE_EXTENDED_RESPONSE, elements);
390 }
391
392
393
394 /**
395 * Decodes the provided ASN.1 element as a extended response protocol op.
396 *
397 * @param element The ASN.1 element to decode.
398 *
399 * @return The decoded extended response protocol op.
400 *
401 * @throws LDAPException If a problem occurs while attempting to decode the
402 * ASN.1 element to a protocol op.
403 */
404 public static ExtendedResponseProtocolOp decodeExtendedResponse(ASN1Element
405 element)
406 throws LDAPException
407 {
408 ArrayList<ASN1Element> elements;
409 try
410 {
411 elements = element.decodeAsSequence().elements();
412 }
413 catch (Exception e)
414 {
415 if (debugEnabled())
416 {
417 TRACER.debugCaught(DebugLogLevel.ERROR, e);
418 }
419
420 Message message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(String.valueOf(e));
421 throw new LDAPException(PROTOCOL_ERROR, message, e);
422 }
423
424
425 int numElements = elements.size();
426 if ((numElements < 3) || (numElements > 6))
427 {
428 Message message = ERR_LDAP_EXTENDED_RESULT_DECODE_INVALID_ELEMENT_COUNT.
429 get(numElements);
430 throw new LDAPException(PROTOCOL_ERROR, message);
431 }
432
433
434 int resultCode;
435 try
436 {
437 resultCode = elements.get(0).decodeAsInteger().intValue();
438 }
439 catch (Exception e)
440 {
441 if (debugEnabled())
442 {
443 TRACER.debugCaught(DebugLogLevel.ERROR, e);
444 }
445
446 Message message =
447 ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(String.valueOf(e));
448 throw new LDAPException(PROTOCOL_ERROR, message, e);
449 }
450
451
452 DN matchedDN;
453 try
454 {
455 String dnString = elements.get(1).decodeAsOctetString().stringValue();
456 if (dnString.length() == 0)
457 {
458 matchedDN = null;
459 }
460 else
461 {
462 matchedDN = DN.decode(dnString);
463 }
464 }
465 catch (Exception e)
466 {
467 if (debugEnabled())
468 {
469 TRACER.debugCaught(DebugLogLevel.ERROR, e);
470 }
471
472 Message message =
473 ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(String.valueOf(e));
474 throw new LDAPException(PROTOCOL_ERROR, message, e);
475 }
476
477
478 Message errorMessage;
479 try
480 {
481 errorMessage = Message.raw(
482 elements.get(2).decodeAsOctetString().stringValue());
483 if (errorMessage.length() == 0)
484 {
485 errorMessage = null;
486 }
487 }
488 catch (Exception e)
489 {
490 if (debugEnabled())
491 {
492 TRACER.debugCaught(DebugLogLevel.ERROR, e);
493 }
494
495 Message message =
496 ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(String.valueOf(e));
497 throw new LDAPException(PROTOCOL_ERROR, message, e);
498 }
499
500
501 ArrayList<String> referralURLs = null;
502 String oid = null;
503 ASN1OctetString value = null;
504 for (int i=3; i < elements.size(); i++)
505 {
506 element = elements.get(i);
507 switch (element.getType())
508 {
509 case TYPE_REFERRAL_SEQUENCE:
510 try
511 {
512 ArrayList<ASN1Element> referralElements =
513 element.decodeAsSequence().elements();
514 referralURLs = new ArrayList<String>(referralElements.size());
515
516 for (ASN1Element e : referralElements)
517 {
518 referralURLs.add(e.decodeAsOctetString().stringValue());
519 }
520 }
521 catch (Exception e)
522 {
523 if (debugEnabled())
524 {
525 TRACER.debugCaught(DebugLogLevel.ERROR, e);
526 }
527
528 Message message = ERR_LDAP_EXTENDED_RESULT_DECODE_REFERRALS.get(
529 String.valueOf(e));
530 throw new LDAPException(PROTOCOL_ERROR, message, e);
531 }
532
533 break;
534 case TYPE_EXTENDED_RESPONSE_OID:
535 try
536 {
537 oid = element.decodeAsOctetString().stringValue();
538 }
539 catch (Exception e)
540 {
541 if (debugEnabled())
542 {
543 TRACER.debugCaught(DebugLogLevel.ERROR, e);
544 }
545
546 Message message =
547 ERR_LDAP_EXTENDED_RESULT_DECODE_OID.get(String.valueOf(e));
548 throw new LDAPException(PROTOCOL_ERROR, message, e);
549 }
550
551 break;
552 case TYPE_EXTENDED_RESPONSE_VALUE:
553 try
554 {
555 value = element.decodeAsOctetString();
556 }
557 catch (Exception e)
558 {
559 if (debugEnabled())
560 {
561 TRACER.debugCaught(DebugLogLevel.ERROR, e);
562 }
563
564 Message message =
565 ERR_LDAP_EXTENDED_RESULT_DECODE_VALUE.get(String.valueOf(e));
566 throw new LDAPException(PROTOCOL_ERROR, message, e);
567 }
568
569 break;
570 default:
571 Message message = ERR_LDAP_EXTENDED_RESULT_DECODE_INVALID_TYPE.get(
572 element.getType());
573 throw new LDAPException(PROTOCOL_ERROR, message);
574 }
575 }
576
577
578 return new ExtendedResponseProtocolOp(resultCode, errorMessage, matchedDN,
579 referralURLs, oid, value);
580 }
581
582
583
584 /**
585 * Appends a string representation of this LDAP protocol op to the provided
586 * buffer.
587 *
588 * @param buffer The buffer to which the string should be appended.
589 */
590 public void toString(StringBuilder buffer)
591 {
592 buffer.append("ExtendedResponse(resultCode=");
593 buffer.append(resultCode);
594
595 if ((errorMessage != null) && (errorMessage.length() > 0))
596 {
597 buffer.append(", errorMessage=");
598 buffer.append(errorMessage);
599 }
600
601 if (matchedDN != null)
602 {
603 buffer.append(", matchedDN=");
604 buffer.append(matchedDN.toString());
605 }
606
607 if ((referralURLs != null) && (! referralURLs.isEmpty()))
608 {
609 buffer.append(", referralURLs={");
610
611 Iterator<String> iterator = referralURLs.iterator();
612 buffer.append(iterator.next());
613
614 while (iterator.hasNext())
615 {
616 buffer.append(", ");
617 buffer.append(iterator.next());
618 }
619
620 buffer.append("}");
621 }
622
623 if ((oid != null) && (oid.length() > 0))
624 {
625 buffer.append(", oid=");
626 buffer.append(oid);
627 }
628
629 if (value != null)
630 {
631 buffer.append(", value=");
632 value.toString(buffer);
633 }
634
635 buffer.append(")");
636 }
637
638
639
640 /**
641 * Appends a multi-line string representation of this LDAP protocol op to the
642 * provided buffer.
643 *
644 * @param buffer The buffer to which the information should be appended.
645 * @param indent The number of spaces from the margin that the lines should
646 * be indented.
647 */
648 public void toString(StringBuilder buffer, int indent)
649 {
650 StringBuilder indentBuf = new StringBuilder(indent);
651 for (int i=0 ; i < indent; i++)
652 {
653 indentBuf.append(' ');
654 }
655
656 buffer.append(indentBuf);
657 buffer.append("Extended Response");
658 buffer.append(EOL);
659
660 buffer.append(indentBuf);
661 buffer.append(" Result Code: ");
662 buffer.append(resultCode);
663 buffer.append(EOL);
664
665 if (errorMessage != null)
666 {
667 buffer.append(indentBuf);
668 buffer.append(" Error Message: ");
669 buffer.append(errorMessage);
670 buffer.append(EOL);
671 }
672
673 if (matchedDN != null)
674 {
675 buffer.append(indentBuf);
676 buffer.append(" Matched DN: ");
677 matchedDN.toString(buffer);
678 buffer.append(EOL);
679 }
680
681 if ((referralURLs != null) && (! referralURLs.isEmpty()))
682 {
683 buffer.append(indentBuf);
684 buffer.append(" Referral URLs: ");
685 buffer.append(EOL);
686
687 for (String s : referralURLs)
688 {
689 buffer.append(indentBuf);
690 buffer.append(" ");
691 buffer.append(s);
692 buffer.append(EOL);
693 }
694 }
695
696 if ((oid != null) && (oid.length() > 0))
697 {
698 buffer.append(indentBuf);
699 buffer.append(" Response OID: ");
700 buffer.append(oid);
701 buffer.append(EOL);
702 }
703
704 if (value != null)
705 {
706 buffer.append(indentBuf);
707 buffer.append(" Response Value: ");
708 value.toString(buffer);
709 buffer.append(EOL);
710 }
711 }
712 }
713