001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2006-2009 Sun Microsystems, Inc.
015 * Portions Copyright 2014-2016 ForgeRock AS.
016 */
017package org.opends.server.protocols.ldap;
018
019import java.io.IOException;
020import java.util.ArrayList;
021import java.util.LinkedHashSet;
022import java.util.LinkedList;
023
024import org.forgerock.i18n.LocalizableMessage;
025import org.forgerock.i18n.slf4j.LocalizedLogger;
026import org.forgerock.opendj.io.ASN1;
027import org.forgerock.opendj.io.ASN1Reader;
028import org.forgerock.opendj.ldap.ByteString;
029import org.forgerock.opendj.ldap.DN;
030import org.forgerock.opendj.ldap.DereferenceAliasesPolicy;
031import org.forgerock.opendj.ldap.SearchScope;
032import org.opends.server.types.*;
033
034import static org.opends.messages.ProtocolMessages.*;
035import static org.opends.server.protocols.ldap.LDAPConstants.*;
036import static org.opends.server.protocols.ldap.LDAPResultCode.*;
037
038/**
039 * Utility class used to decode LDAP messages from an ASN1Reader.
040 */
041public class LDAPReader
042{
043  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
044
045  /**
046   * Decodes the elements from the provided ASN.1 reader as an LDAP message.
047   *
048   * @param reader The ASN.1 reader.
049   *
050   * @return  The decoded LDAP message.
051   *
052   * @throws  LDAPException  If a problem occurs while attempting to decode the
053   *                         LDAP message.
054   */
055  public static LDAPMessage readMessage(ASN1Reader reader)
056      throws LDAPException
057  {
058    try
059    {
060      reader.readStartSequence();
061    }
062    catch(Exception e)
063    {
064      LocalizableMessage message = ERR_LDAP_MESSAGE_DECODE_NULL.get();
065      throw new LDAPException(PROTOCOL_ERROR, message);
066    }
067
068    int messageID;
069    try
070    {
071      messageID = (int)reader.readInteger();
072    }
073    catch(Exception e)
074    {
075      logger.traceException(e);
076
077      LocalizableMessage message = ERR_LDAP_MESSAGE_DECODE_MESSAGE_ID.get(e);
078      throw new LDAPException(PROTOCOL_ERROR, message, e);
079    }
080
081    ProtocolOp protocolOp;
082    try
083    {
084      protocolOp = readProtocolOp(reader);
085    }
086    catch (Exception e)
087    {
088      logger.traceException(e);
089
090      LocalizableMessage message = ERR_LDAP_MESSAGE_DECODE_PROTOCOL_OP.get(e);
091      throw new LDAPException(PROTOCOL_ERROR, message, e);
092    }
093
094    ArrayList<Control> controls = null;
095    try
096    {
097      if(reader.hasNextElement())
098      {
099        controls = readControls(reader);
100      }
101    }
102    catch (Exception e)
103    {
104      logger.traceException(e);
105
106      LocalizableMessage message = ERR_LDAP_MESSAGE_DECODE_CONTROLS.get(e);
107      throw new LDAPException(PROTOCOL_ERROR, message, e);
108    }
109
110    try
111    {
112      reader.readEndSequence();
113    }
114    catch(Exception e)
115    {
116      LocalizableMessage message = ERR_LDAP_MESSAGE_DECODE_NULL.get();
117      throw new LDAPException(PROTOCOL_ERROR, message);
118    }
119
120    return new LDAPMessage(messageID, protocolOp, controls);
121  }
122
123  /**
124   * Decodes the elements from the provided ASN.1 reader as an LDAP
125   * protocol op.
126   *
127   * @param reader The ASN.1 reader.
128   *
129   * @return  The LDAP protocol op decoded from the provided ASN.1 element.
130   *
131   * @throws  LDAPException  If a problem occurs while trying to decode the
132   *                         provided ASN.1 elements as an LDAP protocol op.
133   */
134  public static ProtocolOp readProtocolOp(ASN1Reader reader)
135      throws LDAPException
136  {
137    byte type;
138    try
139    {
140      type = reader.peekType();
141    }
142    catch(Exception e)
143    {
144      LocalizableMessage message = ERR_LDAP_PROTOCOL_OP_DECODE_NULL.get();
145      throw new LDAPException(PROTOCOL_ERROR, message);
146    }
147
148    switch(type)
149    {
150      case OP_TYPE_UNBIND_REQUEST:                                       // 0x42
151        return readUnbindRequest(reader);
152      case 0x43:                                                         // 0x43
153      case 0x44:                                                         // 0x44
154      case 0x45:                                                         // 0x45
155      case 0x46:                                                         // 0x46
156      case 0x47:                                                         // 0x47
157      case 0x48:                                                         // 0x48
158      case 0x49:                                                         // 0x49
159        LocalizableMessage message =
160            ERR_LDAP_PROTOCOL_OP_DECODE_INVALID_TYPE.get(type);
161        throw new LDAPException(PROTOCOL_ERROR, message);
162      case OP_TYPE_DELETE_REQUEST:                                       // 0x4A
163        return readDeleteRequest(reader);
164      case 0x4B:                                                         // 0x4B
165      case 0x4C:                                                         // 0x4C
166      case 0x4D:                                                         // 0x4D
167      case 0x4E:                                                         // 0x4E
168      case 0x4F:                                                         // 0x4F
169        message =
170            ERR_LDAP_PROTOCOL_OP_DECODE_INVALID_TYPE.get(type);
171        throw new LDAPException(PROTOCOL_ERROR, message);
172      case OP_TYPE_ABANDON_REQUEST:                                      // 0x50
173        return readAbandonRequest(reader);
174      case 0x51:                                                         // 0x51
175      case 0x52:                                                         // 0x52
176      case 0x53:                                                         // 0x53
177      case 0x54:                                                         // 0x54
178      case 0x55:                                                         // 0x55
179      case 0x56:                                                         // 0x56
180      case 0x57:                                                         // 0x57
181      case 0x58:                                                         // 0x58
182      case 0x59:                                                         // 0x59
183      case 0x5A:                                                         // 0x5A
184      case 0x5B:                                                         // 0x5B
185      case 0x5C:                                                         // 0x5C
186      case 0x5D:                                                         // 0x5D
187      case 0x5E:                                                         // 0x5E
188      case 0x5F:                                                         // 0x5F
189        message =
190            ERR_LDAP_PROTOCOL_OP_DECODE_INVALID_TYPE.get(type);
191        throw new LDAPException(PROTOCOL_ERROR, message);
192      case OP_TYPE_BIND_REQUEST:                                         // 0x60
193        return readBindRequest(reader);
194      case OP_TYPE_BIND_RESPONSE:                                        // 0x61
195        return readBindResponse(reader);
196      case 0x62:                                                         // 0x62
197        message =
198            ERR_LDAP_PROTOCOL_OP_DECODE_INVALID_TYPE.get(type);
199        throw new LDAPException(PROTOCOL_ERROR, message);
200      case OP_TYPE_SEARCH_REQUEST:                                       // 0x63
201        return readSearchRequest(reader);
202      case OP_TYPE_SEARCH_RESULT_ENTRY:                                  // 0x64
203        return readSearchEntry(reader);
204      case OP_TYPE_SEARCH_RESULT_DONE:                                   // 0x65
205        return readSearchDone(reader);
206      case OP_TYPE_MODIFY_REQUEST:                                       // 0x66
207        return readModifyRequest(reader);
208      case OP_TYPE_MODIFY_RESPONSE:                                      // 0x67
209        return readModifyResponse(reader);
210      case OP_TYPE_ADD_REQUEST:                                          // 0x68
211        return readAddRequest(reader);
212      case OP_TYPE_ADD_RESPONSE:                                         // 0x69
213        return readAddResponse(reader);
214      case 0x6A:                                                         // 0x6A
215        message =
216            ERR_LDAP_PROTOCOL_OP_DECODE_INVALID_TYPE.get(type);
217        throw new LDAPException(PROTOCOL_ERROR, message);
218      case OP_TYPE_DELETE_RESPONSE:                                      // 0x6B
219        return readDeleteResponse(reader);
220      case OP_TYPE_MODIFY_DN_REQUEST:                                    // 0x6C
221        return readModifyDNRequest(reader);
222      case OP_TYPE_MODIFY_DN_RESPONSE:                                   // 0x6D
223        return readModifyDNResponse(reader);
224      case OP_TYPE_COMPARE_REQUEST:                                      // 0x6E
225        return readCompareRequest(reader);
226      case OP_TYPE_COMPARE_RESPONSE:                                     // 0x6F
227        return readCompareResponse(reader);
228      case 0x70:                                                         // 0x70
229      case 0x71:                                                         // 0x71
230      case 0x72:                                                         // 0x72
231        message =
232            ERR_LDAP_PROTOCOL_OP_DECODE_INVALID_TYPE.get(type);
233        throw new LDAPException(PROTOCOL_ERROR, message);
234      case OP_TYPE_SEARCH_RESULT_REFERENCE:                              // 0x73
235        return readSearchReference(reader);
236      case 0x74:                                                         // 0x74
237      case 0x75:                                                         // 0x75
238      case 0x76:                                                         // 0x76
239        message =
240            ERR_LDAP_PROTOCOL_OP_DECODE_INVALID_TYPE.get(type);
241        throw new LDAPException(PROTOCOL_ERROR, message);
242      case OP_TYPE_EXTENDED_REQUEST:                                     // 0x77
243        return readExtendedRequest(reader);
244      case OP_TYPE_EXTENDED_RESPONSE:                                    // 0x78
245        return readExtendedResponse(reader);
246      case OP_TYPE_INTERMEDIATE_RESPONSE:                                // 0x79
247        return
248            readIntermediateResponse(reader);
249      default:
250        message =
251            ERR_LDAP_PROTOCOL_OP_DECODE_INVALID_TYPE.get(type);
252        throw new LDAPException(PROTOCOL_ERROR, message);
253    }
254  }
255
256
257  /**
258   * Decodes the elements from the provided ASN.1 read as an LDAP
259   *  abandon request protocol op.
260   *
261   * @param  reader The ASN.1 reader.
262   *
263   * @return  The decoded abandon request protocol op.
264   *
265   * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
266   *                         an abandon request protocol op.
267   */
268  private static AbandonRequestProtocolOp readAbandonRequest(ASN1Reader reader)
269      throws LDAPException
270  {
271    long idToAbandon;
272    try
273    {
274      idToAbandon = reader.readInteger();
275    }
276    catch (Exception e)
277    {
278      logger.traceException(e);
279
280      LocalizableMessage message = ERR_LDAP_ABANDON_REQUEST_DECODE_ID.get(e);
281      throw new LDAPException(PROTOCOL_ERROR, message, e);
282    }
283
284    return new AbandonRequestProtocolOp((int)idToAbandon);
285  }
286
287  /**
288   * Decodes the elements from the provided ASN.1 reader as an LDAP
289   * add request protocol op.
290   *
291   * @param  reader The ASN.1 reader.
292   *
293   * @return  The decoded add request protocol op.
294   *
295   * @throws  LDAPException  If a problem occurs while decoding the provided
296   *                         ASN.1 element as an LDAP add request protocol op.
297   */
298  private static AddRequestProtocolOp readAddRequest(ASN1Reader reader)
299      throws LDAPException
300  {
301    try
302    {
303      reader.readStartSequence();
304    }
305    catch (Exception e)
306    {
307      logger.traceException(e);
308
309      LocalizableMessage message = ERR_LDAP_ADD_REQUEST_DECODE_SEQUENCE.get(e);
310      throw new LDAPException(PROTOCOL_ERROR, message, e);
311    }
312
313
314    ByteString dn;
315    try
316    {
317      dn = reader.readOctetString();
318    }
319    catch (Exception e)
320    {
321      logger.traceException(e);
322
323      LocalizableMessage message = ERR_LDAP_ADD_REQUEST_DECODE_DN.get(e);
324      throw new LDAPException(PROTOCOL_ERROR, message, e);
325    }
326
327
328
329    ArrayList<RawAttribute> attributes;
330    try
331    {
332      reader.readStartSequence();
333      attributes = new ArrayList<>();
334      while(reader.hasNextElement())
335      {
336        attributes.add(LDAPAttribute.decode(reader));
337      }
338      reader.readEndSequence();
339    }
340    catch (Exception e)
341    {
342      logger.traceException(e);
343
344      LocalizableMessage message = ERR_LDAP_ADD_REQUEST_DECODE_ATTRS.get(e);
345      throw new LDAPException(PROTOCOL_ERROR, message, e);
346    }
347
348    try
349    {
350      reader.readEndSequence();
351    }
352    catch (Exception e)
353    {
354      logger.traceException(e);
355
356      LocalizableMessage message = ERR_LDAP_ADD_REQUEST_DECODE_SEQUENCE.get(e);
357      throw new LDAPException(PROTOCOL_ERROR, message, e);
358    }
359
360
361    return new AddRequestProtocolOp(dn, attributes);
362  }
363
364  /**
365   * Decodes the elements from the provided ASN.1 reader as an
366   * add response protocol op.
367   *
368   * @param  reader The ASN.1 reader.
369   *
370   * @return  The decoded add response protocol op.
371   *
372   * @throws  LDAPException  If a problem occurs while attempting to decode the
373   *                         ASN.1 element to a protocol op.
374   */
375  private static AddResponseProtocolOp readAddResponse(ASN1Reader reader)
376      throws LDAPException
377  {
378    try
379    {
380      reader.readStartSequence();
381    }
382    catch (Exception e)
383    {
384      logger.traceException(e);
385
386      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
387      throw new LDAPException(PROTOCOL_ERROR, message, e);
388    }
389
390    int resultCode;
391    try
392    {
393      resultCode = (int)reader.readInteger();
394    }
395    catch (Exception e)
396    {
397      logger.traceException(e);
398
399      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(e);
400      throw new LDAPException(PROTOCOL_ERROR, message, e);
401    }
402
403
404    DN matchedDN;
405    try
406    {
407      String dnString = reader.readOctetStringAsString();
408      if (dnString.length() == 0)
409      {
410        matchedDN = null;
411      }
412      else
413      {
414        matchedDN = DN.valueOf(dnString);
415      }
416    }
417    catch (Exception e)
418    {
419      logger.traceException(e);
420
421      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(e);
422      throw new LDAPException(PROTOCOL_ERROR, message, e);
423    }
424
425
426    LocalizableMessage errorMessage;
427    try
428    {
429      errorMessage = LocalizableMessage.raw(reader.readOctetStringAsString());
430      if (errorMessage.length() == 0)
431      {
432        errorMessage = null;
433      }
434    }
435    catch (Exception e)
436    {
437      logger.traceException(e);
438
439      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(e);
440      throw new LDAPException(PROTOCOL_ERROR, message, e);
441    }
442
443    ArrayList<String> referralURLs = null;
444
445    try
446    {
447      if (reader.hasNextElement())
448      {
449        reader.readStartSequence();
450        referralURLs = new ArrayList<>();
451
452        while(reader.hasNextElement())
453        {
454          referralURLs.add(reader.readOctetStringAsString());
455        }
456        reader.readEndSequence();
457      }
458    }
459    catch (Exception e)
460    {
461      logger.traceException(e);
462
463      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_REFERRALS.get(e);
464      throw new LDAPException(PROTOCOL_ERROR, message, e);
465    }
466
467    try
468    {
469      reader.readEndSequence();
470    }
471    catch (Exception e)
472    {
473      logger.traceException(e);
474
475      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
476      throw new LDAPException(PROTOCOL_ERROR, message, e);
477    }
478
479    return new AddResponseProtocolOp(resultCode, errorMessage, matchedDN,
480        referralURLs);
481  }
482
483  /**
484   * Decodes the elements from the provided ASN.1 read as an LDAP bind
485   * request protocol op.
486   *
487   * @param  reader The ASN.1 reader
488   *
489   * @return  The decoded LDAP bind request protocol op.
490   *
491   * @throws  LDAPException  If a problem occurs while trying to decode the
492   *                         provided ASN.1 element as an LDAP bind request.
493   */
494  private static BindRequestProtocolOp readBindRequest(ASN1Reader reader)
495      throws LDAPException
496  {
497    try
498    {
499      reader.readStartSequence();
500    }
501    catch (Exception e)
502    {
503      logger.traceException(e);
504
505      LocalizableMessage message = ERR_LDAP_BIND_REQUEST_DECODE_SEQUENCE.get(e);
506      throw new LDAPException(PROTOCOL_ERROR, message, e);
507    }
508
509    int protocolVersion;
510    try
511    {
512      protocolVersion = (int)reader.readInteger();
513    }
514    catch (Exception e)
515    {
516      logger.traceException(e);
517
518      LocalizableMessage message = ERR_LDAP_BIND_REQUEST_DECODE_VERSION.get(e);
519      throw new LDAPException(PROTOCOL_ERROR, message, e);
520    }
521
522
523    ByteString dn;
524    try
525    {
526      dn = reader.readOctetString();
527    }
528    catch (Exception e)
529    {
530      logger.traceException(e);
531
532      LocalizableMessage message = ERR_LDAP_BIND_REQUEST_DECODE_DN.get(e);
533      throw new LDAPException(PROTOCOL_ERROR, message, e);
534    }
535
536    byte type;
537    try
538    {
539      type = reader.peekType();
540
541    }
542    catch (Exception e)
543    {
544      logger.traceException(e);
545
546      LocalizableMessage message = ERR_LDAP_BIND_REQUEST_DECODE_CREDENTIALS.get(e);
547      throw new LDAPException(PROTOCOL_ERROR, message, e);
548    }
549
550    ByteString simplePassword  = null;
551    String     saslMechanism   = null;
552    ByteString saslCredentials = null;
553    switch (type)
554    {
555      case TYPE_AUTHENTICATION_SIMPLE:
556        try
557        {
558          simplePassword =
559              reader.readOctetString();
560        }
561        catch (Exception e)
562        {
563          LocalizableMessage message = ERR_LDAP_BIND_REQUEST_DECODE_PASSWORD.get(e);
564          throw new LDAPException(PROTOCOL_ERROR, message, e);
565        }
566        break;
567      case TYPE_AUTHENTICATION_SASL:
568        try
569        {
570          reader.readStartSequence();
571          saslMechanism = reader.readOctetStringAsString();
572          if (reader.hasNextElement())
573          {
574            saslCredentials =
575                reader.readOctetString();
576          }
577          reader.readEndSequence();
578        }
579        catch (Exception e)
580        {
581          LocalizableMessage message = ERR_LDAP_BIND_REQUEST_DECODE_SASL_INFO.get(e);
582          throw new LDAPException(PROTOCOL_ERROR, message, e);
583        }
584        break;
585      default:
586        LocalizableMessage message = ERR_LDAP_BIND_REQUEST_DECODE_INVALID_CRED_TYPE.get(
587            type);
588        throw new LDAPException(AUTH_METHOD_NOT_SUPPORTED, message);
589    }
590
591    try
592    {
593      reader.readEndSequence();
594    }
595    catch (Exception e)
596    {
597      logger.traceException(e);
598
599      LocalizableMessage message = ERR_LDAP_BIND_REQUEST_DECODE_SEQUENCE.get(e);
600      throw new LDAPException(PROTOCOL_ERROR, message, e);
601    }
602
603    if(type == TYPE_AUTHENTICATION_SIMPLE)
604    {
605      return new BindRequestProtocolOp(dn, protocolVersion, simplePassword);
606    }
607    else
608    {
609      return new BindRequestProtocolOp(dn, saslMechanism, saslCredentials);
610    }
611  }
612
613  /**
614   * Decodes the elements from the provided ASN.1 reader as a bind
615   * response protocol op.
616   *
617   * @param  reader The ASN.1 reader.
618   *
619   * @return  The decoded bind response protocol op.
620   *
621   * @throws  LDAPException  If a problem occurs while attempting to decode the
622   *                         ASN.1 element to a protocol op.
623   */
624  private static BindResponseProtocolOp readBindResponse(ASN1Reader reader)
625      throws LDAPException
626  {
627    try
628    {
629      reader.readStartSequence();
630    }
631    catch (Exception e)
632    {
633      logger.traceException(e);
634
635      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
636      throw new LDAPException(PROTOCOL_ERROR, message, e);
637    }
638
639    int resultCode;
640    try
641    {
642      resultCode = (int)reader.readInteger();
643    }
644    catch (Exception e)
645    {
646      logger.traceException(e);
647
648      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(e);
649      throw new LDAPException(PROTOCOL_ERROR, message, e);
650    }
651
652
653    DN matchedDN;
654    try
655    {
656      String dnString = reader.readOctetStringAsString();
657      if (dnString.length() == 0)
658      {
659        matchedDN = null;
660      }
661      else
662      {
663        matchedDN = DN.valueOf(dnString);
664      }
665    }
666    catch (Exception e)
667    {
668      logger.traceException(e);
669
670      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(e);
671      throw new LDAPException(PROTOCOL_ERROR, message, e);
672    }
673
674
675    LocalizableMessage errorMessage;
676    try
677    {
678      errorMessage = LocalizableMessage.raw(reader.readOctetStringAsString());
679      if (errorMessage.length() == 0)
680      {
681        errorMessage = null;
682      }
683    }
684    catch (Exception e)
685    {
686      logger.traceException(e);
687
688      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(e);
689      throw new LDAPException(PROTOCOL_ERROR, message, e);
690    }
691
692    ArrayList<String> referralURLs = null;
693    ByteString   serverSASLCredentials = null;
694
695    try
696    {
697      if(reader.hasNextElement() &&
698          reader.peekType() == TYPE_REFERRAL_SEQUENCE)
699      {
700        try
701        {
702          reader.readStartSequence();
703          referralURLs = new ArrayList<>();
704
705          // Should have at least 1.
706          do
707          {
708            referralURLs.add(reader.readOctetStringAsString());
709          }
710          while(reader.hasNextElement());
711          reader.readEndSequence();
712        }
713        catch (Exception e)
714        {
715          logger.traceException(e);
716
717          LocalizableMessage message = ERR_LDAP_RESULT_DECODE_REFERRALS.get(e);
718          throw new LDAPException(PROTOCOL_ERROR, message, e);
719        }
720      }
721      if(reader.hasNextElement() &&
722          reader.peekType() == TYPE_SERVER_SASL_CREDENTIALS)
723      {
724        try
725        {
726          serverSASLCredentials =
727              reader.readOctetString();
728        }
729        catch (Exception e)
730        {
731          logger.traceException(e);
732
733          LocalizableMessage message = ERR_LDAP_BIND_RESULT_DECODE_SERVER_SASL_CREDENTIALS.get(e);
734          throw new LDAPException(PROTOCOL_ERROR, message, e);
735        }
736      }
737    }
738    catch(IOException e)
739    {
740      logger.traceException(e);
741    }
742
743    try
744    {
745      reader.readEndSequence();
746    }
747    catch (Exception e)
748    {
749      logger.traceException(e);
750
751      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
752      throw new LDAPException(PROTOCOL_ERROR, message, e);
753    }
754
755    return new BindResponseProtocolOp(resultCode, errorMessage, matchedDN,
756        referralURLs, serverSASLCredentials);
757  }
758
759  /**
760   * Decodes the elements from the provided ASN.1 reader as an LDAP
761   * compare request protocol op.
762   *
763   * @param  reader The ASN.1 reader
764   *
765   * @return  The decoded LDAP compare request protocol op.
766   *
767   * @throws  LDAPException  If a problem occurs while attempting to decode the
768   *                         ASN.1 element as a compare request protocol op.
769   */
770  private static CompareRequestProtocolOp readCompareRequest(ASN1Reader reader)
771      throws LDAPException
772  {
773    try
774    {
775      reader.readStartSequence();
776    }
777    catch (Exception e)
778    {
779      logger.traceException(e);
780
781      LocalizableMessage message = ERR_LDAP_COMPARE_REQUEST_DECODE_SEQUENCE.get(e);
782      throw new LDAPException(PROTOCOL_ERROR, message, e);
783    }
784
785
786    ByteString dn;
787    try
788    {
789      dn = reader.readOctetString();
790    }
791    catch (Exception e)
792    {
793      logger.traceException(e);
794
795      LocalizableMessage message = ERR_LDAP_COMPARE_REQUEST_DECODE_DN.get(e);
796      throw new LDAPException(PROTOCOL_ERROR, message, e);
797    }
798
799    try
800    {
801      reader.readStartSequence();
802    }
803    catch (Exception e)
804    {
805      logger.traceException(e);
806
807      LocalizableMessage message = ERR_LDAP_COMPARE_REQUEST_DECODE_AVA.get(e);
808      throw new LDAPException(PROTOCOL_ERROR, message, e);
809    }
810
811    String attributeType;
812    try
813    {
814      attributeType = reader.readOctetStringAsString();
815    }
816    catch (Exception e)
817    {
818      logger.traceException(e);
819
820      LocalizableMessage message = ERR_LDAP_COMPARE_REQUEST_DECODE_TYPE.get(e);
821      throw new LDAPException(PROTOCOL_ERROR, message, e);
822    }
823
824
825    ByteString assertionValue;
826    try
827    {
828      assertionValue = reader.readOctetString();
829    }
830    catch (Exception e)
831    {
832      logger.traceException(e);
833
834      LocalizableMessage message = ERR_LDAP_COMPARE_REQUEST_DECODE_VALUE.get(e);
835      throw new LDAPException(PROTOCOL_ERROR, message, e);
836    }
837
838    try
839    {
840      reader.readEndSequence();
841    }
842    catch (Exception e)
843    {
844      logger.traceException(e);
845
846      LocalizableMessage message = ERR_LDAP_COMPARE_REQUEST_DECODE_AVA.get(e);
847      throw new LDAPException(PROTOCOL_ERROR, message, e);
848    }
849
850    try
851    {
852      reader.readEndSequence();
853    }
854    catch (Exception e)
855    {
856      logger.traceException(e);
857
858      LocalizableMessage message = ERR_LDAP_COMPARE_REQUEST_DECODE_SEQUENCE.get(e);
859      throw new LDAPException(PROTOCOL_ERROR, message, e);
860    }
861
862    return new CompareRequestProtocolOp(dn, attributeType, assertionValue);
863  }
864
865  /**
866   * Decodes the elements from the provided ASN.1 reader as a
867   * compare response protocol op.
868   *
869   * @param  reader The ASN.1 reader.
870   *
871   * @return  The decoded compare response protocol op.
872   *
873   * @throws  LDAPException  If a problem occurs while attempting to decode the
874   *                         ASN.1 element to a protocol op.
875   */
876  private static CompareResponseProtocolOp readCompareResponse(ASN1Reader
877      reader)
878      throws LDAPException
879  {
880    try
881    {
882      reader.readStartSequence();
883    }
884    catch (Exception e)
885    {
886      logger.traceException(e);
887
888      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
889      throw new LDAPException(PROTOCOL_ERROR, message, e);
890    }
891
892    int resultCode;
893    try
894    {
895      resultCode = (int)reader.readInteger();
896    }
897    catch (Exception e)
898    {
899      logger.traceException(e);
900
901      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(e);
902      throw new LDAPException(PROTOCOL_ERROR, message, e);
903    }
904
905
906    DN matchedDN;
907    try
908    {
909      String dnString = reader.readOctetStringAsString();
910      if (dnString.length() == 0)
911      {
912        matchedDN = null;
913      }
914      else
915      {
916        matchedDN = DN.valueOf(dnString);
917      }
918    }
919    catch (Exception e)
920    {
921      logger.traceException(e);
922
923      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(e);
924      throw new LDAPException(PROTOCOL_ERROR, message, e);
925    }
926
927
928    LocalizableMessage errorMessage;
929    try
930    {
931      errorMessage = LocalizableMessage.raw(reader.readOctetStringAsString());
932      if (errorMessage.length() == 0)
933      {
934        errorMessage = null;
935      }
936    }
937    catch (Exception e)
938    {
939      logger.traceException(e);
940
941      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(e);
942      throw new LDAPException(PROTOCOL_ERROR, message, e);
943    }
944
945    ArrayList<String> referralURLs = null;
946
947    try
948    {
949      if (reader.hasNextElement())
950      {
951        reader.readStartSequence();
952        referralURLs = new ArrayList<>();
953
954        while(reader.hasNextElement())
955        {
956          referralURLs.add(reader.readOctetStringAsString());
957        }
958        reader.readEndSequence();
959      }
960    }
961    catch (Exception e)
962    {
963      logger.traceException(e);
964
965      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_REFERRALS.get(e);
966      throw new LDAPException(PROTOCOL_ERROR, message, e);
967    }
968
969    try
970    {
971      reader.readEndSequence();
972    }
973    catch (Exception e)
974    {
975      logger.traceException(e);
976
977      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
978      throw new LDAPException(PROTOCOL_ERROR, message, e);
979    }
980
981    return new CompareResponseProtocolOp(resultCode, errorMessage, matchedDN,
982        referralURLs);
983  }
984
985  /**
986   * Decodes the elements from the provided ASN.1 reader as an LDAP delete
987   * request protocol op.
988   *
989   * @param  reader The ASN.1 reader.
990   *
991   * @return  The decoded delete request protocol op.
992   *
993   * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
994   *                         an unbind request protocol op.
995   */
996  private static DeleteRequestProtocolOp readDeleteRequest(ASN1Reader reader)
997      throws LDAPException
998  {
999    try
1000    {
1001      return new DeleteRequestProtocolOp(reader.readOctetString());
1002    }
1003    catch (Exception e)
1004    {
1005      logger.traceException(e);
1006
1007      LocalizableMessage message = ERR_LDAP_DELETE_REQUEST_DECODE_DN.get(e);
1008      throw new LDAPException(PROTOCOL_ERROR, message, e);
1009    }
1010  }
1011
1012  /**
1013   * Decodes the provided ASN.1 element as a delete response protocol op.
1014   *
1015   * @param  reader The ASN.1 reader.
1016   *
1017   * @return  The decoded delete response protocol op.
1018   *
1019   * @throws  LDAPException  If a problem occurs while attempting to decode the
1020   *                         ASN.1 element to a protocol op.
1021   */
1022  private static DeleteResponseProtocolOp readDeleteResponse(ASN1Reader reader)
1023      throws LDAPException
1024  {
1025    try
1026    {
1027      reader.readStartSequence();
1028    }
1029    catch (Exception e)
1030    {
1031      logger.traceException(e);
1032
1033      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
1034      throw new LDAPException(PROTOCOL_ERROR, message, e);
1035    }
1036
1037    int resultCode;
1038    try
1039    {
1040      resultCode = (int)reader.readInteger();
1041    }
1042    catch (Exception e)
1043    {
1044      logger.traceException(e);
1045
1046      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(e);
1047      throw new LDAPException(PROTOCOL_ERROR, message, e);
1048    }
1049
1050
1051    DN matchedDN;
1052    try
1053    {
1054      String dnString = reader.readOctetStringAsString();
1055      if (dnString.length() == 0)
1056      {
1057        matchedDN = null;
1058      }
1059      else
1060      {
1061        matchedDN = DN.valueOf(dnString);
1062      }
1063    }
1064    catch (Exception e)
1065    {
1066      logger.traceException(e);
1067
1068      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(e);
1069      throw new LDAPException(PROTOCOL_ERROR, message, e);
1070    }
1071
1072
1073    LocalizableMessage errorMessage;
1074    try
1075    {
1076      errorMessage = LocalizableMessage.raw(reader.readOctetStringAsString());
1077      if (errorMessage.length() == 0)
1078      {
1079        errorMessage = null;
1080      }
1081    }
1082    catch (Exception e)
1083    {
1084      logger.traceException(e);
1085
1086      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(e);
1087      throw new LDAPException(PROTOCOL_ERROR, message, e);
1088    }
1089
1090    ArrayList<String> referralURLs = null;
1091
1092    try
1093    {
1094      if (reader.hasNextElement())
1095      {
1096        reader.readStartSequence();
1097        referralURLs = new ArrayList<>();
1098
1099        while(reader.hasNextElement())
1100        {
1101          referralURLs.add(reader.readOctetStringAsString());
1102        }
1103        reader.readEndSequence();
1104      }
1105    }
1106    catch (Exception e)
1107    {
1108      logger.traceException(e);
1109
1110      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_REFERRALS.get(e);
1111      throw new LDAPException(PROTOCOL_ERROR, message, e);
1112    }
1113
1114    try
1115    {
1116      reader.readEndSequence();
1117    }
1118    catch (Exception e)
1119    {
1120      logger.traceException(e);
1121
1122      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
1123      throw new LDAPException(PROTOCOL_ERROR, message, e);
1124    }
1125
1126
1127    return new DeleteResponseProtocolOp(resultCode, errorMessage, matchedDN,
1128        referralURLs);
1129  }
1130
1131  /**
1132   * Decodes the elements from the provided ASN.1 reader as an
1133   * LDAP extended request protocol op.
1134   *
1135   * @param  reader The ASN.1 reader.
1136   *
1137   * @return  The decoded extended request protocol op.
1138   *
1139   * @throws  LDAPException  If a problem occurs while attempting to decode the
1140   *                         provided ASN.1 element as an LDAP extended request
1141   *                         protocol op.
1142   */
1143  private static ExtendedRequestProtocolOp readExtendedRequest(ASN1Reader
1144      reader)
1145      throws LDAPException
1146  {
1147    try
1148    {
1149      reader.readStartSequence();
1150    }
1151    catch (Exception e)
1152    {
1153      logger.traceException(e);
1154
1155      LocalizableMessage message = ERR_LDAP_EXTENDED_REQUEST_DECODE_SEQUENCE.get(e);
1156      throw new LDAPException(PROTOCOL_ERROR, message, e);
1157    }
1158
1159
1160    String oid;
1161    try
1162    {
1163      oid = reader.readOctetStringAsString();
1164    }
1165    catch (Exception e)
1166    {
1167      logger.traceException(e);
1168
1169      LocalizableMessage message = ERR_LDAP_EXTENDED_REQUEST_DECODE_OID.get(e);
1170      throw new LDAPException(PROTOCOL_ERROR, message, e);
1171    }
1172
1173
1174    ByteString value = null;
1175    try
1176    {
1177      if(reader.hasNextElement())
1178      {
1179        value = reader.readOctetString();
1180      }
1181    }
1182    catch (Exception e)
1183    {
1184      logger.traceException(e);
1185
1186      LocalizableMessage message = ERR_LDAP_EXTENDED_REQUEST_DECODE_VALUE.get(e);
1187      throw new LDAPException(PROTOCOL_ERROR, message, e);
1188    }
1189
1190    try
1191    {
1192      reader.readEndSequence();
1193    }
1194    catch (Exception e)
1195    {
1196      logger.traceException(e);
1197
1198      LocalizableMessage message = ERR_LDAP_EXTENDED_REQUEST_DECODE_SEQUENCE.get(e);
1199      throw new LDAPException(PROTOCOL_ERROR, message, e);
1200    }
1201
1202    return new ExtendedRequestProtocolOp(oid, value);
1203  }
1204
1205  /**
1206   * Decodes the elements from the provided ASN.1 reader as a
1207   * extended response protocol op.
1208   *
1209   * @param  reader The ASN.1 reader.
1210   *
1211   * @return  The decoded extended response protocol op.
1212   *
1213   * @throws  LDAPException  If a problem occurs while attempting to decode the
1214   *                         ASN.1 element to a protocol op.
1215   */
1216  private static ExtendedResponseProtocolOp readExtendedResponse(ASN1Reader
1217      reader)
1218      throws LDAPException
1219  {
1220    try
1221    {
1222      reader.readStartSequence();
1223    }
1224    catch (Exception e)
1225    {
1226      logger.traceException(e);
1227
1228      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
1229      throw new LDAPException(PROTOCOL_ERROR, message, e);
1230    }
1231
1232    int resultCode;
1233    try
1234    {
1235      resultCode = (int)reader.readInteger();
1236    }
1237    catch (Exception e)
1238    {
1239      logger.traceException(e);
1240
1241      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(e);
1242      throw new LDAPException(PROTOCOL_ERROR, message, e);
1243    }
1244
1245
1246    DN matchedDN;
1247    try
1248    {
1249      String dnString = reader.readOctetStringAsString();
1250      if (dnString.length() == 0)
1251      {
1252        matchedDN = null;
1253      }
1254      else
1255      {
1256        matchedDN = DN.valueOf(dnString);
1257      }
1258    }
1259    catch (Exception e)
1260    {
1261      logger.traceException(e);
1262
1263      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(e);
1264      throw new LDAPException(PROTOCOL_ERROR, message, e);
1265    }
1266
1267
1268    LocalizableMessage errorMessage;
1269    try
1270    {
1271      errorMessage = LocalizableMessage.raw(reader.readOctetStringAsString());
1272      if (errorMessage.length() == 0)
1273      {
1274        errorMessage = null;
1275      }
1276    }
1277    catch (Exception e)
1278    {
1279      logger.traceException(e);
1280
1281      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(e);
1282      throw new LDAPException(PROTOCOL_ERROR, message, e);
1283    }
1284
1285    ArrayList<String> referralURLs = null;
1286    String            oid          = null;
1287    ByteString   value        = null;
1288
1289    try
1290    {
1291      if(reader.hasNextElement() &&
1292          reader.peekType() == TYPE_REFERRAL_SEQUENCE)
1293      {
1294        try
1295        {
1296          reader.readStartSequence();
1297          referralURLs = new ArrayList<>();
1298
1299          while(reader.hasNextElement())
1300          {
1301            referralURLs.add(reader.readOctetStringAsString());
1302          }
1303          reader.readEndSequence();
1304        }
1305        catch (Exception e)
1306        {
1307          logger.traceException(e);
1308
1309          LocalizableMessage message = ERR_LDAP_RESULT_DECODE_REFERRALS.get(e);
1310          throw new LDAPException(PROTOCOL_ERROR, message, e);
1311        }
1312      }
1313      if(reader.hasNextElement() &&
1314          reader.peekType() == TYPE_EXTENDED_RESPONSE_OID)
1315      {
1316        try
1317        {
1318          oid = reader.readOctetStringAsString();
1319        }
1320        catch (Exception e)
1321        {
1322          logger.traceException(e);
1323
1324          LocalizableMessage message = ERR_LDAP_EXTENDED_RESULT_DECODE_OID.get(e);
1325          throw new LDAPException(PROTOCOL_ERROR, message, e);
1326        }
1327      }
1328      if(reader.hasNextElement() &&
1329          reader.peekType() == TYPE_EXTENDED_RESPONSE_VALUE)
1330      {
1331        try
1332        {
1333          value = reader.readOctetString();
1334        }
1335        catch (Exception e)
1336        {
1337          logger.traceException(e);
1338
1339          LocalizableMessage message = ERR_LDAP_EXTENDED_RESULT_DECODE_VALUE.get(e);
1340          throw new LDAPException(PROTOCOL_ERROR, message, e);
1341        }
1342      }
1343    }
1344    catch(IOException e)
1345    {
1346      logger.traceException(e);
1347    }
1348
1349    try
1350    {
1351      reader.readEndSequence();
1352    }
1353    catch (Exception e)
1354    {
1355      logger.traceException(e);
1356
1357      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
1358      throw new LDAPException(PROTOCOL_ERROR, message, e);
1359    }
1360
1361    return new ExtendedResponseProtocolOp(resultCode, errorMessage, matchedDN,
1362        referralURLs, oid, value);
1363  }
1364
1365  /**
1366   * Decodes the elements from the provided ASN.1 reader as an LDAP
1367   * intermediate response protocol op.
1368   *
1369   * @param  reader The ASN.1 reader.
1370   *
1371   * @return  The decoded intermediate response protocol op.
1372   *
1373   * @throws  LDAPException  If a problem occurs while attempting to decode the
1374   *                         provided ASN.1 element as an LDAP intermediate
1375   *                         response protocol op.
1376   */
1377  private static IntermediateResponseProtocolOp
1378  readIntermediateResponse(ASN1Reader reader)
1379      throws LDAPException
1380  {
1381    try
1382    {
1383      reader.readStartSequence();
1384    }
1385    catch (Exception e)
1386    {
1387      logger.traceException(e);
1388
1389      LocalizableMessage message = ERR_LDAP_INTERMEDIATE_RESPONSE_DECODE_SEQUENCE.get(e);
1390      throw new LDAPException(PROTOCOL_ERROR, message, e);
1391    }
1392
1393    String          oid   = null;
1394    ByteString value = null;
1395
1396    try
1397    {
1398      if(reader.hasNextElement() &&
1399          reader.peekType() == TYPE_INTERMEDIATE_RESPONSE_OID)
1400      {
1401        try
1402        {
1403          if(reader.hasNextElement())
1404          {
1405            oid = reader.readOctetStringAsString();
1406          }
1407        }
1408        catch (Exception e)
1409        {
1410          logger.traceException(e);
1411
1412          LocalizableMessage message =
1413              ERR_LDAP_INTERMEDIATE_RESPONSE_CANNOT_DECODE_OID.get(
1414                  e.getMessage());
1415          throw new LDAPException(PROTOCOL_ERROR, message);
1416        }
1417      }
1418      if(reader.hasNextElement() &&
1419          reader.peekType() == TYPE_INTERMEDIATE_RESPONSE_VALUE)
1420      {
1421        try
1422        {
1423          value = reader.readOctetString();
1424        }
1425        catch (Exception e)
1426        {
1427          logger.traceException(e);
1428
1429          LocalizableMessage message =
1430              ERR_LDAP_INTERMEDIATE_RESPONSE_CANNOT_DECODE_VALUE.
1431                  get(e.getMessage());
1432          throw new LDAPException(PROTOCOL_ERROR, message);
1433        }
1434      }
1435    }
1436    catch(IOException e)
1437    {
1438      logger.traceException(e);
1439    }
1440
1441    try
1442    {
1443      reader.readEndSequence();
1444    }
1445    catch (Exception e)
1446    {
1447      logger.traceException(e);
1448
1449      LocalizableMessage message = ERR_LDAP_INTERMEDIATE_RESPONSE_DECODE_SEQUENCE.get(e);
1450      throw new LDAPException(PROTOCOL_ERROR, message, e);
1451    }
1452
1453    return new IntermediateResponseProtocolOp(oid, value);
1454  }
1455
1456  /**
1457   * Decodes the elements from the provided ASN.1 reader as a
1458   * modify DN request protocol op.
1459   *
1460   * @param  reader The ASN.1 reader.
1461   *
1462   * @return  The decoded modify DN request protocol op.
1463   *
1464   * @throws  LDAPException  If a problem occurs while trying to decode the
1465   *                         provided ASN.1 element as an LDAP modify DN request
1466   *                         protocol op.
1467   */
1468  private static ModifyDNRequestProtocolOp readModifyDNRequest(ASN1Reader
1469      reader)
1470      throws LDAPException
1471  {
1472    try
1473    {
1474      reader.readStartSequence();
1475    }
1476    catch (Exception e)
1477    {
1478      logger.traceException(e);
1479
1480      LocalizableMessage message = ERR_LDAP_MODIFY_DN_REQUEST_DECODE_SEQUENCE.get(e);
1481      throw new LDAPException(PROTOCOL_ERROR, message, e);
1482    }
1483
1484
1485    ByteString entryDN;
1486    try
1487    {
1488      entryDN = reader.readOctetString();
1489    }
1490    catch (Exception e)
1491    {
1492      logger.traceException(e);
1493
1494      LocalizableMessage message = ERR_LDAP_MODIFY_DN_REQUEST_DECODE_DN.get(e);
1495      throw new LDAPException(PROTOCOL_ERROR, message, e);
1496    }
1497
1498
1499    ByteString newRDN;
1500    try
1501    {
1502      newRDN = reader.readOctetString();
1503    }
1504    catch (Exception e)
1505    {
1506      logger.traceException(e);
1507
1508      LocalizableMessage message = ERR_LDAP_MODIFY_DN_REQUEST_DECODE_NEW_RDN.get(e);
1509      throw new LDAPException(PROTOCOL_ERROR, message, e);
1510    }
1511
1512
1513    boolean deleteOldRDN;
1514    try
1515    {
1516      deleteOldRDN = reader.readBoolean();
1517    }
1518    catch (Exception e)
1519    {
1520      logger.traceException(e);
1521
1522      LocalizableMessage message = ERR_LDAP_MODIFY_DN_REQUEST_DECODE_DELETE_OLD_RDN.get(e);
1523      throw new LDAPException(PROTOCOL_ERROR, message, e);
1524    }
1525
1526
1527    ByteString newSuperior = null;
1528    try
1529    {
1530      if(reader.hasNextElement())
1531      {
1532        newSuperior = reader.readOctetString();
1533      }
1534    }
1535    catch (Exception e)
1536    {
1537      logger.traceException(e);
1538
1539      LocalizableMessage message = ERR_LDAP_MODIFY_DN_REQUEST_DECODE_NEW_SUPERIOR.get(e);
1540      throw new LDAPException(PROTOCOL_ERROR, message, e);
1541    }
1542
1543    try
1544    {
1545      reader.readEndSequence();
1546    }
1547    catch (Exception e)
1548    {
1549      logger.traceException(e);
1550
1551      LocalizableMessage message = ERR_LDAP_MODIFY_DN_REQUEST_DECODE_SEQUENCE.get(e);
1552      throw new LDAPException(PROTOCOL_ERROR, message, e);
1553    }
1554
1555    return new ModifyDNRequestProtocolOp(entryDN, newRDN, deleteOldRDN,
1556        newSuperior);
1557  }
1558
1559  /**
1560   * Decodes the elements from the provided ASN.1 reader as a
1561   * modify DN response protocol op.
1562   *
1563   * @param  reader The ASN.1 reader.
1564   *
1565   * @return  The decoded modify DN response protocol op.
1566   *
1567   * @throws  LDAPException  If a problem occurs while attempting to decode the
1568   *                         ASN.1 element to a protocol op.
1569   */
1570  private static ModifyDNResponseProtocolOp readModifyDNResponse(ASN1Reader
1571      reader)
1572      throws LDAPException
1573  {
1574    try
1575    {
1576      reader.readStartSequence();
1577    }
1578    catch (Exception e)
1579    {
1580      logger.traceException(e);
1581
1582      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
1583      throw new LDAPException(PROTOCOL_ERROR, message, e);
1584    }
1585
1586    int resultCode;
1587    try
1588    {
1589      resultCode = (int)reader.readInteger();
1590    }
1591    catch (Exception e)
1592    {
1593      logger.traceException(e);
1594
1595      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(e);
1596      throw new LDAPException(PROTOCOL_ERROR, message, e);
1597    }
1598
1599
1600    DN matchedDN;
1601    try
1602    {
1603      String dnString = reader.readOctetStringAsString();
1604      if (dnString.length() == 0)
1605      {
1606        matchedDN = null;
1607      }
1608      else
1609      {
1610        matchedDN = DN.valueOf(dnString);
1611      }
1612    }
1613    catch (Exception e)
1614    {
1615      logger.traceException(e);
1616
1617      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(e);
1618      throw new LDAPException(PROTOCOL_ERROR, message, e);
1619    }
1620
1621
1622    LocalizableMessage errorMessage;
1623    try
1624    {
1625      errorMessage = LocalizableMessage.raw(reader.readOctetStringAsString());
1626      if (errorMessage.length() == 0)
1627      {
1628        errorMessage = null;
1629      }
1630    }
1631    catch (Exception e)
1632    {
1633      logger.traceException(e);
1634
1635      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(e);
1636      throw new LDAPException(PROTOCOL_ERROR, message, e);
1637    }
1638
1639    ArrayList<String> referralURLs = null;
1640
1641    try
1642    {
1643      if (reader.hasNextElement())
1644      {
1645        reader.readStartSequence();
1646        referralURLs = new ArrayList<>();
1647
1648        while(reader.hasNextElement())
1649        {
1650          referralURLs.add(reader.readOctetStringAsString());
1651        }
1652        reader.readEndSequence();
1653      }
1654    }
1655    catch (Exception e)
1656    {
1657      logger.traceException(e);
1658
1659      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_REFERRALS.get(e);
1660      throw new LDAPException(PROTOCOL_ERROR, message, e);
1661    }
1662
1663    try
1664    {
1665      reader.readEndSequence();
1666    }
1667    catch (Exception e)
1668    {
1669      logger.traceException(e);
1670
1671      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
1672      throw new LDAPException(PROTOCOL_ERROR, message, e);
1673    }
1674
1675    return new ModifyDNResponseProtocolOp(resultCode, errorMessage, matchedDN,
1676        referralURLs);
1677  }
1678
1679  /**
1680   * Decodes the elements from the provided ASN.1 reader as an LDAP
1681   * modify request protocol op.
1682   *
1683   * @param  reader The ASN.1 reader.
1684   *
1685   * @return  The decoded modify request protocol op.
1686   *
1687   * @throws  LDAPException  If a problem occurs while decoding the provided
1688   *                         ASN.1 element as an LDAP modify request protocol
1689   *                         op.
1690   */
1691  private static ModifyRequestProtocolOp readModifyRequest(ASN1Reader reader)
1692      throws LDAPException
1693  {
1694    try
1695    {
1696      reader.readStartSequence();
1697    }
1698    catch (Exception e)
1699    {
1700      logger.traceException(e);
1701
1702      LocalizableMessage message = ERR_LDAP_MODIFY_REQUEST_DECODE_SEQUENCE.get(e);
1703      throw new LDAPException(PROTOCOL_ERROR, message, e);
1704    }
1705
1706    ByteString dn;
1707    try
1708    {
1709      dn = reader.readOctetString();
1710    }
1711    catch (Exception e)
1712    {
1713      logger.traceException(e);
1714
1715      LocalizableMessage message = ERR_LDAP_MODIFY_REQUEST_DECODE_DN.get(e);
1716      throw new LDAPException(PROTOCOL_ERROR, message, e);
1717    }
1718
1719
1720
1721    ArrayList<RawModification> modifications;
1722    try
1723    {
1724      reader.readStartSequence();
1725      modifications = new ArrayList<>();
1726      while(reader.hasNextElement())
1727      {
1728        modifications.add(LDAPModification.decode(reader));
1729      }
1730      reader.readEndSequence();
1731    }
1732    catch (Exception e)
1733    {
1734      logger.traceException(e);
1735
1736      LocalizableMessage message = ERR_LDAP_MODIFY_REQUEST_DECODE_MODS.get(e);
1737      throw new LDAPException(PROTOCOL_ERROR, message, e);
1738    }
1739
1740    try
1741    {
1742      reader.readEndSequence();
1743    }
1744    catch (Exception e)
1745    {
1746      logger.traceException(e);
1747
1748      LocalizableMessage message = ERR_LDAP_MODIFY_REQUEST_DECODE_SEQUENCE.get(e);
1749      throw new LDAPException(PROTOCOL_ERROR, message, e);
1750    }
1751
1752
1753    return new ModifyRequestProtocolOp(dn, modifications);
1754  }
1755
1756  /**
1757   * Decodes the elements from the provided ASN.1 reader as a modify
1758   * response protocol op.
1759   *
1760   * @param  reader The ASN.1 reader.
1761   *
1762   * @return  The decoded modify response protocol op.
1763   *
1764   * @throws  LDAPException  If a problem occurs while attempting to decode the
1765   *                         ASN.1 element to a protocol op.
1766   */
1767  private static ModifyResponseProtocolOp readModifyResponse(ASN1Reader
1768      reader)
1769      throws LDAPException
1770  {
1771    try
1772    {
1773      reader.readStartSequence();
1774    }
1775    catch (Exception e)
1776    {
1777      logger.traceException(e);
1778
1779      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
1780      throw new LDAPException(PROTOCOL_ERROR, message, e);
1781    }
1782
1783    int resultCode;
1784    try
1785    {
1786      resultCode = (int)reader.readInteger();
1787    }
1788    catch (Exception e)
1789    {
1790      logger.traceException(e);
1791
1792      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(e);
1793      throw new LDAPException(PROTOCOL_ERROR, message, e);
1794    }
1795
1796
1797    DN matchedDN;
1798    try
1799    {
1800      String dnString = reader.readOctetStringAsString();
1801      if (dnString.length() == 0)
1802      {
1803        matchedDN = null;
1804      }
1805      else
1806      {
1807        matchedDN = DN.valueOf(dnString);
1808      }
1809    }
1810    catch (Exception e)
1811    {
1812      logger.traceException(e);
1813
1814      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(e);
1815      throw new LDAPException(PROTOCOL_ERROR, message, e);
1816    }
1817
1818
1819    LocalizableMessage errorMessage;
1820    try
1821    {
1822      errorMessage = LocalizableMessage.raw(reader.readOctetStringAsString());
1823      if (errorMessage.length() == 0)
1824      {
1825        errorMessage = null;
1826      }
1827    }
1828    catch (Exception e)
1829    {
1830      logger.traceException(e);
1831
1832      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(e);
1833      throw new LDAPException(PROTOCOL_ERROR, message, e);
1834    }
1835
1836    ArrayList<String> referralURLs = null;
1837
1838    try
1839    {
1840      if (reader.hasNextElement())
1841      {
1842        reader.readStartSequence();
1843        referralURLs = new ArrayList<>();
1844
1845        while(reader.hasNextElement())
1846        {
1847          referralURLs.add(reader.readOctetStringAsString());
1848        }
1849        reader.readEndSequence();
1850      }
1851    }
1852    catch (Exception e)
1853    {
1854      logger.traceException(e);
1855
1856      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_REFERRALS.get(e);
1857      throw new LDAPException(PROTOCOL_ERROR, message, e);
1858    }
1859
1860    try
1861    {
1862      reader.readEndSequence();
1863    }
1864    catch (Exception e)
1865    {
1866      logger.traceException(e);
1867
1868      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
1869      throw new LDAPException(PROTOCOL_ERROR, message, e);
1870    }
1871
1872    return new ModifyResponseProtocolOp(resultCode, errorMessage, matchedDN,
1873        referralURLs);
1874  }
1875
1876  /**
1877   * Decodes the elements from the provided ASN.1 reader as an LDAP search
1878   * request protocol op.
1879   *
1880   * @param  reader The ASN.1 reader.
1881   *
1882   * @return  The decoded LDAP search request protocol op.
1883   *
1884   * @throws  LDAPException  If a problem occurs while decoding the provided
1885   *                         ASN.1 element as an LDAP search request protocol
1886   *                         op.
1887   */
1888  private static SearchRequestProtocolOp readSearchRequest(ASN1Reader reader)
1889      throws LDAPException
1890  {
1891    try
1892    {
1893      reader.readStartSequence();
1894    }
1895    catch (Exception e)
1896    {
1897      logger.traceException(e);
1898
1899      LocalizableMessage message = ERR_LDAP_SEARCH_REQUEST_DECODE_SEQUENCE.get(e);
1900      throw new LDAPException(PROTOCOL_ERROR, message, e);
1901    }
1902
1903    ByteString baseDN;
1904    try
1905    {
1906      baseDN = reader.readOctetString();
1907    }
1908    catch (Exception e)
1909    {
1910      logger.traceException(e);
1911
1912      LocalizableMessage message = ERR_LDAP_SEARCH_REQUEST_DECODE_BASE.get(e);
1913      throw new LDAPException(PROTOCOL_ERROR, message, e);
1914    }
1915
1916
1917    SearchScope scope;
1918    try
1919    {
1920      int scopeValue = (int)reader.readInteger();
1921      switch (scopeValue)
1922      {
1923        case SCOPE_BASE_OBJECT:
1924          scope = SearchScope.BASE_OBJECT;
1925          break;
1926        case SCOPE_SINGLE_LEVEL:
1927          scope = SearchScope.SINGLE_LEVEL;
1928          break;
1929        case SCOPE_WHOLE_SUBTREE:
1930          scope = SearchScope.WHOLE_SUBTREE;
1931          break;
1932        case SCOPE_SUBORDINATE_SUBTREE:
1933          scope = SearchScope.SUBORDINATES;
1934          break;
1935        default:
1936          LocalizableMessage message =
1937              ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_SCOPE.get(scopeValue);
1938          throw new LDAPException(PROTOCOL_ERROR, message);
1939      }
1940    }
1941    catch (LDAPException le)
1942    {
1943      throw le;
1944    }
1945    catch (Exception e)
1946    {
1947      logger.traceException(e);
1948
1949      LocalizableMessage message = ERR_LDAP_SEARCH_REQUEST_DECODE_SCOPE.get(e);
1950      throw new LDAPException(PROTOCOL_ERROR, message, e);
1951    }
1952
1953
1954    DereferenceAliasesPolicy dereferencePolicy;
1955    try
1956    {
1957      int derefValue = (int)reader.readInteger();
1958      switch (derefValue)
1959      {
1960        case DEREF_NEVER:
1961        case DEREF_IN_SEARCHING:
1962        case DEREF_FINDING_BASE:
1963        case DEREF_ALWAYS:
1964          dereferencePolicy = DereferenceAliasesPolicy.valueOf(derefValue);
1965          break;
1966        default:
1967          LocalizableMessage message =
1968              ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_DEREF.get(derefValue);
1969          throw new LDAPException(PROTOCOL_ERROR, message);
1970      }
1971    }
1972    catch (LDAPException le)
1973    {
1974      throw le;
1975    }
1976    catch (Exception e)
1977    {
1978      logger.traceException(e);
1979
1980      LocalizableMessage message = ERR_LDAP_SEARCH_REQUEST_DECODE_DEREF.get(e);
1981      throw new LDAPException(PROTOCOL_ERROR, message, e);
1982    }
1983
1984
1985    int sizeLimit;
1986    try
1987    {
1988      sizeLimit = (int)reader.readInteger();
1989    }
1990    catch (Exception e)
1991    {
1992      logger.traceException(e);
1993
1994      LocalizableMessage message = ERR_LDAP_SEARCH_REQUEST_DECODE_SIZE_LIMIT.get(e);
1995      throw new LDAPException(PROTOCOL_ERROR, message, e);
1996    }
1997
1998
1999    int timeLimit;
2000    try
2001    {
2002      timeLimit = (int)reader.readInteger();
2003    }
2004    catch (Exception e)
2005    {
2006      logger.traceException(e);
2007
2008      LocalizableMessage message = ERR_LDAP_SEARCH_REQUEST_DECODE_TIME_LIMIT.get(e);
2009      throw new LDAPException(PROTOCOL_ERROR, message, e);
2010    }
2011
2012
2013    boolean typesOnly;
2014    try
2015    {
2016      typesOnly = reader.readBoolean();
2017    }
2018    catch (Exception e)
2019    {
2020      logger.traceException(e);
2021
2022      LocalizableMessage message = ERR_LDAP_SEARCH_REQUEST_DECODE_TYPES_ONLY.get(e);
2023      throw new LDAPException(PROTOCOL_ERROR, message, e);
2024    }
2025
2026    RawFilter filter;
2027    try
2028    {
2029      filter = RawFilter.decode(reader);
2030    }
2031    catch (Exception e)
2032    {
2033      logger.traceException(e);
2034
2035      LocalizableMessage message = ERR_LDAP_SEARCH_REQUEST_DECODE_FILTER.get(e);
2036      throw new LDAPException(PROTOCOL_ERROR, message, e);
2037    }
2038
2039
2040    LinkedHashSet<String> attributes;
2041    try
2042    {
2043      reader.readStartSequence();
2044      attributes = new LinkedHashSet<>();
2045      while(reader.hasNextElement())
2046      {
2047        attributes.add(reader.readOctetStringAsString());
2048      }
2049      reader.readEndSequence();
2050    }
2051    catch (Exception e)
2052    {
2053      logger.traceException(e);
2054
2055      LocalizableMessage message = ERR_LDAP_SEARCH_REQUEST_DECODE_ATTRIBUTES.get(e);
2056      throw new LDAPException(PROTOCOL_ERROR, message, e);
2057    }
2058
2059    try
2060    {
2061      reader.readEndSequence();
2062    }
2063    catch (Exception e)
2064    {
2065      logger.traceException(e);
2066
2067      LocalizableMessage message = ERR_LDAP_SEARCH_REQUEST_DECODE_SEQUENCE.get(e);
2068      throw new LDAPException(PROTOCOL_ERROR, message, e);
2069    }
2070
2071    return new SearchRequestProtocolOp(baseDN, scope, dereferencePolicy,
2072        sizeLimit, timeLimit, typesOnly, filter,
2073        attributes);
2074  }
2075
2076  /**
2077   * Decodes the elements from the provided ASN.1 reader as a search
2078   * result done protocol op.
2079   *
2080   * @param  reader The ASN.1 reader
2081   *
2082   * @return  The decoded search result done protocol op.
2083   *
2084   * @throws  LDAPException  If a problem occurs while attempting to decode the
2085   *                         ASN.1 element to a protocol op.
2086   */
2087  private static SearchResultDoneProtocolOp readSearchDone(ASN1Reader
2088      reader)
2089      throws LDAPException
2090  {
2091    try
2092    {
2093      reader.readStartSequence();
2094    }
2095    catch (Exception e)
2096    {
2097      logger.traceException(e);
2098
2099      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
2100      throw new LDAPException(PROTOCOL_ERROR, message, e);
2101    }
2102
2103    int resultCode;
2104    try
2105    {
2106      resultCode = (int)reader.readInteger();
2107    }
2108    catch (Exception e)
2109    {
2110      logger.traceException(e);
2111
2112      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(e);
2113      throw new LDAPException(PROTOCOL_ERROR, message, e);
2114    }
2115
2116
2117    DN matchedDN;
2118    try
2119    {
2120      String dnString = reader.readOctetStringAsString();
2121      if (dnString.length() == 0)
2122      {
2123        matchedDN = null;
2124      }
2125      else
2126      {
2127        matchedDN = DN.valueOf(dnString);
2128      }
2129    }
2130    catch (Exception e)
2131    {
2132      logger.traceException(e);
2133
2134      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(e);
2135      throw new LDAPException(PROTOCOL_ERROR, message, e);
2136    }
2137
2138
2139    LocalizableMessage errorMessage;
2140    try
2141    {
2142      errorMessage = LocalizableMessage.raw(reader.readOctetStringAsString());
2143      if (errorMessage.length() == 0)
2144      {
2145        errorMessage = null;
2146      }
2147    }
2148    catch (Exception e)
2149    {
2150      logger.traceException(e);
2151
2152      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(e);
2153      throw new LDAPException(PROTOCOL_ERROR, message, e);
2154    }
2155
2156    ArrayList<String> referralURLs = null;
2157
2158    try
2159    {
2160      if (reader.hasNextElement())
2161      {
2162        reader.readStartSequence();
2163        referralURLs = new ArrayList<>();
2164
2165        while(reader.hasNextElement())
2166        {
2167          referralURLs.add(reader.readOctetStringAsString());
2168        }
2169        reader.readEndSequence();
2170      }
2171    }
2172    catch (Exception e)
2173    {
2174      logger.traceException(e);
2175
2176      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_REFERRALS.get(e);
2177      throw new LDAPException(PROTOCOL_ERROR, message, e);
2178    }
2179
2180    try
2181    {
2182      reader.readEndSequence();
2183    }
2184    catch (Exception e)
2185    {
2186      logger.traceException(e);
2187
2188      LocalizableMessage message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(e);
2189      throw new LDAPException(PROTOCOL_ERROR, message, e);
2190    }
2191
2192    return new SearchResultDoneProtocolOp(resultCode, errorMessage, matchedDN,
2193        referralURLs);
2194  }
2195
2196  /**
2197   * Decodes the elements from the provided ASN.1 reader as an LDAP search
2198   * result entry protocol op.
2199   *
2200   * @param  reader The ASN.1 reader.
2201   *
2202   * @return  The decoded search result entry protocol op.
2203   *
2204   * @throws  LDAPException  If a problem occurs while decoding the provided
2205   *                         ASN.1 element as an LDAP search result entry
2206   *                         protocol op.
2207   */
2208  public static SearchResultEntryProtocolOp readSearchEntry(ASN1Reader
2209      reader)
2210      throws LDAPException
2211  {
2212    try
2213    {
2214      reader.readStartSequence();
2215    }
2216    catch (Exception e)
2217    {
2218      logger.traceException(e);
2219
2220      LocalizableMessage message = ERR_LDAP_SEARCH_ENTRY_DECODE_SEQUENCE.get(e);
2221      throw new LDAPException(PROTOCOL_ERROR, message, e);
2222    }
2223
2224
2225    DN dn;
2226    try
2227    {
2228      dn = DN.valueOf(reader.readOctetStringAsString());
2229    }
2230    catch (Exception e)
2231    {
2232      logger.traceException(e);
2233
2234      LocalizableMessage message = ERR_LDAP_SEARCH_ENTRY_DECODE_DN.get(e);
2235      throw new LDAPException(PROTOCOL_ERROR, message, e);
2236    }
2237
2238
2239
2240    LinkedList<LDAPAttribute> attributes;
2241    try
2242    {
2243      reader.readStartSequence();
2244      attributes = new LinkedList<>();
2245      while(reader.hasNextElement())
2246      {
2247        attributes.add(LDAPAttribute.decode(reader));
2248      }
2249      reader.readEndSequence();
2250    }
2251    catch (Exception e)
2252    {
2253      logger.traceException(e);
2254
2255      LocalizableMessage message = ERR_LDAP_SEARCH_ENTRY_DECODE_ATTRS.get(e);
2256      throw new LDAPException(PROTOCOL_ERROR, message, e);
2257    }
2258
2259    try
2260    {
2261      reader.readEndSequence();
2262    }
2263    catch (Exception e)
2264    {
2265      logger.traceException(e);
2266
2267      LocalizableMessage message = ERR_LDAP_SEARCH_ENTRY_DECODE_SEQUENCE.get(e);
2268      throw new LDAPException(PROTOCOL_ERROR, message, e);
2269    }
2270
2271
2272    return new SearchResultEntryProtocolOp(dn, attributes);
2273  }
2274
2275  /**
2276   * Decodes the elements from the provided ASN.1 reader as a search
2277   * result reference protocol op.
2278   *
2279   * @param  reader The ASN.1 reader.
2280   *
2281   * @return  The decoded search result reference protocol op.
2282   *
2283   * @throws  LDAPException  If a problem occurs while decoding the provided
2284   *                         ASN.1 element as an LDAP search result reference
2285   *                         protocol op.
2286   */
2287  private static SearchResultReferenceProtocolOp
2288  readSearchReference(ASN1Reader reader)
2289      throws LDAPException
2290  {
2291    try
2292    {
2293      reader.readStartSequence();
2294    }
2295    catch (Exception e)
2296    {
2297      logger.traceException(e);
2298
2299      LocalizableMessage message = ERR_LDAP_SEARCH_REFERENCE_DECODE_SEQUENCE.get(e);
2300      throw new LDAPException(PROTOCOL_ERROR, message, e);
2301    }
2302
2303
2304    ArrayList<String> referralURLs = new ArrayList<>();
2305    try
2306    {
2307      // Should have atleast 1 URL.
2308      do
2309      {
2310        referralURLs.add(reader.readOctetStringAsString());
2311      }
2312      while(reader.hasNextElement());
2313    }
2314    catch (Exception e)
2315    {
2316      logger.traceException(e);
2317
2318      LocalizableMessage message = ERR_LDAP_SEARCH_REFERENCE_DECODE_URLS.get(e);
2319      throw new LDAPException(PROTOCOL_ERROR, message, e);
2320    }
2321
2322    try
2323    {
2324      reader.readEndSequence();
2325    }
2326    catch (Exception e)
2327    {
2328      logger.traceException(e);
2329
2330      LocalizableMessage message = ERR_LDAP_SEARCH_REFERENCE_DECODE_SEQUENCE.get(e);
2331      throw new LDAPException(PROTOCOL_ERROR, message, e);
2332    }
2333
2334    return new SearchResultReferenceProtocolOp(referralURLs);
2335  }
2336
2337  /**
2338   * Decodes the elements from the provided ASN.1 read as an LDAP unbind
2339   * request protocol op.
2340   *
2341   * @param  reader The ASN.1 reader.
2342   *
2343   * @return  The decoded LDAP unbind request protocol op.
2344   *
2345   * @throws  LDAPException  If the provided ASN.1 element cannot be decoded as
2346   *                         an unbind request protocol op.
2347   */
2348  private static UnbindRequestProtocolOp readUnbindRequest(ASN1Reader reader)
2349      throws LDAPException
2350  {
2351    try
2352    {
2353      reader.readNull();
2354      return new UnbindRequestProtocolOp();
2355    }
2356    catch (Exception e)
2357    {
2358      logger.traceException(e);
2359
2360      LocalizableMessage message = ERR_LDAP_UNBIND_DECODE.get(e);
2361      throw new LDAPException(PROTOCOL_ERROR, message, e);
2362    }
2363  }
2364
2365  /**
2366   * Decodes the elements from the provided ASN.1 reader as a set of controls.
2367   *
2368   * @param  reader The ASN.1 reader.
2369   *
2370   * @return  The decoded set of controls.
2371   *
2372   * @throws  LDAPException  If a problem occurs while attempting to decode the
2373   *                         controls.
2374   */
2375  private static ArrayList<Control> readControls(ASN1Reader reader)
2376      throws LDAPException
2377  {
2378    try
2379    {
2380      reader.readStartSequence();
2381      ArrayList<Control> controls = new ArrayList<>();
2382      while(reader.hasNextElement())
2383      {
2384        controls.add(readControl(reader));
2385      }
2386
2387      reader.readEndSequence();
2388      return controls;
2389    }
2390    catch (Exception e)
2391    {
2392      LocalizableMessage message = ERR_LDAP_CONTROL_DECODE_CONTROLS_SEQUENCE.get(e);
2393      throw new LDAPException(PROTOCOL_ERROR, message, e);
2394    }
2395  }
2396
2397  /**
2398   * Decodes the elements from the provided ASN.1 reader as an LDAP control.
2399   *
2400   * @param  reader The ASN.1 reader.
2401   *
2402   * @return  The decoded LDAP control.
2403   *
2404   * @throws  LDAPException  If a problem occurs while attempting to decode the
2405   *                         provided ASN.1 element as an LDAP control.
2406   */
2407  public static LDAPControl readControl(ASN1Reader reader)
2408      throws LDAPException
2409  {
2410    try
2411    {
2412      reader.readStartSequence();
2413    }
2414    catch (Exception e)
2415    {
2416      logger.traceException(e);
2417
2418      LocalizableMessage message = ERR_LDAP_CONTROL_DECODE_SEQUENCE.get(e);
2419      throw new LDAPException(PROTOCOL_ERROR, message, e);
2420    }
2421
2422
2423    String oid;
2424    try
2425    {
2426      oid = reader.readOctetStringAsString();
2427    }
2428    catch (Exception e)
2429    {
2430      logger.traceException(e);
2431
2432      LocalizableMessage message = ERR_LDAP_CONTROL_DECODE_OID.get(e);
2433      throw new LDAPException(PROTOCOL_ERROR, message, e);
2434    }
2435
2436    boolean isCritical = false;
2437    ByteString value = null;
2438    try
2439    {
2440      if(reader.hasNextElement() &&
2441          reader.peekType() == ASN1.UNIVERSAL_BOOLEAN_TYPE)
2442      {
2443        try
2444        {
2445          isCritical = reader.readBoolean();
2446        }
2447        catch (Exception e2)
2448        {
2449          logger.traceException(e2);
2450
2451          LocalizableMessage message = ERR_LDAP_CONTROL_DECODE_CRITICALITY.get(e2);
2452          throw new LDAPException(PROTOCOL_ERROR, message, e2);
2453        }
2454      }
2455      if(reader.hasNextElement() &&
2456          reader.peekType() == ASN1.UNIVERSAL_OCTET_STRING_TYPE)
2457      {
2458        try
2459        {
2460          value = reader.readOctetString();
2461        }
2462        catch (Exception e2)
2463        {
2464          logger.traceException(e2);
2465
2466          LocalizableMessage message = ERR_LDAP_CONTROL_DECODE_VALUE.get(e2);
2467          throw new LDAPException(PROTOCOL_ERROR, message, e2);
2468        }
2469      }
2470    }
2471    catch(IOException e)
2472    {
2473      logger.traceException(e);
2474    }
2475
2476    try
2477    {
2478      reader.readEndSequence();
2479    }
2480    catch (Exception e)
2481    {
2482      logger.traceException(e);
2483
2484      LocalizableMessage message = ERR_LDAP_CONTROL_DECODE_SEQUENCE.get(e);
2485      throw new LDAPException(PROTOCOL_ERROR, message, e);
2486    }
2487
2488    return new LDAPControl(oid, isCritical, value);
2489  }
2490}