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    
034    import org.opends.server.protocols.asn1.ASN1Element;
035    import org.opends.server.protocols.asn1.ASN1Exception;
036    import org.opends.server.protocols.asn1.ASN1OctetString;
037    import org.opends.server.protocols.asn1.ASN1Sequence;
038    import org.opends.server.types.DebugLogLevel;
039    import org.opends.server.types.LDAPException;
040    
041    import static org.opends.server.loggers.debug.DebugLogger.*;
042    import org.opends.server.loggers.debug.DebugTracer;
043    import static org.opends.messages.ProtocolMessages.*;
044    import static org.opends.server.protocols.ldap.LDAPConstants.*;
045    import static org.opends.server.protocols.ldap.LDAPResultCode.*;
046    import static org.opends.server.util.ServerConstants.*;
047    import static org.opends.server.util.StaticUtils.*;
048    
049    
050    
051    /**
052     * This class defines the structures and methods for an LDAP intermediate
053     * response protocol op, which is used to provide information to a client before
054     * the final response for an operation.
055     */
056    public class IntermediateResponseProtocolOp
057           extends ProtocolOp
058    {
059      /**
060       * The tracer object for the debug logger.
061       */
062      private static final DebugTracer TRACER = getTracer();
063    
064      // The value for this intermediate response.
065      private ASN1OctetString value;
066    
067      // The OID for this intermediate response.
068      private String oid;
069    
070    
071    
072      /**
073       * Creates a new intermediate protocol op with the specified OID and no
074       * value.
075       *
076       * @param  oid  The OID for this intermediate response.
077       */
078      public IntermediateResponseProtocolOp(String oid)
079      {
080        this.oid   = oid;
081        this.value = null;
082      }
083    
084    
085    
086      /**
087       * Creates a new intermediate response protocol op with the specified OID and
088       * value.
089       *
090       * @param  oid    The OID for this intermediate response.
091       * @param  value  The value for this intermediate response.
092       */
093      public IntermediateResponseProtocolOp(String oid, ASN1OctetString value)
094      {
095        this.oid   = oid;
096        this.value = value;
097      }
098    
099    
100    
101      /**
102       * Retrieves the OID for this intermediate response.
103       *
104       * @return  The OID for this intermediate response, or <CODE>null</CODE> if
105       *          there is no OID.
106       */
107      public String getOID()
108      {
109        return oid;
110      }
111    
112    
113    
114      /**
115       * Specifies the OID for this intermediate response.
116       *
117       * @param  oid  The OID for this intermediate response.
118       */
119      public void setOID(String oid)
120      {
121        this.oid = oid;
122      }
123    
124    
125    
126      /**
127       * Retrieves the value for this intermediate response.
128       *
129       * @return  The value for this intermediate response, or <CODE>null</CODE> if
130       *          there is no value.
131       */
132      public ASN1OctetString getValue()
133      {
134        return value;
135      }
136    
137    
138    
139      /**
140       * Specifies the value for this intermediate response.
141       *
142       * @param  value  The value for this intermediate response.
143       */
144      public void setValue(ASN1OctetString value)
145      {
146        this.value = value;
147      }
148    
149    
150    
151      /**
152       * Retrieves the BER type for this protocol op.
153       *
154       * @return  The BER type for this protocol op.
155       */
156      public byte getType()
157      {
158        return OP_TYPE_INTERMEDIATE_RESPONSE;
159      }
160    
161    
162    
163      /**
164       * Retrieves the name for this protocol op type.
165       *
166       * @return  The name for this protocol op type.
167       */
168      public String getProtocolOpName()
169      {
170        return "Intermediate Response";
171      }
172    
173    
174    
175      /**
176       * Encodes this protocol op to an ASN.1 element suitable for including in an
177       * LDAP message.
178       *
179       * @return  The ASN.1 element containing the encoded protocol op.
180       */
181      public ASN1Element encode()
182      {
183        ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
184    
185        if (oid != null)
186        {
187          elements.add(new ASN1OctetString(TYPE_INTERMEDIATE_RESPONSE_OID, oid));
188        }
189    
190        if (value != null)
191        {
192          value.setType(TYPE_INTERMEDIATE_RESPONSE_VALUE);
193          elements.add(value);
194        }
195    
196        return new ASN1Sequence(OP_TYPE_INTERMEDIATE_RESPONSE, elements);
197      }
198    
199    
200    
201      /**
202       * Decodes the provided ASN.1 element as an LDAP intermediate response
203       * protocol op.
204       *
205       * @param  element  The ASN.1 element to be decoded.
206       *
207       * @return  The decoded intermediate response protocol op.
208       *
209       * @throws  LDAPException  If a problem occurs while attempting to decode the
210       *                         provided ASN.1 element as an LDAP intermediate
211       *                         response protocol op.
212       */
213      public static IntermediateResponseProtocolOp
214                         decodeIntermediateResponse(ASN1Element element)
215             throws LDAPException
216      {
217        ArrayList<ASN1Element> elements;
218        try
219        {
220          elements = element.decodeAsSequence().elements();
221        }
222        catch (Exception e)
223        {
224          if (debugEnabled())
225          {
226            TRACER.debugCaught(DebugLogLevel.ERROR, e);
227          }
228    
229          Message message =
230              ERR_LDAP_INTERMEDIATE_RESPONSE_DECODE_SEQUENCE.get(String.valueOf(e));
231          throw new LDAPException(PROTOCOL_ERROR, message, e);
232        }
233    
234    
235        int numElements = elements.size();
236        if (numElements > 2)
237        {
238          Message message =
239              ERR_LDAP_INTERMEDIATE_RESPONSE_DECODE_INVALID_ELEMENT_COUNT.
240                get(numElements);
241          throw new LDAPException(PROTOCOL_ERROR, message);
242        }
243    
244    
245        String          oid   = null;
246        ASN1OctetString value = null;
247    
248        if (elements.size() == 1)
249        {
250          ASN1Element e = elements.get(0);
251    
252          switch (e.getType())
253          {
254            case TYPE_INTERMEDIATE_RESPONSE_OID:
255              try
256              {
257                oid = e.decodeAsOctetString().stringValue();
258              }
259              catch (ASN1Exception ae)
260              {
261                if (debugEnabled())
262                {
263                  TRACER.debugCaught(DebugLogLevel.ERROR, ae);
264                }
265    
266                Message message = ERR_LDAP_INTERMEDIATE_RESPONSE_CANNOT_DECODE_OID.
267                    get(ae.getMessage());
268                throw new LDAPException(PROTOCOL_ERROR, message);
269              }
270              break;
271            case TYPE_INTERMEDIATE_RESPONSE_VALUE:
272              try
273              {
274                value = e.decodeAsOctetString();
275              }
276              catch (ASN1Exception ae)
277              {
278                if (debugEnabled())
279                {
280                  TRACER.debugCaught(DebugLogLevel.ERROR, ae);
281                }
282    
283                Message message =
284                    ERR_LDAP_INTERMEDIATE_RESPONSE_CANNOT_DECODE_VALUE.
285                      get(ae.getMessage());
286                throw new LDAPException(PROTOCOL_ERROR, message);
287              }
288              break;
289            default:
290              Message message = ERR_LDAP_INTERMEDIATE_RESPONSE_INVALID_ELEMENT_TYPE.
291                  get(byteToHex(e.getType()));
292              throw new LDAPException(PROTOCOL_ERROR, message);
293          }
294        }
295        else if (elements.size() == 2)
296        {
297          try
298          {
299            oid = elements.get(0).decodeAsOctetString().stringValue();
300          }
301          catch (ASN1Exception ae)
302          {
303            if (debugEnabled())
304            {
305              TRACER.debugCaught(DebugLogLevel.ERROR, ae);
306            }
307    
308            Message message = ERR_LDAP_INTERMEDIATE_RESPONSE_CANNOT_DECODE_OID.get(
309                ae.getMessage());
310            throw new LDAPException(PROTOCOL_ERROR, message);
311          }
312    
313          try
314          {
315            value = elements.get(1).decodeAsOctetString();
316          }
317          catch (ASN1Exception ae)
318          {
319            if (debugEnabled())
320            {
321              TRACER.debugCaught(DebugLogLevel.ERROR, ae);
322            }
323    
324            Message message = ERR_LDAP_INTERMEDIATE_RESPONSE_CANNOT_DECODE_OID.get(
325                ae.getMessage());
326            throw new LDAPException(PROTOCOL_ERROR, message);
327          }
328        }
329    
330    
331        return new IntermediateResponseProtocolOp(oid, value);
332      }
333    
334    
335    
336      /**
337       * Appends a string representation of this LDAP protocol op to the provided
338       * buffer.
339       *
340       * @param  buffer  The buffer to which the string should be appended.
341       */
342      public void toString(StringBuilder buffer)
343      {
344        buffer.append("IntermediateResponse(oid=");
345        buffer.append(String.valueOf(oid));
346    
347        if (value != null)
348        {
349          buffer.append(", value=");
350          value.toString(buffer);
351        }
352    
353        buffer.append(")");
354      }
355    
356    
357    
358      /**
359       * Appends a multi-line string representation of this LDAP protocol op to the
360       * provided buffer.
361       *
362       * @param  buffer  The buffer to which the information should be appended.
363       * @param  indent  The number of spaces from the margin that the lines should
364       *                 be indented.
365       */
366      public void toString(StringBuilder buffer, int indent)
367      {
368        StringBuilder indentBuf = new StringBuilder(indent);
369        for (int i=0 ; i < indent; i++)
370        {
371          indentBuf.append(' ');
372        }
373    
374        buffer.append(indentBuf);
375        buffer.append("Intermediate Response");
376        buffer.append(EOL);
377    
378        if (oid != null)
379        {
380          buffer.append(indentBuf);
381          buffer.append("  OID:  ");
382          buffer.append(oid);
383          buffer.append(EOL);
384        }
385    
386        if (value != null)
387        {
388          buffer.append(indentBuf);
389          buffer.append("  Value:");
390          buffer.append(EOL);
391          value.toString(buffer, indent+4);
392        }
393      }
394    }
395