001    /*
002     *  Licensed to the Apache Software Foundation (ASF) under one
003     *  or more contributor license agreements.  See the NOTICE file
004     *  distributed with this work for additional information
005     *  regarding copyright ownership.  The ASF licenses this file
006     *  to you under the Apache License, Version 2.0 (the
007     *  "License"); you may not use this file except in compliance
008     *  with the License.  You may obtain a copy of the License at
009     *  
010     *    http://www.apache.org/licenses/LICENSE-2.0
011     *  
012     *  Unless required by applicable law or agreed to in writing,
013     *  software distributed under the License is distributed on an
014     *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     *  KIND, either express or implied.  See the License for the
016     *  specific language governing permissions and limitations
017     *  under the License. 
018     *  
019     */
020    
021    package org.apache.directory.shared.ldap.message;
022    
023    import org.apache.directory.shared.ldap.name.LdapDN;
024    
025    
026    /**
027     * LdapResult implementation.
028     * 
029     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
030     * @version $Revision: 764131 $
031     */
032    public class LdapResultImpl implements InternalLdapResult
033    {
034        static final long serialVersionUID = -1446626887394613213L;
035    
036        /** Lowest matched entry Dn - defaults to empty string */
037        private LdapDN matchedDn;
038    
039        /** Referral associated with this LdapResult if the errorCode is REFERRAL */
040        private InternalReferral referral;
041    
042        /** Decriptive error message - defaults to empty string */
043        private String errorMessage;
044    
045        /** Resultant operation error code - defaults to SUCCESS */
046        private ResultCodeEnum resultCode = ResultCodeEnum.SUCCESS;
047    
048    
049        // ------------------------------------------------------------------------
050        // LdapResult Interface Method Implementations
051        // ------------------------------------------------------------------------
052    
053        /**
054         * Gets the descriptive error message associated with the error code. May be
055         * null for SUCCESS, COMPARETRUE, COMPAREFALSE and REFERRAL operations.
056         * 
057         * @return the descriptive error message.
058         */
059        public String getErrorMessage()
060        {
061            return errorMessage;
062        }
063    
064    
065        /**
066         * Sets the descriptive error message associated with the error code. May be
067         * null for SUCCESS, COMPARETRUE, and COMPAREFALSE operations.
068         * 
069         * @param errorMessage
070         *            the descriptive error message.
071         */
072        public void setErrorMessage( String errorMessage )
073        {
074            this.errorMessage = errorMessage;
075        }
076    
077    
078        /**
079         * Gets the lowest entry in the directory that was matched. For result codes
080         * of noSuchObject, aliasProblem, invalidDNSyntax and
081         * aliasDereferencingProblem, the matchedDN field is set to the name of the
082         * lowest entry (object or alias) in the directory that was matched. If no
083         * aliases were dereferenced while attempting to locate the entry, this will
084         * be a truncated form of the name provided, or if aliases were
085         * dereferenced, of the resulting name, as defined in section 12.5 of X.511
086         * [8]. The matchedDN field is to be set to a zero length string with all
087         * other result codes.
088         * 
089         * @return the Dn of the lowest matched entry.
090         */
091        public LdapDN getMatchedDn()
092        {
093            return matchedDn;
094        }
095    
096    
097        /**
098         * Sets the lowest entry in the directory that was matched.
099         * 
100         * @see #getMatchedDn()
101         * @param matchedDn
102         *            the Dn of the lowest matched entry.
103         */
104        public void setMatchedDn( LdapDN matchedDn )
105        {
106            this.matchedDn = matchedDn;
107        }
108    
109    
110        /**
111         * Gets the result code enumeration associated with the response.
112         * Corresponds to the <b> resultCode </b> field within the LDAPResult ASN.1
113         * structure.
114         * 
115         * @return the result code enum value.
116         */
117        public ResultCodeEnum getResultCode()
118        {
119            return resultCode;
120        }
121    
122    
123        /**
124         * Sets the result code enumeration associated with the response.
125         * Corresponds to the <b> resultCode </b> field within the LDAPResult ASN.1
126         * structure.
127         * 
128         * @param resultCode
129         *            the result code enum value.
130         */
131        public void setResultCode( ResultCodeEnum resultCode )
132        {
133            this.resultCode = resultCode;
134        }
135    
136    
137        /**
138         * Gets the Referral associated with this LdapResult if the resultCode
139         * property is set to the REFERRAL ResultCodeEnum.
140         * 
141         * @return the referral on REFERRAL errors, null on all others.
142         */
143        public InternalReferral getReferral()
144        {
145            return referral;
146        }
147    
148    
149        /**
150         * Gets whether or not this result represents a Referral. For referrals the
151         * error code is set to REFERRAL and the referral property is not null.
152         * 
153         * @return true if this result represents a referral.
154         */
155        public boolean isReferral()
156        {
157            return referral != null;
158        }
159    
160    
161        /**
162         * Sets the Referral associated with this LdapResult if the resultCode
163         * property is set to the REFERRAL ResultCodeEnum. Setting this property
164         * will result in a true return from isReferral and the resultCode should be
165         * set to REFERRAL.
166         * 
167         * @param referral
168         *            optional referral on REFERRAL errors.
169         */
170        public void setReferral( InternalReferral referral )
171        {
172            this.referral = referral;
173        }
174    
175    
176        /**
177         * @param obj The object to compare with
178         * @return <code>true</code> if both objects are equals
179         */
180        public boolean equals( Object obj )
181        {
182            // quickly return true if this is the obj
183            if ( obj == this )
184            {
185                return true;
186            }
187    
188            // return false if object does not implement interface
189            if ( !( obj instanceof InternalLdapResult ) )
190            {
191                return false;
192            }
193    
194            // compare all the like elements of the two LdapResult objects
195            InternalLdapResult result = ( InternalLdapResult ) obj;
196    
197            if ( referral == null && result.getReferral() != null )
198            {
199                return false;
200            }
201    
202            if ( result.getReferral() == null && referral != null )
203            {
204                return false;
205            }
206    
207            if ( referral != null && result.getReferral() != null )
208            {
209                if ( !referral.equals( result.getReferral() ) )
210                {
211                    return false;
212                }
213            }
214    
215            if ( !resultCode.equals( result.getResultCode() ) )
216            {
217                return false;
218            }
219    
220            // Handle Error Messages where "" is considered equivalent to null
221            String errMsg0 = errorMessage;
222            String errMsg1 = result.getErrorMessage();
223    
224            if ( errMsg0 == null )
225            {
226                errMsg0 = "";
227            }
228    
229            if ( errMsg1 == null )
230            {
231                errMsg1 = "";
232            }
233    
234            if ( !errMsg0.equals( errMsg1 ) )
235            {
236                return false;
237            }
238    
239            if ( matchedDn != null )
240            {
241                if ( !matchedDn.equals( result.getMatchedDn() ) )
242                {
243                    return false;
244                }
245            }
246            else if ( result.getMatchedDn() != null ) // one is null other is not
247            {
248                return false;
249            }
250    
251            return true;
252        }
253    
254    
255        /**
256         * Get a String representation of a LdapResult
257         * 
258         * @return A LdapResult String
259         */
260        public String toString()
261        {
262    
263            StringBuffer sb = new StringBuffer();
264    
265            sb.append( "        Ldap Result\n" );
266            sb.append( "            Result code : (" ).append( resultCode ).append( ')' );
267    
268            switch ( resultCode )
269            {
270    
271                case SUCCESS :
272                    sb.append( " success\n" );
273                    break;
274    
275                case OPERATIONS_ERROR :
276                    sb.append( " operationsError\n" );
277                    break;
278    
279                case PROTOCOL_ERROR :
280                    sb.append( " protocolError\n" );
281                    break;
282    
283                case TIME_LIMIT_EXCEEDED :
284                    sb.append( " timeLimitExceeded\n" );
285                    break;
286    
287                case SIZE_LIMIT_EXCEEDED :
288                    sb.append( " sizeLimitExceeded\n" );
289                    break;
290    
291                case COMPARE_FALSE :
292                    sb.append( " compareFalse\n" );
293                    break;
294    
295                case COMPARE_TRUE :
296                    sb.append( " compareTrue\n" );
297                    break;
298    
299                case AUTH_METHOD_NOT_SUPPORTED :
300                    sb.append( " authMethodNotSupported\n" );
301                    break;
302    
303                case STRONG_AUTH_REQUIRED :
304                    sb.append( " strongAuthRequired\n" );
305                    break;
306    
307                case REFERRAL :
308                    sb.append( " referral -- new\n" );
309                    break;
310    
311                case ADMIN_LIMIT_EXCEEDED :
312                    sb.append( " adminLimitExceeded -- new\n" );
313                    break;
314    
315                case UNAVAILABLE_CRITICAL_EXTENSION :
316                    sb.append( " unavailableCriticalExtension -- new\n" );
317                    break;
318    
319                case CONFIDENTIALITY_REQUIRED :
320                    sb.append( " confidentialityRequired -- new\n" );
321                    break;
322    
323                case SASL_BIND_IN_PROGRESS :
324                    sb.append( " saslBindInProgress -- new\n" );
325                    break;
326    
327                case NO_SUCH_ATTRIBUTE :
328                    sb.append( " noSuchAttribute\n" );
329                    break;
330    
331                case UNDEFINED_ATTRIBUTE_TYPE :
332                    sb.append( " undefinedAttributeType\n" );
333                    break;
334    
335                case INAPPROPRIATE_MATCHING :
336                    sb.append( " inappropriateMatching\n" );
337                    break;
338    
339                case CONSTRAINT_VIOLATION :
340                    sb.append( " constraintViolation\n" );
341                    break;
342    
343                case ATTRIBUTE_OR_VALUE_EXISTS :
344                    sb.append( " attributeOrValueExists\n" );
345                    break;
346    
347                case INVALID_ATTRIBUTE_SYNTAX :
348                    sb.append( " invalidAttributeSyntax\n" );
349                    break;
350    
351                case NO_SUCH_OBJECT :
352                    sb.append( " noSuchObject\n" );
353                    break;
354    
355                case ALIAS_PROBLEM :
356                    sb.append( " aliasProblem\n" );
357                    break;
358    
359                case INVALID_DN_SYNTAX :
360                    sb.append( " invalidDNSyntax\n" );
361                    break;
362    
363                case ALIAS_DEREFERENCING_PROBLEM :
364                    sb.append( " aliasDereferencingProblem\n" );
365                    break;
366    
367                case INAPPROPRIATE_AUTHENTICATION :
368                    sb.append( " inappropriateAuthentication\n" );
369                    break;
370    
371                case INVALID_CREDENTIALS :
372                    sb.append( " invalidCredentials\n" );
373                    break;
374    
375                case INSUFFICIENT_ACCESS_RIGHTS :
376                    sb.append( " insufficientAccessRights\n" );
377                    break;
378    
379                case BUSY :
380                    sb.append( " busy\n" );
381                    break;
382    
383                case UNAVAILABLE :
384                    sb.append( " unavailable\n" );
385                    break;
386    
387                case UNWILLING_TO_PERFORM :
388                    sb.append( " unwillingToPerform\n" );
389                    break;
390    
391                case LOOP_DETECT :
392                    sb.append( " loopDetect\n" );
393                    break;
394    
395                case NAMING_VIOLATION :
396                    sb.append( " namingViolation\n" );
397                    break;
398    
399                case OBJECT_CLASS_VIOLATION :
400                    sb.append( " objectClassViolation\n" );
401                    break;
402    
403                case NOT_ALLOWED_ON_NON_LEAF :
404                    sb.append( " notAllowedOnNonLeaf\n" );
405                    break;
406    
407                case NOT_ALLOWED_ON_RDN :
408                    sb.append( " notAllowedOnRDN\n" );
409                    break;
410    
411                case ENTRY_ALREADY_EXISTS :
412                    sb.append( " entryAlreadyExists\n" );
413                    break;
414    
415                case OBJECT_CLASS_MODS_PROHIBITED :
416                    sb.append( " objectClassModsProhibited\n" );
417                    break;
418    
419                case AFFECTS_MULTIPLE_DSAS :
420                    sb.append( " affectsMultipleDSAs -- new\n" );
421                    break;
422    
423                case OTHER :
424                    sb.append( " other\n" );
425                    break;
426                    
427                default :
428                    switch ( resultCode.getResultCode() )
429                    {
430                        case 9 :
431                            sb.append( " -- 9 reserved --\n" );
432                            break;
433                            
434                        case 22 :
435                        case 23:
436                        case 24 :
437                        case 25 :
438                        case 26 :
439                        case 27 :
440                        case 28 :
441                        case 29 :
442                        case 30 :
443                        case 31 :
444                            sb.append( " -- 22-31 unused --\n" );
445                            break;
446    
447                        case 35 :
448                            sb.append( " -- 35 reserved for undefined isLeaf --\n" );
449                            break;
450                                    
451                        case 37 :
452                        case 38 :
453                        case 39 :
454                        case 40 :
455                        case 41 :
456                        case 42 :
457                        case 43 :
458                        case 44 :
459                        case 45 :
460                        case 46 :
461                        case 47 :
462                            sb.append( " -- 37-47 unused --\n" );
463                            break;
464    
465                        case 55 :
466                        case 56 :
467                        case 57 :
468                        case 58 :
469                        case 59 :
470                        case 60 :
471                        case 61 :
472                        case 62 :
473                        case 63 :
474                            sb.append( " -- 55-63 unused --\n" );
475                            break;
476    
477                        case 70 :
478                            sb.append( " -- 70 reserved for CLDAP --\n" );
479                            break;
480    
481                        case 72 :
482                        case 73 :
483                        case 74 :
484                        case 75 :
485                        case 76 :
486                        case 77 :
487                        case 78 :
488                        case 79 :
489                            sb.append( " -- 72-79 unused --\n" );
490                            break;
491    
492                        case 81 :
493                        case 82 :
494                        case 83 :
495                        case 84 :
496                        case 85 :
497                        case 86 :
498                        case 87 :
499                        case 88 :
500                        case 89 :
501                        case 90 :
502                            sb.append( " -- 81-90 reserved for APIs --" );
503                            break;
504                            
505                        default :
506                            sb.append( "Unknown error code : " ).append( resultCode );
507                            break;
508                    }
509            }
510    
511            sb.append( "            Matched DN : '" ).append( matchedDn ).append( "'\n" );
512            sb.append( "            Error message : '" ).append( errorMessage ).append( "'\n" );
513    
514            if ( referral != null )
515            {
516                sb.append( "            Referrals :\n" );
517    
518                sb.append( "                Referral :" ).append( referral.toString() ).append( '\n' );
519            }
520    
521            return sb.toString();
522        }
523    }