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