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