001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.protocols.ldap;
028    import org.opends.messages.Message;
029    
030    
031    
032    import java.util.ArrayList;
033    import java.util.Iterator;
034    import java.util.List;
035    
036    import org.opends.server.protocols.asn1.ASN1Element;
037    import org.opends.server.protocols.asn1.ASN1Enumerated;
038    import org.opends.server.protocols.asn1.ASN1OctetString;
039    import org.opends.server.protocols.asn1.ASN1Sequence;
040    import org.opends.server.types.DebugLogLevel;
041    import org.opends.server.types.DN;
042    import org.opends.server.types.LDAPException;
043    
044    import static org.opends.server.loggers.debug.DebugLogger.*;
045    import org.opends.server.loggers.debug.DebugTracer;
046    import static org.opends.messages.ProtocolMessages.*;
047    import static org.opends.server.protocols.ldap.LDAPConstants.*;
048    import static org.opends.server.protocols.ldap.LDAPResultCode.*;
049    import static org.opends.server.util.ServerConstants.*;
050    
051    
052    
053    /**
054     * This class defines the structures and methods for an LDAP add response
055     * protocol op, which is used to provide information about the result of
056     * processing an add request.
057     */
058    public class AddResponseProtocolOp
059           extends ProtocolOp
060    {
061      /**
062       * The tracer object for the debug logger.
063       */
064      private static final DebugTracer TRACER = getTracer();
065    
066      // The matched DN for this response.
067      private DN matchedDN;
068    
069      // The result code for this response.
070      private int resultCode;
071    
072      // The set of referral URLs for this response.
073      private List<String> referralURLs;
074    
075      // The error message for this response.
076      private Message errorMessage;
077    
078    
079    
080      /**
081       * Creates a new add response protocol op with the provided result code.
082       *
083       * @param  resultCode  The result code for this response.
084       */
085      public AddResponseProtocolOp(int resultCode)
086      {
087        this.resultCode = resultCode;
088    
089        errorMessage = null;
090        matchedDN = null;
091        referralURLs = null;
092      }
093    
094    
095    
096      /**
097       * Creates a new add response protocol op with the provided result code and
098       * error message.
099       *
100       * @param  resultCode    The result code for this response.
101       * @param  errorMessage  The error message for this response.
102       */
103      public AddResponseProtocolOp(int resultCode, Message errorMessage)
104      {
105        this.resultCode   = resultCode;
106        this.errorMessage = errorMessage;
107    
108        matchedDN    = null;
109        referralURLs = null;
110      }
111    
112    
113    
114      /**
115       * Creates a new add response protocol op with the provided information.
116       *
117       * @param  resultCode    The result code for this response.
118       * @param  errorMessage  The error message for this response.
119       * @param  matchedDN     The matched DN for this response.
120       * @param  referralURLs  The referral URLs for this response.
121       */
122      public AddResponseProtocolOp(int resultCode, Message errorMessage,
123                                   DN matchedDN, List<String> referralURLs)
124      {
125        this.resultCode   = resultCode;
126        this.errorMessage = errorMessage;
127        this.matchedDN    = matchedDN;
128        this.referralURLs = referralURLs;
129      }
130    
131    
132    
133      /**
134       * Retrieves the result code for this response.
135       *
136       * @return  The result code for this response.
137       */
138      public int getResultCode()
139      {
140        return resultCode;
141      }
142    
143    
144    
145      /**
146       * Specifies the result code for this response.
147       *
148       * @param  resultCode  The result code for this response.
149       */
150      public void setResultCode(int resultCode)
151      {
152        this.resultCode = resultCode;
153      }
154    
155    
156    
157      /**
158       * Retrieves the error message for this response.
159       *
160       * @return  The error message for this response, or <CODE>null</CODE> if none
161       *          is available.
162       */
163      public Message getErrorMessage()
164      {
165        return errorMessage;
166      }
167    
168    
169    
170      /**
171       * Specifies the error message for this response.
172       *
173       * @param  errorMessage  The error message for this response.
174       */
175      public void setErrorMessage(Message errorMessage)
176      {
177        this.errorMessage = errorMessage;
178      }
179    
180    
181    
182      /**
183       * Retrieves the matched DN for this response.
184       *
185       * @return  The matched DN for this response, or <CODE>null</CODE> if none is
186       *          available.
187       */
188      public DN getMatchedDN()
189      {
190        return matchedDN;
191      }
192    
193    
194    
195      /**
196       * Specifies the matched DN for this response.
197       *
198       * @param  matchedDN  The matched DN for this response.
199       */
200      public void setMatchedDN(DN matchedDN)
201      {
202        this.matchedDN = matchedDN;
203      }
204    
205    
206    
207      /**
208       * Retrieves the set of referral URLs for this response.
209       *
210       * @return  The set of referral URLs for this response, or <CODE>null</CODE>
211       *          if none are available.
212       */
213      public List<String> getReferralURLs()
214      {
215        return referralURLs;
216      }
217    
218    
219    
220      /**
221       * Specifies the set of referral URLs for this response.
222       *
223       * @param  referralURLs  The set of referral URLs for this response.
224       */
225      public void setReferralURLs(List<String> referralURLs)
226      {
227        this.referralURLs = referralURLs;
228      }
229    
230    
231    
232      /**
233       * Retrieves the BER type for this protocol op.
234       *
235       * @return  The BER type for this protocol op.
236       */
237      public byte getType()
238      {
239        return OP_TYPE_ADD_RESPONSE;
240      }
241    
242    
243    
244      /**
245       * Retrieves the name for this protocol op type.
246       *
247       * @return  The name for this protocol op type.
248       */
249      public String getProtocolOpName()
250      {
251        return "Add Response";
252      }
253    
254    
255    
256      /**
257       * Encodes this protocol op to an ASN.1 element suitable for including in an
258       * LDAP message.
259       *
260       * @return  The ASN.1 element containing the encoded protocol op.
261       */
262      public ASN1Element encode()
263      {
264        ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(4);
265        elements.add(new ASN1Enumerated(resultCode));
266    
267        if (matchedDN == null)
268        {
269          elements.add(new ASN1OctetString());
270        }
271        else
272        {
273          elements.add(new ASN1OctetString(matchedDN.toString()));
274        }
275    
276        elements.add(new ASN1OctetString(errorMessage));
277    
278        if ((referralURLs != null) && (! referralURLs.isEmpty()))
279        {
280          ArrayList<ASN1Element> referralElements =
281               new ArrayList<ASN1Element>(referralURLs.size());
282    
283          for (String s : referralURLs)
284          {
285            referralElements.add(new ASN1OctetString(s));
286          }
287    
288          elements.add(new ASN1Sequence(TYPE_REFERRAL_SEQUENCE, referralElements));
289        }
290    
291        return new ASN1Sequence(OP_TYPE_ADD_RESPONSE, elements);
292      }
293    
294    
295    
296      /**
297       * Decodes the provided ASN.1 element as an add response protocol op.
298       *
299       * @param  element  The ASN.1 element to decode.
300       *
301       * @return  The decoded add response protocol op.
302       *
303       * @throws  LDAPException  If a problem occurs while attempting to decode the
304       *                         ASN.1 element to a protocol op.
305       */
306      public static AddResponseProtocolOp decodeAddResponse(ASN1Element element)
307             throws LDAPException
308      {
309        ArrayList<ASN1Element> elements;
310        try
311        {
312          elements = element.decodeAsSequence().elements();
313        }
314        catch (Exception e)
315        {
316          if (debugEnabled())
317          {
318            TRACER.debugCaught(DebugLogLevel.ERROR, e);
319          }
320    
321          Message message = ERR_LDAP_RESULT_DECODE_SEQUENCE.get(String.valueOf(e));
322          throw new LDAPException(PROTOCOL_ERROR, message, e);
323        }
324    
325    
326        int numElements = elements.size();
327        if ((numElements < 3) || (numElements > 4))
328        {
329          Message message =
330              ERR_LDAP_RESULT_DECODE_INVALID_ELEMENT_COUNT.get(numElements);
331          throw new LDAPException(PROTOCOL_ERROR, message);
332        }
333    
334    
335        int resultCode;
336        try
337        {
338          resultCode = elements.get(0).decodeAsInteger().intValue();
339        }
340        catch (Exception e)
341        {
342          if (debugEnabled())
343          {
344            TRACER.debugCaught(DebugLogLevel.ERROR, e);
345          }
346    
347          Message message =
348              ERR_LDAP_RESULT_DECODE_RESULT_CODE.get(String.valueOf(e));
349          throw new LDAPException(PROTOCOL_ERROR, message, e);
350        }
351    
352    
353        DN matchedDN;
354        try
355        {
356          String dnString = elements.get(1).decodeAsOctetString().stringValue();
357          if (dnString.length() == 0)
358          {
359            matchedDN = null;
360          }
361          else
362          {
363            matchedDN = DN.decode(dnString);
364          }
365        }
366        catch (Exception e)
367        {
368          if (debugEnabled())
369          {
370            TRACER.debugCaught(DebugLogLevel.ERROR, e);
371          }
372    
373          Message message =
374              ERR_LDAP_RESULT_DECODE_MATCHED_DN.get(String.valueOf(e));
375          throw new LDAPException(PROTOCOL_ERROR, message, e);
376        }
377    
378    
379        Message errorMessage;
380        try
381        {
382          errorMessage = Message.raw(
383                  elements.get(2).decodeAsOctetString().stringValue());
384          if (errorMessage.length() == 0)
385          {
386            errorMessage = null;
387          }
388        }
389        catch (Exception e)
390        {
391          if (debugEnabled())
392          {
393            TRACER.debugCaught(DebugLogLevel.ERROR, e);
394          }
395    
396          Message message =
397              ERR_LDAP_RESULT_DECODE_ERROR_MESSAGE.get(String.valueOf(e));
398          throw new LDAPException(PROTOCOL_ERROR, message, e);
399        }
400    
401    
402        ArrayList<String> referralURLs;
403        if (numElements == 3)
404        {
405          referralURLs = null;
406        }
407        else
408        {
409          try
410          {
411            ArrayList<ASN1Element> referralElements =
412                 elements.get(3).decodeAsSequence().elements();
413            referralURLs = new ArrayList<String>(referralElements.size());
414    
415            for (ASN1Element e : referralElements)
416            {
417              referralURLs.add(e.decodeAsOctetString().stringValue());
418            }
419          }
420          catch (Exception e)
421          {
422            if (debugEnabled())
423            {
424              TRACER.debugCaught(DebugLogLevel.ERROR, e);
425            }
426    
427            Message message =
428                ERR_LDAP_RESULT_DECODE_REFERRALS.get(String.valueOf(e));
429            throw new LDAPException(PROTOCOL_ERROR, message, e);
430          }
431        }
432    
433    
434        return new AddResponseProtocolOp(resultCode, errorMessage, matchedDN,
435                                         referralURLs);
436      }
437    
438    
439    
440      /**
441       * Appends a string representation of this LDAP protocol op to the provided
442       * buffer.
443       *
444       * @param  buffer  The buffer to which the string should be appended.
445       */
446      public void toString(StringBuilder buffer)
447      {
448        buffer.append("AddResponse(resultCode=");
449        buffer.append(resultCode);
450    
451        if ((errorMessage != null) && (errorMessage.length() > 0))
452        {
453          buffer.append(", errorMessage=");
454          buffer.append(errorMessage);
455        }
456    
457        if (matchedDN != null)
458        {
459          buffer.append(", matchedDN=");
460          buffer.append(matchedDN.toString());
461        }
462    
463        if ((referralURLs != null) && (! referralURLs.isEmpty()))
464        {
465          buffer.append(", referralURLs={");
466    
467          Iterator<String> iterator = referralURLs.iterator();
468          buffer.append(iterator.next());
469    
470          while (iterator.hasNext())
471          {
472            buffer.append(", ");
473            buffer.append(iterator.next());
474          }
475    
476          buffer.append("}");
477        }
478    
479        buffer.append(")");
480      }
481    
482    
483    
484      /**
485       * Appends a multi-line string representation of this LDAP protocol op to the
486       * provided buffer.
487       *
488       * @param  buffer  The buffer to which the information should be appended.
489       * @param  indent  The number of spaces from the margin that the lines should
490       *                 be indented.
491       */
492      public void toString(StringBuilder buffer, int indent)
493      {
494        StringBuilder indentBuf = new StringBuilder(indent);
495        for (int i=0 ; i < indent; i++)
496        {
497          indentBuf.append(' ');
498        }
499    
500        buffer.append(indentBuf);
501        buffer.append("Add Response");
502        buffer.append(EOL);
503    
504        buffer.append(indentBuf);
505        buffer.append("  Result Code:  ");
506        buffer.append(resultCode);
507        buffer.append(EOL);
508    
509        if (errorMessage != null)
510        {
511          buffer.append(indentBuf);
512          buffer.append("  Error Message:  ");
513          buffer.append(errorMessage);
514          buffer.append(EOL);
515        }
516    
517        if (matchedDN != null)
518        {
519          buffer.append(indentBuf);
520          buffer.append("  Matched DN:  ");
521          matchedDN.toString(buffer);
522          buffer.append(EOL);
523        }
524    
525        if ((referralURLs != null) && (! referralURLs.isEmpty()))
526        {
527          buffer.append(indentBuf);
528          buffer.append("  Referral URLs:  ");
529          buffer.append(EOL);
530    
531          for (String s : referralURLs)
532          {
533            buffer.append(indentBuf);
534            buffer.append("  ");
535            buffer.append(s);
536            buffer.append(EOL);
537          }
538        }
539      }
540    }
541