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.DN;
041    import org.opends.server.types.DebugLogLevel;
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 delete response
055     * protocol op, which is used to provide information about the result of
056     * processing a delete request.
057     */
058    public class BindResponseProtocolOp
059           extends ProtocolOp
060    {
061      /**
062       * The tracer object for the debug logger.
063       */
064      private static final DebugTracer TRACER = getTracer();
065    
066      // The server SASL credentials for this response.
067      private ASN1OctetString serverSASLCredentials;
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    
082    
083      /**
084       * Creates a new bind response protocol op with the provided result code.
085       *
086       * @param  resultCode  The result code for this response.
087       */
088      public BindResponseProtocolOp(int resultCode)
089      {
090        this.resultCode = resultCode;
091    
092        errorMessage          = null;
093        matchedDN             = null;
094        referralURLs          = null;
095        serverSASLCredentials = null;
096      }
097    
098    
099    
100      /**
101       * Creates a new bind response protocol op with the provided result code and
102       * error message.
103       *
104       * @param  resultCode    The result code for this response.
105       * @param  errorMessage  The error message for this response.
106       */
107      public BindResponseProtocolOp(int resultCode, Message errorMessage)
108      {
109        this.resultCode   = resultCode;
110        this.errorMessage = errorMessage;
111    
112        matchedDN             = null;
113        referralURLs          = null;
114        serverSASLCredentials = null;
115      }
116    
117    
118    
119      /**
120       * Creates a new bind response protocol op with the provided information.
121       *
122       * @param  resultCode    The result code for this response.
123       * @param  errorMessage  The error message for this response.
124       * @param  matchedDN     The matched DN for this response.
125       * @param  referralURLs  The referral URLs for this response.
126       */
127      public BindResponseProtocolOp(int resultCode, Message errorMessage,
128                                    DN matchedDN, List<String> referralURLs)
129      {
130        this.resultCode   = resultCode;
131        this.errorMessage = errorMessage;
132        this.matchedDN    = matchedDN;
133        this.referralURLs = referralURLs;
134    
135        serverSASLCredentials = null;
136      }
137    
138    
139    
140      /**
141       * Creates a new bind response protocol op with the provided information.
142       *
143       * @param  resultCode             The result code for this response.
144       * @param  errorMessage           The error message for this response.
145       * @param  matchedDN              The matched DN for this response.
146       * @param  referralURLs           The referral URLs for this response.
147       * @param  serverSASLCredentials  The server SASL credentials for this
148       */
149      public BindResponseProtocolOp(int resultCode, Message errorMessage,
150                                    DN matchedDN, List<String> referralURLs,
151                                    ASN1OctetString serverSASLCredentials)
152      {
153        this.resultCode            = resultCode;
154        this.errorMessage          = errorMessage;
155        this.matchedDN             = matchedDN;
156        this.referralURLs          = referralURLs;
157        this.serverSASLCredentials = serverSASLCredentials;
158      }
159    
160    
161    
162      /**
163       * Retrieves the result code for this response.
164       *
165       * @return  The result code for this response.
166       */
167      public int getResultCode()
168      {
169        return resultCode;
170      }
171    
172    
173    
174      /**
175       * Specifies the result code for this response.
176       *
177       * @param  resultCode  The result code for this response.
178       */
179      public void setResultCode(int resultCode)
180      {
181        this.resultCode = resultCode;
182      }
183    
184    
185    
186      /**
187       * Retrieves the error message for this response.
188       *
189       * @return  The error message for this response, or <CODE>null</CODE> if none
190       *          is available.
191       */
192      public Message getErrorMessage()
193      {
194        return errorMessage;
195      }
196    
197    
198    
199      /**
200       * Specifies the error message for this response.
201       *
202       * @param  errorMessage  The error message for this response.
203       */
204      public void setErrorMessage(Message errorMessage)
205      {
206        this.errorMessage = errorMessage;
207      }
208    
209    
210    
211      /**
212       * Retrieves the matched DN for this response.
213       *
214       * @return  The matched DN for this response, or <CODE>null</CODE> if none is
215       *          available.
216       */
217      public DN getMatchedDN()
218      {
219        return matchedDN;
220      }
221    
222    
223    
224      /**
225       * Specifies the matched DN for this response.
226       *
227       * @param  matchedDN  The matched DN for this response.
228       */
229      public void setMatchedDN(DN matchedDN)
230      {
231        this.matchedDN = matchedDN;
232      }
233    
234    
235    
236      /**
237       * Retrieves the set of referral URLs for this response.
238       *
239       * @return  The set of referral URLs for this response, or <CODE>null</CODE>
240       *          if none are available.
241       */
242      public List<String> getReferralURLs()
243      {
244        return referralURLs;
245      }
246    
247    
248    
249      /**
250       * Specifies the set of referral URLs for this response.
251       *
252       * @param  referralURLs  The set of referral URLs for this response.
253       */
254      public void setReferralURLs(List<String> referralURLs)
255      {
256        this.referralURLs = referralURLs;
257      }
258    
259    
260    
261      /**
262       * Retrieves the server SASL credentials for this response.
263       *
264       * @return  The server SASL credentials for this response, or
265       *          <CODE>null</CODE> if there are none.
266       */
267      public ASN1OctetString getServerSASLCredentials()
268      {
269        return serverSASLCredentials;
270      }
271    
272    
273    
274      /**
275       * Specifies the server SASL credentials for this response.
276       *
277       * @param  serverSASLCredentials  The server SASL credentials for this
278       *                                response.
279       */
280      public void setServerSASLCredentials(ASN1OctetString serverSASLCredentials)
281      {
282        this.serverSASLCredentials = serverSASLCredentials;
283      }
284    
285    
286    
287      /**
288       * Retrieves the BER type for this protocol op.
289       *
290       * @return  The BER type for this protocol op.
291       */
292      public byte getType()
293      {
294        return OP_TYPE_BIND_RESPONSE;
295      }
296    
297    
298    
299      /**
300       * Retrieves the name for this protocol op type.
301       *
302       * @return  The name for this protocol op type.
303       */
304      public String getProtocolOpName()
305      {
306        return "Bind Response";
307      }
308    
309    
310    
311      /**
312       * Encodes this protocol op to an ASN.1 element suitable for including in an
313       * LDAP message.
314       *
315       * @return  The ASN.1 element containing the encoded protocol op.
316       */
317      public ASN1Element encode()
318      {
319        ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(5);
320        elements.add(new ASN1Enumerated(resultCode));
321    
322        if (matchedDN == null)
323        {
324          elements.add(new ASN1OctetString());
325        }
326        else
327        {
328          elements.add(new ASN1OctetString(matchedDN.toString()));
329        }
330    
331        elements.add(new ASN1OctetString(errorMessage));
332    
333        if ((referralURLs != null) && (! referralURLs.isEmpty()))
334        {
335          ArrayList<ASN1Element> referralElements =
336               new ArrayList<ASN1Element>(referralURLs.size());
337    
338          for (String s : referralURLs)
339          {
340            referralElements.add(new ASN1OctetString(s));
341          }
342    
343          elements.add(new ASN1Sequence(TYPE_REFERRAL_SEQUENCE, referralElements));
344        }
345    
346        if (serverSASLCredentials != null)
347        {
348          serverSASLCredentials.setType(TYPE_SERVER_SASL_CREDENTIALS);
349          elements.add(serverSASLCredentials);
350        }
351    
352        return new ASN1Sequence(OP_TYPE_BIND_RESPONSE, elements);
353      }
354    
355    
356    
357      /**
358       * Decodes the provided ASN.1 element as a bind response protocol op.
359       *
360       * @param  element  The ASN.1 element to decode.
361       *
362       * @return  The decoded bind response protocol op.
363       *
364       * @throws  LDAPException  If a problem occurs while attempting to decode the
365       *                         ASN.1 element to a protocol op.
366       */
367      public static BindResponseProtocolOp decodeBindResponse(ASN1Element element)
368             throws LDAPException
369      {
370        ArrayList<ASN1Element> elements;
371        try
372        {
373          elements = element.decodeAsSequence().elements();
374        }
375        catch (Exception e)
376        {
377          if (debugEnabled())
378          {
379            TRACER.debugCaught(DebugLogLevel.ERROR, e);
380          }
381    
382          Message message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(String.valueOf(e));
383          throw new LDAPException(PROTOCOL_ERROR, message, e);
384        }
385    
386    
387        int numElements = elements.size();
388        if ((numElements < 3) || (numElements > 5))
389        {
390          Message message =
391              ERR_LDAP_BIND_RESULT_DECODE_INVALID_ELEMENT_COUNT.get(numElements);
392          throw new LDAPException(PROTOCOL_ERROR, message);
393        }
394    
395    
396        int resultCode;
397        try
398        {
399          resultCode = elements.get(0).decodeAsInteger().intValue();
400        }
401        catch (Exception e)
402        {
403          if (debugEnabled())
404          {
405            TRACER.debugCaught(DebugLogLevel.ERROR, e);
406          }
407    
408          Message message =
409              ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(String.valueOf(e));
410          throw new LDAPException(PROTOCOL_ERROR, message, e);
411        }
412    
413    
414        DN matchedDN;
415        try
416        {
417          String dnString = elements.get(1).decodeAsOctetString().stringValue();
418          if (dnString.length() == 0)
419          {
420            matchedDN = null;
421          }
422          else
423          {
424            matchedDN = DN.decode(dnString);
425          }
426        }
427        catch (Exception e)
428        {
429          if (debugEnabled())
430          {
431            TRACER.debugCaught(DebugLogLevel.ERROR, e);
432          }
433    
434          Message message =
435              ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(String.valueOf(e));
436          throw new LDAPException(PROTOCOL_ERROR, message, e);
437        }
438    
439    
440        Message errorMessage;
441        try
442        {
443          errorMessage =
444                  Message.raw(elements.get(2).decodeAsOctetString().stringValue());
445          if (errorMessage.length() == 0)
446          {
447            errorMessage = null;
448          }
449        }
450        catch (Exception e)
451        {
452          if (debugEnabled())
453          {
454            TRACER.debugCaught(DebugLogLevel.ERROR, e);
455          }
456    
457          Message message =
458              ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(String.valueOf(e));
459          throw new LDAPException(PROTOCOL_ERROR, message, e);
460        }
461    
462    
463        ArrayList<String> referralURLs;
464        ASN1OctetString   serverSASLCredentials;
465        switch (numElements)
466        {
467          case 4:
468            element = elements.get(3);
469            switch (element.getType())
470            {
471              case TYPE_REFERRAL_SEQUENCE:
472                serverSASLCredentials = null;
473    
474                try
475                {
476                  ArrayList<ASN1Element> referralElements =
477                       element.decodeAsSequence().elements();
478                  referralURLs = new ArrayList<String>(referralElements.size());
479    
480                  for (ASN1Element e : referralElements)
481                  {
482                    referralURLs.add(e.decodeAsOctetString().stringValue());
483                  }
484                }
485                catch (Exception e)
486                {
487                  if (debugEnabled())
488                  {
489                    TRACER.debugCaught(DebugLogLevel.ERROR, e);
490                  }
491    
492                  Message message =
493                      ERR_LDAP_RESULT_DECODE_REFERRALS.get(String.valueOf(e));
494                  throw new LDAPException(PROTOCOL_ERROR, message, e);
495                }
496    
497                break;
498              case TYPE_SERVER_SASL_CREDENTIALS:
499                referralURLs = null;
500    
501                try
502                {
503                  serverSASLCredentials = element.decodeAsOctetString();
504                }
505                catch (Exception e)
506                {
507                  if (debugEnabled())
508                  {
509                    TRACER.debugCaught(DebugLogLevel.ERROR, e);
510                  }
511    
512                  Message message =
513                      ERR_LDAP_BIND_RESULT_DECODE_SERVER_SASL_CREDENTIALS.
514                        get(String.valueOf(e));
515                  throw new LDAPException(PROTOCOL_ERROR, message, e);
516                }
517    
518                break;
519              default:
520                Message message =
521                    ERR_LDAP_BIND_RESULT_DECODE_INVALID_TYPE.get(element.getType());
522                throw new LDAPException(PROTOCOL_ERROR, message);
523            }
524            break;
525          case 5:
526            try
527            {
528              ArrayList<ASN1Element> referralElements =
529                   elements.get(3).decodeAsSequence().elements();
530              referralURLs = new ArrayList<String>(referralElements.size());
531    
532              for (ASN1Element e : referralElements)
533              {
534                referralURLs.add(e.decodeAsOctetString().stringValue());
535              }
536            }
537            catch (Exception e)
538            {
539              if (debugEnabled())
540              {
541                TRACER.debugCaught(DebugLogLevel.ERROR, e);
542              }
543    
544              Message message =
545                  ERR_LDAP_RESULT_DECODE_REFERRALS.get(String.valueOf(e));
546              throw new LDAPException(PROTOCOL_ERROR, message, e);
547            }
548    
549            try
550            {
551              serverSASLCredentials = elements.get(4).decodeAsOctetString();
552            }
553            catch (Exception e)
554            {
555              if (debugEnabled())
556              {
557                TRACER.debugCaught(DebugLogLevel.ERROR, e);
558              }
559    
560              Message message = ERR_LDAP_BIND_RESULT_DECODE_SERVER_SASL_CREDENTIALS.
561                  get(String.valueOf(e));
562              throw new LDAPException(PROTOCOL_ERROR, message, e);
563            }
564    
565            break;
566          default:
567            referralURLs          = null;
568            serverSASLCredentials = null;
569            break;
570        }
571    
572    
573        return new BindResponseProtocolOp(resultCode, errorMessage, matchedDN,
574                                          referralURLs, serverSASLCredentials);
575      }
576    
577    
578    
579      /**
580       * Appends a string representation of this LDAP protocol op to the provided
581       * buffer.
582       *
583       * @param  buffer  The buffer to which the string should be appended.
584       */
585      public void toString(StringBuilder buffer)
586      {
587        buffer.append("BindResponse(resultCode=");
588        buffer.append(resultCode);
589    
590        if ((errorMessage != null) && (errorMessage.length() > 0))
591        {
592          buffer.append(", errorMessage=");
593          buffer.append(errorMessage);
594        }
595    
596        if (matchedDN != null)
597        {
598          buffer.append(", matchedDN=");
599          buffer.append(matchedDN.toString());
600        }
601    
602        if ((referralURLs != null) && (! referralURLs.isEmpty()))
603        {
604          buffer.append(", referralURLs={");
605    
606          Iterator<String> iterator = referralURLs.iterator();
607          buffer.append(iterator.next());
608    
609          while (iterator.hasNext())
610          {
611            buffer.append(", ");
612            buffer.append(iterator.next());
613          }
614    
615          buffer.append("}");
616        }
617    
618        if (serverSASLCredentials != null)
619        {
620          buffer.append(", serverSASLCredentials=");
621          serverSASLCredentials.toString(buffer);
622        }
623    
624        buffer.append(")");
625      }
626    
627    
628    
629      /**
630       * Appends a multi-line string representation of this LDAP protocol op to the
631       * provided buffer.
632       *
633       * @param  buffer  The buffer to which the information should be appended.
634       * @param  indent  The number of spaces from the margin that the lines should
635       *                 be indented.
636       */
637      public void toString(StringBuilder buffer, int indent)
638      {
639        StringBuilder indentBuf = new StringBuilder(indent);
640        for (int i=0 ; i < indent; i++)
641        {
642          indentBuf.append(' ');
643        }
644    
645        buffer.append(indentBuf);
646        buffer.append("Bind Response");
647        buffer.append(EOL);
648    
649        buffer.append(indentBuf);
650        buffer.append("  Result Code:  ");
651        buffer.append(resultCode);
652        buffer.append(EOL);
653    
654        if (errorMessage != null)
655        {
656          buffer.append(indentBuf);
657          buffer.append("  Error Message:  ");
658          buffer.append(errorMessage);
659          buffer.append(EOL);
660        }
661    
662        if (matchedDN != null)
663        {
664          buffer.append(indentBuf);
665          buffer.append("  Matched DN:  ");
666          matchedDN.toString(buffer);
667          buffer.append(EOL);
668        }
669    
670        if ((referralURLs != null) && (! referralURLs.isEmpty()))
671        {
672          buffer.append(indentBuf);
673          buffer.append("  Referral URLs:  ");
674          buffer.append(EOL);
675    
676          for (String s : referralURLs)
677          {
678            buffer.append(indentBuf);
679            buffer.append("  ");
680            buffer.append(s);
681            buffer.append(EOL);
682          }
683        }
684    
685        if (serverSASLCredentials != null)
686        {
687          buffer.append(indentBuf);
688          buffer.append("  Server SASL Credentials:");
689          buffer.append(EOL);
690    
691          serverSASLCredentials.toString(buffer, indent+4);
692        }
693      }
694    }
695