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 legal-notices/CDDLv1_0.txt
010 * or http://forgerock.org/license/CDDLv1.0.html.
011 * See the License for the specific language governing permissions
012 * and limitations under the License.
013 *
014 * When distributing Covered Code, include this CDDL HEADER in each
015 * file and include the License file at legal-notices/CDDLv1_0.txt.
016 * If applicable, add the following below this CDDL HEADER, with the
017 * fields enclosed by brackets "[]" replaced with your own identifying
018 * information:
019 *      Portions Copyright [yyyy] [name of copyright owner]
020 *
021 * CDDL HEADER END
022 *
023 *
024 *      Copyright 2006-2009 Sun Microsystems, Inc.
025 *      Portions Copyright 2014-2015 ForgeRock AS
026 */
027package org.opends.server.protocols.ldap;
028
029
030import java.util.ArrayList;
031import java.util.Iterator;
032import java.util.List;
033import java.io.IOException;
034
035import org.opends.server.api.ProtocolElement;
036import org.forgerock.opendj.io.*;
037import org.opends.server.types.Control;
038
039import static org.opends.server.protocols.ldap.LDAPConstants.
040    TYPE_CONTROL_SEQUENCE;
041import static org.opends.server.util.ServerConstants.*;
042
043
044/**
045 * This class defines the data structures and methods to use when interacting
046 * with an LDAP message, which is the basic envelope used to hold LDAP requests
047 * and responses.
048 */
049public class LDAPMessage
050       implements ProtocolElement
051{
052  /** The set of controls for this LDAP message. */
053  private List<Control> controls;
054
055  /** The message ID for this LDAP message. */
056  private final int messageID;
057
058  /** The protocol op for this LDAP message. */
059  private final ProtocolOp protocolOp;
060
061
062
063  /**
064   * Creates a new LDAP message with the provided message ID and protocol op but
065   * no controls.
066   *
067   * @param  messageID   The message ID for this LDAP message.
068   * @param  protocolOp  The protocol op for this LDAP message.
069   */
070  public LDAPMessage(int messageID, ProtocolOp protocolOp)
071  {
072    this(messageID, protocolOp, null);
073  }
074
075
076
077  /**
078   * Creates a new LDAP message with the provided message ID, protocol op, and
079   * set of controls.
080   *
081   * @param  messageID   The message ID for this LDAP message.
082   * @param  protocolOp  The protocol op for this LDAP message.
083   * @param  controls    The set of controls for this LDAP message.
084   */
085  public LDAPMessage(int messageID, ProtocolOp protocolOp,
086                     List<Control> controls)
087  {
088    this.messageID  = messageID;
089    this.protocolOp = protocolOp;
090    this.controls = controls;
091  }
092
093
094
095  /**
096   * Retrieves the message ID for this LDAP message.
097   *
098   * @return  The message ID for this LDAP message.
099   */
100  public int getMessageID()
101  {
102    return messageID;
103  }
104
105
106
107  /**
108   * Retrieves the protocol op for this LDAP message.
109   *
110   * @return  The protocol op for this LDAP message.
111   */
112  public ProtocolOp getProtocolOp()
113  {
114    return protocolOp;
115  }
116
117
118
119  /**
120   * Retrieves the protocol op type for this LDAP message.
121   *
122   * @return  The protocol op type for this LDAP message.
123   */
124  public byte getProtocolOpType()
125  {
126    return protocolOp.getType();
127  }
128
129
130
131  /**
132   * Retrieves the protocol op name for this LDAP message.
133   *
134   * @return  The protocol op name for this LDAP message.
135   */
136  public String getProtocolOpName()
137  {
138    return protocolOp.getProtocolOpName();
139  }
140
141
142
143  /**
144   * Retrieves the protocol op for this LDAP message as an abandon request
145   * protocol op.
146   *
147   * @return  The protocol op for this LDAP message as an abandon request
148   *          protocol op.
149   *
150   * @throws  ClassCastException  If the protocol op is not an abandon request
151   *                              protocol op.
152   */
153  public AbandonRequestProtocolOp getAbandonRequestProtocolOp()
154         throws ClassCastException
155  {
156    return (AbandonRequestProtocolOp) protocolOp;
157  }
158
159
160
161  /**
162   * Retrieves the protocol op for this LDAP message as an add request protocol
163   * op.
164   *
165   * @return  The protocol op for this LDAP message as an add request protocol
166   *          op.
167   *
168   * @throws  ClassCastException  If the protocol op is not an add request
169   *                              protocol op.
170   */
171  public AddRequestProtocolOp getAddRequestProtocolOp()
172         throws ClassCastException
173  {
174    return (AddRequestProtocolOp) protocolOp;
175  }
176
177
178
179  /**
180   * Retrieves the protocol op for this LDAP message as an add response protocol
181   * op.
182   *
183   * @return  The protocol op for this LDAP message as an add response protocol
184   *          op.
185   *
186   * @throws  ClassCastException  If the protocol op is not an add response
187   *                              protocol op.
188   */
189  public AddResponseProtocolOp getAddResponseProtocolOp()
190         throws ClassCastException
191  {
192    return (AddResponseProtocolOp) protocolOp;
193  }
194
195
196
197  /**
198   * Retrieves the protocol op for this LDAP message as a bind request
199   * protocol op.
200   *
201   * @return  The protocol op for this LDAP message as a bind request
202   *          protocol op.
203   *
204   * @throws  ClassCastException  If the protocol op is not a bind request
205   *                              protocol op.
206   */
207  public BindRequestProtocolOp getBindRequestProtocolOp()
208         throws ClassCastException
209  {
210    return (BindRequestProtocolOp) protocolOp;
211  }
212
213
214
215  /**
216   * Retrieves the protocol op for this LDAP message as a bind response
217   * protocol op.
218   *
219   * @return  The protocol op for this LDAP message as a bind response
220   *          protocol op.
221   *
222   * @throws  ClassCastException  If the protocol op is not a bind response
223   *                              protocol op.
224   */
225  public BindResponseProtocolOp getBindResponseProtocolOp()
226         throws ClassCastException
227  {
228    return (BindResponseProtocolOp) protocolOp;
229  }
230
231
232
233  /**
234   * Retrieves the protocol op for this LDAP message as a compare request
235   * protocol op.
236   *
237   * @return  The protocol op for this LDAP message as a compare request
238   *          protocol op.
239   *
240   * @throws  ClassCastException  If the protocol op is not a compare request
241   *                              protocol op.
242   */
243  public CompareRequestProtocolOp getCompareRequestProtocolOp()
244         throws ClassCastException
245  {
246    return (CompareRequestProtocolOp) protocolOp;
247  }
248
249
250
251  /**
252   * Retrieves the protocol op for this LDAP message as a compare response
253   * protocol op.
254   *
255   * @return  The protocol op for this LDAP message as a compare response
256   *          protocol op.
257   *
258   * @throws  ClassCastException  If the protocol op is not a compare response
259   *                              protocol op.
260   */
261  public CompareResponseProtocolOp getCompareResponseProtocolOp()
262         throws ClassCastException
263  {
264    return (CompareResponseProtocolOp) protocolOp;
265  }
266
267
268
269  /**
270   * Retrieves the protocol op for this LDAP message as a delete request
271   * protocol op.
272   *
273   * @return  The protocol op for this LDAP message as a delete request
274   *          protocol op.
275   *
276   * @throws  ClassCastException  If the protocol op is not a delete request
277   *                              protocol op.
278   */
279  public DeleteRequestProtocolOp getDeleteRequestProtocolOp()
280         throws ClassCastException
281  {
282    return (DeleteRequestProtocolOp) protocolOp;
283  }
284
285
286
287  /**
288   * Retrieves the protocol op for this LDAP message as a delete response
289   * protocol op.
290   *
291   * @return  The protocol op for this LDAP message as a delete response
292   *          protocol op.
293   *
294   * @throws  ClassCastException  If the protocol op is not a delete response
295   *                              protocol op.
296   */
297  public DeleteResponseProtocolOp getDeleteResponseProtocolOp()
298         throws ClassCastException
299  {
300    return (DeleteResponseProtocolOp) protocolOp;
301  }
302
303
304
305  /**
306   * Retrieves the protocol op for this LDAP message as an extended request
307   * protocol op.
308   *
309   * @return  The protocol op for this LDAP message as an extended request
310   *          protocol op.
311   *
312   * @throws  ClassCastException  If the protocol op is not an extended request
313   *                              protocol op.
314   */
315  public ExtendedRequestProtocolOp getExtendedRequestProtocolOp()
316         throws ClassCastException
317  {
318    return (ExtendedRequestProtocolOp) protocolOp;
319  }
320
321
322
323  /**
324   * Retrieves the protocol op for this LDAP message as an extended response
325   * protocol op.
326   *
327   * @return  The protocol op for this LDAP message as an extended response
328   *          protocol op.
329   *
330   * @throws  ClassCastException  If the protocol op is not an extended response
331   *                              protocol op.
332   */
333  public ExtendedResponseProtocolOp getExtendedResponseProtocolOp()
334         throws ClassCastException
335  {
336    return (ExtendedResponseProtocolOp) protocolOp;
337  }
338
339
340
341  /**
342   * Retrieves the protocol op for this LDAP message as a modify request
343   * protocol op.
344   *
345   * @return  The protocol op for this LDAP message as a modify request
346   *          protocol op.
347   *
348   * @throws  ClassCastException  If the protocol op is not a modify request
349   *                              protocol op.
350   */
351  public ModifyRequestProtocolOp getModifyRequestProtocolOp()
352         throws ClassCastException
353  {
354    return (ModifyRequestProtocolOp) protocolOp;
355  }
356
357
358
359  /**
360   * Retrieves the protocol op for this LDAP message as a modify response
361   * protocol op.
362   *
363   * @return  The protocol op for this LDAP message as a modify response
364   *          protocol op.
365   *
366   * @throws  ClassCastException  If the protocol op is not a modify response
367   *                              protocol op.
368   */
369  public ModifyResponseProtocolOp getModifyResponseProtocolOp()
370         throws ClassCastException
371  {
372    return (ModifyResponseProtocolOp) protocolOp;
373  }
374
375
376
377  /**
378   * Retrieves the protocol op for this LDAP message as a modify DN request
379   * protocol op.
380   *
381   * @return  The protocol op for this LDAP message as a modify DN request
382   *          protocol op.
383   *
384   * @throws  ClassCastException  If the protocol op is not a modify DN request
385   *                              protocol op.
386   */
387  public ModifyDNRequestProtocolOp getModifyDNRequestProtocolOp()
388         throws ClassCastException
389  {
390    return (ModifyDNRequestProtocolOp) protocolOp;
391  }
392
393
394
395  /**
396   * Retrieves the protocol op for this LDAP message as a modify DN response
397   * protocol op.
398   *
399   * @return  The protocol op for this LDAP message as a modify DN response
400   *          protocol op.
401   *
402   * @throws  ClassCastException  If the protocol op is not a modify DN response
403   *                              protocol op.
404   */
405  public ModifyDNResponseProtocolOp getModifyDNResponseProtocolOp()
406         throws ClassCastException
407  {
408    return (ModifyDNResponseProtocolOp) protocolOp;
409  }
410
411
412
413  /**
414   * Retrieves the protocol op for this LDAP message as a search request
415   * protocol op.
416   *
417   * @return  The protocol op for this LDAP message as a search request
418   *          protocol op.
419   *
420   * @throws  ClassCastException  If the protocol op is not a search request
421   *                              protocol op.
422   */
423  public SearchRequestProtocolOp getSearchRequestProtocolOp()
424         throws ClassCastException
425  {
426    return (SearchRequestProtocolOp) protocolOp;
427  }
428
429
430
431  /**
432   * Retrieves the protocol op for this LDAP message as a search result done
433   * protocol op.
434   *
435   * @return  The protocol op for this LDAP message as a search result done
436   *          protocol op.
437   *
438   * @throws  ClassCastException  If the protocol op is not a search result done
439   *                              protocol op.
440   */
441  public SearchResultDoneProtocolOp getSearchResultDoneProtocolOp()
442         throws ClassCastException
443  {
444    return (SearchResultDoneProtocolOp) protocolOp;
445  }
446
447
448
449  /**
450   * Retrieves the protocol op for this LDAP message as a search result entry
451   * protocol op.
452   *
453   * @return  The protocol op for this LDAP message as a search result entry
454   *          protocol op.
455   *
456   * @throws  ClassCastException  If the protocol op is not a search result
457   *                              entry protocol op.
458   */
459  public SearchResultEntryProtocolOp getSearchResultEntryProtocolOp()
460         throws ClassCastException
461  {
462    return (SearchResultEntryProtocolOp) protocolOp;
463  }
464
465
466
467  /**
468   * Retrieves the protocol op for this LDAP message as a search result
469   * reference protocol op.
470   *
471   * @return  The protocol op for this LDAP message as a search result reference
472   *          protocol op.
473   *
474   * @throws  ClassCastException  If the protocol op is not a search result
475   *                              reference protocol op.
476   */
477  public SearchResultReferenceProtocolOp getSearchResultReferenceProtocolOp()
478         throws ClassCastException
479  {
480    return (SearchResultReferenceProtocolOp) protocolOp;
481  }
482
483
484
485  /**
486   * Retrieves the protocol op for this LDAP message as an unbind request
487   * protocol op.
488   *
489   * @return  The protocol op for this LDAP message as an unbind request
490   *          protocol op.
491   *
492   * @throws  ClassCastException  If the protocol op is not an unbind request
493   *                              protocol op.
494   */
495  public UnbindRequestProtocolOp getUnbindRequestProtocolOp()
496         throws ClassCastException
497  {
498    return (UnbindRequestProtocolOp) protocolOp;
499  }
500
501
502
503  /**
504   * Retrieves the set of controls for this LDAP message.  It may be modified by
505   * the caller.
506   *
507   * @return  The set of controls for this LDAP message.
508   */
509  public List<Control> getControls()
510  {
511    // This method is not thread-safe.
512    if (controls == null)
513    {
514      controls = new ArrayList<>(0);
515    }
516    return controls;
517  }
518
519  /**
520   * Writes this protocol op to an ASN.1 output stream.
521   *
522   * @param stream The ASN.1 output stream to write to.
523   * @throws IOException If a problem occurs while writing to the stream.
524   */
525  public void write(ASN1Writer stream) throws IOException
526  {
527    stream.writeStartSequence();
528    stream.writeInteger(messageID);
529    protocolOp.write(stream);
530
531    if(controls != null && !controls.isEmpty())
532    {
533      stream.writeStartSequence(TYPE_CONTROL_SEQUENCE);
534      for(Control control : controls)
535      {
536        control.write(stream);
537      }
538      stream.writeEndSequence();
539    }
540
541    stream.writeEndSequence();
542  }
543
544
545
546  /**
547   * Retrieves the name of the protocol associated with this protocol element.
548   *
549   * @return  The name of the protocol associated with this protocol element.
550   */
551  public String getProtocolElementName()
552  {
553    return "LDAP";
554  }
555
556
557
558  /**
559   * Retrieves a string representation of this LDAP message.
560   *
561   * @return  A string representation of this LDAP message.
562   */
563  @Override
564  public String toString()
565  {
566    StringBuilder buffer = new StringBuilder();
567    toString(buffer);
568    return buffer.toString();
569  }
570
571
572
573  /**
574   * Appends a string representation of this protocol element to the provided
575   * buffer.
576   *
577   * @param  buffer  The buffer into which the string representation should be
578   *                 written.
579   */
580  public void toString(StringBuilder buffer)
581  {
582    buffer.append("LDAPMessage(msgID=");
583    buffer.append(messageID);
584    buffer.append(", protocolOp=");
585    if (protocolOp != null) {
586      protocolOp.toString(buffer);
587    } else {
588      buffer.append("null");
589    }
590
591    if (controls != null && !controls.isEmpty())
592    {
593      buffer.append(", controls={ ");
594
595      Iterator<Control> iterator = controls.iterator();
596      iterator.next().toString(buffer);
597
598      while (iterator.hasNext())
599      {
600        buffer.append(", ");
601        iterator.next().toString(buffer);
602      }
603
604      buffer.append(" }");
605    }
606
607    buffer.append(")");
608  }
609
610
611
612  /**
613   * Appends a string representation of this protocol element to the provided
614   * buffer.
615   *
616   * @param  buffer  The buffer into which the string representation should be
617   *                 written.
618   * @param  indent  The number of spaces that should be used to indent the
619   *                 resulting string representation.
620   */
621  public void toString(StringBuilder buffer, int indent)
622  {
623    StringBuilder indentBuf = new StringBuilder(indent);
624    for (int i=0 ; i < indent; i++)
625    {
626      indentBuf.append(' ');
627    }
628
629    buffer.append(indentBuf);
630    buffer.append("LDAP LocalizableMessage");
631    buffer.append(EOL);
632
633    buffer.append(indentBuf);
634    buffer.append("  LocalizableMessage ID:  ");
635    buffer.append(messageID);
636    buffer.append(EOL);
637
638    buffer.append(indentBuf);
639    buffer.append("  Protocol Op:");
640    buffer.append(EOL);
641    protocolOp.toString(buffer, indent+4);
642
643    if (controls != null && !controls.isEmpty())
644    {
645      buffer.append(indentBuf);
646      buffer.append("  Controls:");
647
648      for (Control c : controls)
649      {
650        // TODO: Indent
651        c.toString(buffer);//, indent+4);
652      }
653    }
654  }
655}
656