(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / Novell.Directory.Ldap / Novell.Directory.Ldap / LdapMessage.cs
blobe480ca8d922f5f15fe5c962aaa7211ec9ea57c7e
1 /******************************************************************************
2 * The MIT License
3 * Copyright (c) 2003 Novell Inc. www.novell.com
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the Software), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *******************************************************************************/
24 // Novell.Directory.Ldap.LdapMessage.cs
26 // Author:
27 // Sunil Kumar (Sunilk@novell.com)
29 // (C) 2003 Novell, Inc (http://www.novell.com)
32 using System;
33 using Novell.Directory.Ldap.Rfc2251;
34 using Novell.Directory.Ldap.Asn1;
35 using Novell.Directory.Ldap.Utilclass;
37 namespace Novell.Directory.Ldap
40 /// <summary> The base class for Ldap request and response messages.
41 ///
42 /// Subclassed by response messages used in asynchronous operations.
43 ///
44 ///
45 /// </summary>
46 public class LdapMessage
48 /// <summary> Returns the LdapMessage request associated with this response</summary>
49 virtual internal LdapMessage RequestingMessage
51 /* package */
53 get
55 return message.RequestingMessage;
59 /// <summary> Returns any controls in the message.</summary>
60 virtual public LdapControl[] Controls
62 get
65 /* LdapControl[] controls = null;
66 RfcControls asn1Ctrls = message.Controls;
68 if (asn1Ctrls != null)
70 controls = new LdapControl[asn1Ctrls.size()];
71 for (int i = 0; i < asn1Ctrls.size(); i++)
73 RfcControl rfcCtl = (RfcControl) asn1Ctrls.get_Renamed(i);
74 System.String oid = rfcCtl.ControlType.stringValue();
75 sbyte[] value_Renamed = rfcCtl.ControlValue.byteValue();
76 bool critical = rfcCtl.Criticality.booleanValue();
78 controls[i] = controlFactory(oid, critical, value_Renamed);
82 return controls;
84 LdapControl[] controls = null;
85 RfcControls asn1Ctrls = message.Controls;
87 // convert from RFC 2251 Controls to LDAPControl[].
88 if (asn1Ctrls != null)
90 controls = new LdapControl[asn1Ctrls.size()];
91 for (int i = 0; i < asn1Ctrls.size(); i++)
95 * At this point we have an RfcControl which needs to be
96 * converted to the appropriate Response Control. This requires
97 * calling the constructor of a class that extends LDAPControl.
98 * The controlFactory method searches the list of registered
99 * controls and if a match is found calls the constructor
100 * for that child LDAPControl. Otherwise, it returns a regular
101 * LDAPControl object.
103 * Question: Why did we not call the controlFactory method when
104 * we were parsing the control. Answer: By the time the
105 * code realizes that we have a control it is already too late.
107 RfcControl rfcCtl = (RfcControl) asn1Ctrls.get_Renamed(i);
108 System.String oid = rfcCtl.ControlType.stringValue();
109 sbyte[] value_Renamed = rfcCtl.ControlValue.byteValue();
110 bool critical = rfcCtl.Criticality.booleanValue();
112 /* Return from this call should return either an LDAPControl
113 * or a class extending LDAPControl that implements the
114 * appropriate registered response control
116 controls[i] = controlFactory(oid, critical, value_Renamed);
119 return controls;
125 /// <summary> Returns the message ID. The message ID is an integer value
126 /// identifying the Ldap request and its response.
127 /// </summary>
128 virtual public int MessageID
132 if (imsgNum == - 1)
134 imsgNum = message.MessageID;
136 return imsgNum;
140 /// <summary> Returns the Ldap operation type of the message.
141 ///
142 /// The type is one of the following:
143 /// <ul>
144 /// <li>BIND_REQUEST = 0;</li>
145 /// <li>BIND_RESPONSE = 1;</li>
146 /// <li>UNBIND_REQUEST = 2;</li>
147 /// <li>SEARCH_REQUEST = 3;</li>
148 /// <li>SEARCH_RESPONSE = 4;</li>
149 /// <li>SEARCH_RESULT = 5;</li>
150 /// <li>MODIFY_REQUEST = 6;</li>
151 /// <li>MODIFY_RESPONSE = 7;</li>
152 /// <li>ADD_REQUEST = 8;</li>
153 /// <li>ADD_RESPONSE = 9;</li>
154 /// <li>DEL_REQUEST = 10;</li>
155 /// <li>DEL_RESPONSE = 11;</li>
156 /// <li>MODIFY_RDN_REQUEST = 12;</li>
157 /// <li>MODIFY_RDN_RESPONSE = 13;</li>
158 /// <li>COMPARE_REQUEST = 14;</li>
159 /// <li>COMPARE_RESPONSE = 15;</li>
160 /// <li>ABANDON_REQUEST = 16;</li>
161 /// <li>SEARCH_RESULT_REFERENCE = 19;</li>
162 /// <li>EXTENDED_REQUEST = 23;</li>
163 /// <li>EXTENDED_RESPONSE = 24;</li>
164 /// </ul>
165 ///
166 /// </summary>
167 /// <returns> The operation type of the message.
168 /// </returns>
169 virtual public int Type
173 if (messageType == - 1)
175 messageType = message.Type;
177 return messageType;
181 /// <summary> Indicates whether the message is a request or a response
182 ///
183 /// </summary>
184 /// <returns> true if the message is a request, false if it is a response,
185 /// a search result, or a search result reference.
186 /// </returns>
187 virtual public bool Request
191 return message.isRequest();
195 /// <summary> Returns the RFC 2251 LdapMessage composed in this object.</summary>
196 virtual internal RfcLdapMessage Asn1Object
198 /* package */
202 return message;
206 private System.String Name
210 System.String name;
211 switch (Type)
214 case SEARCH_RESPONSE:
215 name = "LdapSearchResponse";
216 break;
218 case SEARCH_RESULT:
219 name = "LdapSearchResult";
220 break;
222 case SEARCH_REQUEST:
223 name = "LdapSearchRequest";
224 break;
226 case MODIFY_REQUEST:
227 name = "LdapModifyRequest";
228 break;
230 case MODIFY_RESPONSE:
231 name = "LdapModifyResponse";
232 break;
234 case ADD_REQUEST:
235 name = "LdapAddRequest";
236 break;
238 case ADD_RESPONSE:
239 name = "LdapAddResponse";
240 break;
242 case DEL_REQUEST:
243 name = "LdapDelRequest";
244 break;
246 case DEL_RESPONSE:
247 name = "LdapDelResponse";
248 break;
250 case MODIFY_RDN_REQUEST:
251 name = "LdapModifyRDNRequest";
252 break;
254 case MODIFY_RDN_RESPONSE:
255 name = "LdapModifyRDNResponse";
256 break;
258 case COMPARE_REQUEST:
259 name = "LdapCompareRequest";
260 break;
262 case COMPARE_RESPONSE:
263 name = "LdapCompareResponse";
264 break;
266 case BIND_REQUEST:
267 name = "LdapBindRequest";
268 break;
270 case BIND_RESPONSE:
271 name = "LdapBindResponse";
272 break;
274 case UNBIND_REQUEST:
275 name = "LdapUnbindRequest";
276 break;
278 case ABANDON_REQUEST:
279 name = "LdapAbandonRequest";
280 break;
282 case SEARCH_RESULT_REFERENCE:
283 name = "LdapSearchResultReference";
284 break;
286 case EXTENDED_REQUEST:
287 name = "LdapExtendedRequest";
288 break;
290 case EXTENDED_RESPONSE:
291 name = "LdapExtendedResponse";
292 break;
294 default:
295 throw new System.SystemException("LdapMessage: Unknown Type " + Type);
298 return name;
302 /// <summary> Retrieves the identifier tag for this message.
303 ///
304 /// An identifier can be associated with a message with the
305 /// <code>setTag</code> method.
306 /// Tags are set by the application and not by the API or the server.
307 /// If a server response <code>isRequest() == false</code> has no tag,
308 /// the tag associated with the corresponding server request is used.
309 ///
310 /// </summary>
311 /// <returns> the identifier associated with this message or <code>null</code>
312 /// if none.
313 ///
314 /// </returns>
315 /// <summary> Sets a string identifier tag for this message.
316 ///
317 /// This method allows an API to set a tag and later identify messages
318 /// by retrieving the tag associated with the message.
319 /// Tags are set by the application and not by the API or the server.
320 /// Message tags are not included with any message sent to or received
321 /// from the server.
322 ///
323 /// Tags set on a request to the server
324 /// are automatically associated with the response messages when they are
325 /// received by the API and transferred to the application.
326 /// The application can explicitly set a different value in a
327 /// response message.
328 ///
329 /// To set a value in a server request, for example an
330 /// {@link LdapSearchRequest}, you must create the object,
331 /// set the tag, and use the
332 /// {@link LdapConnection.SendRequest LdapConnection.sendRequest()}
333 /// method to send it to the server.
334 ///
335 /// </summary>
336 /// <param name="stringTag"> the String assigned to identify this message.
337 ///
338 /// </param>
339 virtual public System.String Tag
343 if ((System.Object) this.stringTag != null)
345 return this.stringTag;
347 if (Request)
349 return null;
351 LdapMessage m = this.RequestingMessage;
352 if (m == null)
354 return null;
356 return m.stringTag;
361 this.stringTag = value;
362 return ;
367 /// <summary> A bind request operation.
368 ///
369 /// BIND_REQUEST = 0
370 /// </summary>
371 public const int BIND_REQUEST = 0;
373 /// <summary> A bind response operation.
374 ///
375 /// BIND_RESPONSE = 1
376 /// </summary>
377 public const int BIND_RESPONSE = 1;
379 /// <summary> An unbind request operation.
380 ///
381 /// UNBIND_REQUEST = 2
382 /// </summary>
383 public const int UNBIND_REQUEST = 2;
385 /// <summary> A search request operation.
386 ///
387 /// SEARCH_REQUEST = 3
388 /// </summary>
389 public const int SEARCH_REQUEST = 3;
391 /// <summary> A search response containing data.
392 ///
393 /// SEARCH_RESPONSE = 4
394 /// </summary>
395 public const int SEARCH_RESPONSE = 4;
397 /// <summary> A search result message - contains search status.
398 ///
399 /// SEARCH_RESULT = 5
400 /// </summary>
401 public const int SEARCH_RESULT = 5;
403 /// <summary> A modify request operation.
404 ///
405 /// MODIFY_REQUEST = 6
406 /// </summary>
407 public const int MODIFY_REQUEST = 6;
409 /// <summary> A modify response operation.
410 ///
411 /// MODIFY_RESPONSE = 7
412 /// </summary>
413 public const int MODIFY_RESPONSE = 7;
415 /// <summary> An add request operation.
416 ///
417 /// ADD_REQUEST = 8
418 /// </summary>
419 public const int ADD_REQUEST = 8;
421 /// <summary> An add response operation.
422 ///
423 /// ADD_RESONSE = 9
424 /// </summary>
425 public const int ADD_RESPONSE = 9;
427 /// <summary> A delete request operation.
428 ///
429 /// DEL_REQUEST = 10
430 /// </summary>
431 public const int DEL_REQUEST = 10;
433 /// <summary> A delete response operation.
434 ///
435 /// DEL_RESONSE = 11
436 /// </summary>
437 public const int DEL_RESPONSE = 11;
439 /// <summary> A modify RDN request operation.
440 ///
441 /// MODIFY_RDN_REQUEST = 12
442 /// </summary>
443 public const int MODIFY_RDN_REQUEST = 12;
445 /// <summary> A modify RDN response operation.
446 ///
447 /// MODIFY_RDN_RESPONSE = 13
448 /// </summary>
449 public const int MODIFY_RDN_RESPONSE = 13;
451 /// <summary> A compare result operation.
452 ///
453 /// COMPARE_REQUEST = 14
454 /// </summary>
455 public const int COMPARE_REQUEST = 14;
457 /// <summary> A compare response operation.
458 ///
459 /// COMPARE_RESPONSE = 15
460 /// </summary>
461 public const int COMPARE_RESPONSE = 15;
463 /// <summary> An abandon request operation.
464 ///
465 /// ABANDON_REQUEST = 16
466 /// </summary>
467 public const int ABANDON_REQUEST = 16;
470 /// <summary> A search result reference operation.
471 ///
472 /// SEARCH_RESULT_REFERENCE = 19
473 /// </summary>
474 public const int SEARCH_RESULT_REFERENCE = 19;
476 /// <summary> An extended request operation.
477 ///
478 /// EXTENDED_REQUEST = 23
479 /// </summary>
480 public const int EXTENDED_REQUEST = 23;
482 /// <summary> An extended response operation.
483 ///
484 /// EXTENDED_RESONSE = 24
485 /// </summary>
486 public const int EXTENDED_RESPONSE = 24;
488 /// <summary> A request or response message for an asynchronous Ldap operation.</summary>
489 protected internal RfcLdapMessage message;
491 /// <summary> Lock object to protect counter for message numbers</summary>
493 private static Object msgLock = new Object();
496 /// <summary> Counters used to construct request message #'s, unique for each request
497 /// Will be enabled after ASN.1 conversion
498 /// </summary>
500 private static int msgNum = 0; // Ldap Request counter
502 private int imsgNum = - 1; // This instance LdapMessage number
504 private int messageType = - 1;
506 /* application defined tag to identify this message */
507 private System.String stringTag = null;
509 /// <summary> Dummy constuctor</summary>
510 /* package */
511 internal LdapMessage()
513 return ;
516 /// <summary> Creates an LdapMessage when sending a protocol operation and sends
517 /// some optional controls with the message.
518 ///
519 /// </summary>
520 /// <param name="op">The operation type of message.
521 ///
522 /// </param>
523 /// <param name="controls">The controls to use with the operation.
524 ///
525 /// </param>
526 /// <seealso cref="Type">
527 /// </seealso>
528 /*package*/
529 internal LdapMessage(int type, RfcRequest op, LdapControl[] controls)
532 // Get a unique number for this request message
534 messageType = type;
535 RfcControls asn1Ctrls = null;
536 if (controls != null)
538 // Move LdapControls into an RFC 2251 Controls object.
539 asn1Ctrls = new RfcControls();
540 for (int i = 0; i < controls.Length; i++)
542 // asn1Ctrls.add(null);
543 asn1Ctrls.add(controls[i].Asn1Object);
547 // create RFC 2251 LdapMessage
548 message = new RfcLdapMessage(op, asn1Ctrls);
549 return ;
552 /// <summary> Creates an Rfc 2251 LdapMessage when the libraries receive a response
553 /// from a command.
554 ///
555 /// </summary>
556 /// <param name="message">A response message.
557 /// </param>
558 protected internal LdapMessage(RfcLdapMessage message)
560 this.message = message;
561 return ;
564 /// <summary> Returns a mutated clone of this LdapMessage,
565 /// replacing base dn, filter.
566 ///
567 /// </summary>
568 /// <param name="dn">the base dn
569 ///
570 /// </param>
571 /// <param name="filter">the filter
572 ///
573 /// </param>
574 /// <param name="reference">true if a search reference
575 ///
576 /// </param>
577 /// <returns> the object representing the new message
578 /// </returns>
579 /* package */
580 internal LdapMessage Clone(System.String dn, System.String filter, bool reference)
582 return new LdapMessage((RfcLdapMessage) message.dupMessage(dn, filter, reference));
585 /// <summary> Instantiates an LdapControl. We search through our list of
586 /// registered controls. If we find a matchiing OID we instantiate
587 /// that control by calling its contructor. Otherwise we default to
588 /// returning a regular LdapControl object
589 ///
590 /// </summary>
591 private LdapControl controlFactory(System.String oid, bool critical, sbyte[] value_Renamed)
593 // throw new NotImplementedException();
594 RespControlVector regControls = LdapControl.RegisteredControls;
598 * search through the registered extension list to find the
599 * response control class
601 System.Type respCtlClass = regControls.findResponseControl(oid);
603 // Did not find a match so return default LDAPControl
604 if (respCtlClass == null)
605 return new LdapControl(oid, critical, value_Renamed);
607 /* If found, get LDAPControl constructor */
608 System.Type[] argsClass = new System.Type[]{typeof(System.String), typeof(bool), typeof(sbyte[])};
609 System.Object[] args = new System.Object[]{oid, critical, value_Renamed};
610 System.Exception ex = null;
613 System.Reflection.ConstructorInfo ctlConstructor = respCtlClass.GetConstructor(argsClass);
617 /* Call the control constructor for a registered Class*/
618 System.Object ctl = null;
619 // ctl = ctlConstructor.newInstance(args);
620 ctl = ctlConstructor.Invoke(args);
621 return (LdapControl) ctl;
623 catch (System.UnauthorizedAccessException e)
625 ex = e;
627 catch (System.Reflection.TargetInvocationException e)
629 ex = e;
631 catch (System.Exception e)
633 // Could not create the ResponseControl object
634 // All possible exceptions are ignored. We fall through
635 // and create a default LDAPControl object
636 ex = e;
640 catch (System.MethodAccessException e)
642 // bad class was specified, fall through and return a
643 // default LDAPControl object
644 ex = e;
647 catch (System.FieldAccessException e)
649 // No match with the OID
650 // Do nothing. Fall through and construct a default LDAPControl object.
652 // If we get here we did not have a registered response control
653 // for this oid. Return a default LDAPControl object.
654 return new LdapControl(oid, critical, value_Renamed);
658 /// <summary> Creates a String representation of this object
659 ///
660 /// </summary>
661 /// <returns> a String representation for this LdapMessage
662 /// </returns>
663 public override System.String ToString()
665 return Name + "(" + MessageID + "): " + message.ToString();