Class Files Representing Various LDAP Requests
[mono.git] / mcs / class / Novell.Directory.Ldap / Novell.Directory.Ldap / LdapResponse.cs
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:
11
12 * The above copyright notice and this permission notice shall be included in 
13 * all copies or substantial portions of the Software.
14
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 *******************************************************************************/
23 //
24 // Novell.Directory.Ldap.LdapResponse.cs
25 //
26 // Author:
27 //   Sunil Kumar (Sunilk@novell.com)
28 //
29 // (C) 2003 Novell, Inc (http://www.novell.com)
30 //
31
32 using System;
33 using Novell.Directory.Ldap.Asn1;
34 using Novell.Directory.Ldap.Rfc2251;
35 using Novell.Directory.Ldap.Utilclass;
36
37 namespace Novell.Directory.Ldap
38 {
39         
40         /// <summary>  A message received from an LdapServer
41         /// in response to an asynchronous request.
42         /// 
43         /// </summary>
44         /// <seealso cref="LdapConnection#search">
45         /// </seealso>
46         
47         /*
48         * Note: Exceptions generated by the reader thread are returned
49         * to the application as an exception in an LdapResponse.  Thus
50         * if <code>exception</code> has a value, it is not a server response,
51         * but instad an exception returned to the application from the API.
52         */
53         public class LdapResponse:LdapMessage
54         {
55                 /// <summary> Returns any error message in the response.
56                 /// 
57                 /// </summary>
58                 /// <returns> Any error message in the response.
59                 /// </returns>
60                 virtual public System.String ErrorMessage
61                 {
62                         get
63                         {
64                                 if (exception != null)
65                                 {
66                                         return exception.LdapErrorMessage;
67                                 }
68
69 /*                              RfcResponse resp=(RfcResponse)( message.Response);
70                                 if(resp == null)
71                                         Console.WriteLine(" Response is null");
72                                 else
73                                         Console.WriteLine(" Response is non null");
74                                 string str=resp.getErrorMessage().stringValue();
75                                 if( str==null)
76                                          Console.WriteLine("str is null..");
77                                 Console.WriteLine(" Response is non null" + str);
78                                 return str;
79 */
80                                 return ((RfcResponse) message.Response).getErrorMessage().stringValue();
81                         }
82                         
83                 }
84                 /// <summary> Returns the partially matched DN field from the server response,
85                 /// if the response contains one.
86                 /// 
87                 /// </summary>
88                 /// <returns> The partially matched DN field, if the response contains one.
89                 /// 
90                 /// </returns>
91                 virtual public System.String MatchedDN
92                 {
93                         get
94                         {
95                                 if (exception != null)
96                                 {
97                                         return exception.MatchedDN;
98                                 }
99                                 return ((RfcResponse) message.Response).getMatchedDN().stringValue();
100                         }
101                         
102                 }
103                 /// <summary> Returns all referrals in a server response, if the response contains any.
104                 /// 
105                 /// </summary>
106                 /// <returns> All the referrals in the server response.
107                 /// </returns>
108                 virtual public System.String[] Referrals
109                 {
110                         get
111                         {
112                                 System.String[] referrals = null;
113                                 RfcReferral ref_Renamed = ((RfcResponse) message.Response).getReferral();
114                                 
115                                 if (ref_Renamed == null)
116                                 {
117                                         referrals = new System.String[0];
118                                 }
119                                 else
120                                 {
121                                         // convert RFC 2251 Referral to String[]
122                                         int size = ref_Renamed.size();
123                                         referrals = new System.String[size];
124                                         for (int i = 0; i < size; i++)
125                                         {
126                                                 System.String aRef = ((Asn1OctetString) ref_Renamed.get_Renamed(i)).stringValue();
127                                                 try
128                                                 {
129                                                         // get the referral URL
130                                                         LdapUrl urlRef = new LdapUrl(aRef);
131                                                         if ((System.Object) urlRef.getDN() == null)
132                                                         {
133                                                                 RfcLdapMessage origMsg = base.Asn1Object.RequestingMessage.Asn1Object;
134                                                                 System.String dn;
135                                                                 if ((System.Object) (dn = origMsg.RequestDN) != null)
136                                                                 {
137                                                                         urlRef.setDN(dn);
138                                                                         aRef = urlRef.ToString();
139                                                                 }
140                                                         }
141                                                 }
142                                                 catch (System.UriFormatException mex)
143                                                 {
144                                                         ;
145                                                 }
146                                                 finally
147                                                 {
148                                                         referrals[i] = aRef;
149                                                 }
150                                         }
151                                 }
152                                 return referrals;
153                         }
154                         
155                 }
156                 /// <summary> Returns the result code in a server response.
157                 /// 
158                 /// <p> For a list of result codes, see the LdapException class. </p>
159                 /// 
160                 /// </summary>
161                 /// <returns> The result code.
162                 /// </returns>
163                 virtual public int ResultCode
164                 {
165                         get
166                         {
167                                 if (exception != null)
168                                 {
169                                         return exception.ResultCode;
170                                 }
171                                 return ((RfcResponse) message.Response).getResultCode().intValue();
172                         }
173                         
174                 }
175                 /// <summary> Checks the resultCode and generates the appropriate exception or
176                 /// null if success.
177                 /// </summary>
178                 virtual internal LdapException ResultException
179                 {
180                         /* package */
181                         
182                         get
183                         {
184                                 LdapException ex = null;
185                                 switch (ResultCode)
186                                 {
187                                         
188                                         case LdapException.SUCCESS: 
189                                         case LdapException.COMPARE_TRUE: 
190                                         case LdapException.COMPARE_FALSE: 
191                                                 break;
192                                         
193                                         case LdapException.REFERRAL: 
194                                                 System.String[] refs = Referrals;
195                                                 ex = new LdapReferralException("Automatic referral following not enabled", LdapException.REFERRAL, ErrorMessage);
196                                                 ((LdapReferralException) ex).setReferrals(refs);
197                                                 break;
198                                         
199                                         default: 
200                                                 ex = new LdapException(LdapException.resultCodeToString(ResultCode), ResultCode, ErrorMessage, MatchedDN);
201 //                                              ex = new LdapException("49", 49, "hello error", "hi error..");
202                                                 break;
203                                         
204                                 }
205                                 return ex;
206                         }
207                         
208                 }
209                 /// <summary> Returns any controls in the message.
210                 /// 
211                 /// </summary>
212                 /// <seealso cref="com.novell.ldap.LdapMessage#getControls()">
213                 /// </seealso>
214                 override public LdapControl[] Controls
215                 {
216                         get
217                         {
218                                 if (exception != null)
219                                 {
220                                         return null;
221                                 }
222                                 return base.Controls;
223                         }
224                         
225                 }
226                 /// <summary> Returns the message ID.
227                 /// 
228                 /// </summary>
229                 /// <seealso cref="com.novell.ldap.LdapMessage#getMessageID()">
230                 /// </seealso>
231                 override public int MessageID
232                 {
233                         get
234                         {
235                                 if (exception != null)
236                                 {
237                                         return exception.MessageID;
238                                 }
239                                 return base.MessageID;
240                         }
241                         
242                 }
243                 /// <summary> Returns the Ldap operation type of the message.
244                 /// 
245                 /// </summary>
246                 /// <returns> The operation type of the message.
247                 /// 
248                 /// </returns>
249                 /// <seealso cref="com.novell.ldap.LdapMessage#getType()">
250                 /// </seealso>
251                 override public int Type
252                 {
253                         get
254                         {
255                                 if (exception != null)
256                                 {
257                                         return exception.ReplyType;
258                                 }
259                                 return base.Type;
260                         }
261                         
262                 }
263                 /// <summary> Returns an embedded exception response
264                 /// 
265                 /// </summary>
266                 /// <returns> an embedded exception if any
267                 /// </returns>
268                 virtual internal LdapException Exception
269                 {
270                         /*package*/
271                         
272                         get
273                         {
274                                 return exception;
275                         }
276                         
277                 }
278                 /// <summary> Indicates the referral instance being followed if the
279                 /// connection created to follow referrals.
280                 /// 
281                 /// </summary>
282                 /// <returns> the referral being followed
283                 /// </returns>
284                 virtual internal ReferralInfo ActiveReferral
285                 {
286                         /*package*/
287                         
288                         get
289                         {
290                                 return activeReferral;
291                         }
292                         
293                 }
294                 private InterThreadException exception = null;
295                 private ReferralInfo activeReferral;
296                 
297                 /// <summary> Creates an LdapResponse using an LdapException.
298                 /// Used to wake up the user following an abandon.
299                 /// Note: The abandon doesn't have to be user initiated
300                 /// but may be the result of error conditions.
301                 /// <br>
302                 /// Referral information is available if this connection created solely
303                 /// to follow a referral.
304                 /// 
305                 /// </summary>
306                 /// <param name="ex"> The exception
307                 /// <br><br>
308                 /// </param>
309                 /// <param name="activeReferral"> The referral actually used to create the
310                 /// connection
311                 /// </param>
312                 public LdapResponse(InterThreadException ex, ReferralInfo activeReferral)
313                 {
314                         exception = ex;
315                         this.activeReferral = activeReferral;
316                         
317                         return ;
318                 }
319                 
320                 /// <summary> Creates a response LdapMessage when receiving an asynchronous
321                 /// response from a server.
322                 /// 
323                 /// </summary>
324                 /// <param name="message"> The RfcLdapMessage from a server.
325                 /// </param>
326                 /*package*/
327                 internal LdapResponse(RfcLdapMessage message):base(message)
328                 {
329                         return ;
330                 }
331                 
332                 /// <summary> Creates a SUCCESS response LdapMessage. Typically the response
333                 /// comes from a source other than a BER encoded Ldap message,
334                 /// such as from DSML.  Other values which are allowed in a response
335                 /// are set to their empty values.
336                 /// 
337                 /// </summary>
338                 /// <param name="type"> The message type as defined in LdapMessage.
339                 /// 
340                 /// </param>
341                 /// <seealso cref="LdapMessage">
342                 /// </seealso>
343                 public LdapResponse(int type):this(type, LdapException.SUCCESS, null, null, null, null)
344                 {
345                         return ;
346                 }
347                 
348                 /// <summary> Creates a response LdapMessage from parameters. Typically the data
349                 /// comes from a source other than a BER encoded Ldap message,
350                 /// such as from DSML.
351                 /// 
352                 /// </summary>
353                 /// <param name="type"> The message type as defined in LdapMessage.
354                 /// 
355                 /// </param>
356                 /// <param name="resultCode"> The result code as defined in LdapException.
357                 /// 
358                 /// </param>
359                 /// <param name="matchedDN">  The name of the lowest entry that was matched
360                 /// for some error result codes, an empty string
361                 /// or <code>null</code> if none.
362                 /// 
363                 /// </param>
364                 /// <param name="serverMessage"> A diagnostic message returned by the server,
365                 /// an empty string or <code>null</code> if none.
366                 /// 
367                 /// </param>
368                 /// <param name="referrals">  The referral URLs returned for a REFERRAL result
369                 /// code or <code>null</code> if none.
370                 /// 
371                 /// </param>
372                 /// <param name="controls">   Any controls returned by the server or
373                 /// <code>null</code> if none.
374                 /// 
375                 /// </param>
376                 /// <seealso cref="LdapMessage">
377                 /// </seealso>
378                 /// <seealso cref="LdapException">
379                 /// </seealso>
380                 public LdapResponse(int type, int resultCode, System.String matchedDN, System.String serverMessage, System.String[] referrals, LdapControl[] controls):base(new RfcLdapMessage(RfcResultFactory(type, resultCode, matchedDN, serverMessage, referrals)))
381                 {
382                         
383                         return ;
384                 }
385                 
386                 private static Asn1Sequence RfcResultFactory(int type, int resultCode, System.String matchedDN, System.String serverMessage, System.String[] referrals)
387                 {
388                         Asn1Sequence ret;
389                         
390                         if ((System.Object) matchedDN == null)
391                                 matchedDN = "";
392                         if ((System.Object) serverMessage == null)
393                                 serverMessage = "";
394                         
395                         switch (type)
396                         {
397                                 
398                                 case SEARCH_RESULT: 
399                                         ret = new RfcSearchResultDone(new Asn1Enumerated(resultCode), new RfcLdapDN(matchedDN), new RfcLdapString(serverMessage), null);
400                                         break;
401                                 
402                                 case BIND_RESPONSE: 
403                                         ret = null; // Not yet implemented
404                                         break;
405                                 
406                                 case SEARCH_RESPONSE: 
407                                         ret = null; // Not yet implemented
408                                         break;
409                                 
410                                 case MODIFY_RESPONSE: 
411                                         ret = new RfcModifyResponse(new Asn1Enumerated(resultCode), new RfcLdapDN(matchedDN), new RfcLdapString(serverMessage), null);
412                                         break;
413                                 
414                                 case ADD_RESPONSE: 
415                                         ret = new RfcAddResponse(new Asn1Enumerated(resultCode), new RfcLdapDN(matchedDN), new RfcLdapString(serverMessage), null);
416                                         break;
417                                 
418                                 case DEL_RESPONSE: 
419                                         ret = new RfcDelResponse(new Asn1Enumerated(resultCode), new RfcLdapDN(matchedDN), new RfcLdapString(serverMessage), null);
420                                         break;
421                                 
422                                 case MODIFY_RDN_RESPONSE: 
423                                         ret = new RfcModifyDNResponse(new Asn1Enumerated(resultCode), new RfcLdapDN(matchedDN), new RfcLdapString(serverMessage), null);
424                                         break;
425                                 
426                                 case COMPARE_RESPONSE: 
427                                         ret = new RfcCompareResponse(new Asn1Enumerated(resultCode), new RfcLdapDN(matchedDN), new RfcLdapString(serverMessage), null);
428                                         break;
429                                 
430                                 case SEARCH_RESULT_REFERENCE: 
431                                         ret = null; // Not yet implemented
432                                         break;
433                                 
434                                 case EXTENDED_RESPONSE: 
435                                         ret = null; // Not yet implemented
436                                         break;
437                                 
438                                 default: 
439                                         throw new System.SystemException("Type " + type + " Not Supported");
440                                 
441                         }
442                         return ret;
443                 }
444                 
445                 /// <summary> Checks the resultCode and throws the appropriate exception.
446                 /// 
447                 /// </summary>
448                 /// <exception cref=""> LdapException A general exception which includes an error
449                 /// message and an Ldap error code.
450                 /// </exception>
451                 /* package */
452                 internal virtual void  chkResultCode()
453                 {
454                         if (exception != null)
455                         {
456                                 throw exception;
457                         }
458                         else
459                         {
460                                 LdapException ex = ResultException;
461                                 if (ex != null)
462                                 {
463                                         throw ex;
464                                 }
465                                 return ;
466                         }
467                 }
468                 
469                 /* Methods from LdapMessage */
470                 
471                 /// <summary> Indicates if this response is an embedded exception response
472                 /// 
473                 /// </summary>
474                 /// <returns> true if contains an embedded Ldapexception
475                 /// </returns>
476                 /*package*/
477                 internal virtual bool hasException()
478                 {
479                         return (exception != null);
480                 }
481         }
482 }