001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2009 Sun Microsystems, Inc.
015 * Portions copyright 2013-2016 ForgeRock AS.
016 */
017package org.forgerock.opendj.ldap;
018
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.List;
022import java.util.LinkedHashMap;
023import java.util.Map;
024
025import org.forgerock.i18n.LocalizableMessage;
026
027import static com.forgerock.opendj.ldap.CoreMessages.*;
028
029/**
030 * An operation result code as defined in RFC 4511 section 4.1.9 is used to
031 * indicate the final status of an operation. If a server detects multiple
032 * errors for an operation, only one result code is returned. The server should
033 * return the result code that best indicates the nature of the error
034 * encountered. Servers may return substituted result codes to prevent
035 * unauthorized disclosures.
036 *
037 * @see <a href="http://tools.ietf.org/html/rfc4511#section-4.1.9">RFC 4511 -
038 *      Lightweight Directory Access Protocol (LDAP): The Protocol </a>
039 */
040public final class ResultCode {
041    /**
042     * Contains equivalent values for the ResultCode values.
043     * This allows easily using ResultCode values with switch statements.
044     */
045    public static enum Enum {
046        //@Checkstyle:off
047        /** @see ResultCode#UNDEFINED */
048        UNDEFINED,
049        /** @see ResultCode#SUCCESS */
050        SUCCESS,
051        /** @see ResultCode#OPERATIONS_ERROR */
052        OPERATIONS_ERROR,
053        /** @see ResultCode#PROTOCOL_ERROR */
054        PROTOCOL_ERROR,
055        /** @see ResultCode#TIME_LIMIT_EXCEEDED */
056        TIME_LIMIT_EXCEEDED,
057        /** @see ResultCode#SIZE_LIMIT_EXCEEDED */
058        SIZE_LIMIT_EXCEEDED,
059        /** @see ResultCode#COMPARE_FALSE */
060        COMPARE_FALSE,
061        /** @see ResultCode#COMPARE_TRUE */
062        COMPARE_TRUE,
063        /** @see ResultCode#AUTH_METHOD_NOT_SUPPORTED */
064        AUTH_METHOD_NOT_SUPPORTED,
065        /** @see ResultCode#STRONG_AUTH_REQUIRED */
066        STRONG_AUTH_REQUIRED,
067        /** @see ResultCode#REFERRAL */
068        REFERRAL,
069        /** @see ResultCode#ADMIN_LIMIT_EXCEEDED */
070        ADMIN_LIMIT_EXCEEDED,
071        /** @see ResultCode#UNAVAILABLE_CRITICAL_EXTENSION */
072        UNAVAILABLE_CRITICAL_EXTENSION,
073        /** @see ResultCode#CONFIDENTIALITY_REQUIRED */
074        CONFIDENTIALITY_REQUIRED,
075        /** @see ResultCode#SASL_BIND_IN_PROGRESS */
076        SASL_BIND_IN_PROGRESS,
077        /** @see ResultCode#NO_SUCH_ATTRIBUTE */
078        NO_SUCH_ATTRIBUTE,
079        /** @see ResultCode#UNDEFINED_ATTRIBUTE_TYPE */
080        UNDEFINED_ATTRIBUTE_TYPE,
081        /** @see ResultCode#INAPPROPRIATE_MATCHING */
082        INAPPROPRIATE_MATCHING,
083        /** @see ResultCode#CONSTRAINT_VIOLATION */
084        CONSTRAINT_VIOLATION,
085        /** @see ResultCode#ATTRIBUTE_OR_VALUE_EXISTS */
086        ATTRIBUTE_OR_VALUE_EXISTS,
087        /** @see ResultCode#INVALID_ATTRIBUTE_SYNTAX */
088        INVALID_ATTRIBUTE_SYNTAX,
089        /** @see ResultCode#NO_SUCH_OBJECT */
090        NO_SUCH_OBJECT,
091        /** @see ResultCode#ALIAS_PROBLEM */
092        ALIAS_PROBLEM,
093        /** @see ResultCode#INVALID_DN_SYNTAX */
094        INVALID_DN_SYNTAX,
095        /** @see ResultCode#ALIAS_DEREFERENCING_PROBLEM */
096        ALIAS_DEREFERENCING_PROBLEM,
097        /** @see ResultCode#INAPPROPRIATE_AUTHENTICATION */
098        INAPPROPRIATE_AUTHENTICATION,
099        /** @see ResultCode#INVALID_CREDENTIALS */
100        INVALID_CREDENTIALS,
101        /** @see ResultCode#INSUFFICIENT_ACCESS_RIGHTS */
102        INSUFFICIENT_ACCESS_RIGHTS,
103        /** @see ResultCode#BUSY */
104        BUSY,
105        /** @see ResultCode#UNAVAILABLE */
106        UNAVAILABLE,
107        /** @see ResultCode#UNWILLING_TO_PERFORM */
108        UNWILLING_TO_PERFORM,
109        /** @see ResultCode#LOOP_DETECT */
110        LOOP_DETECT,
111        /** @see ResultCode#SORT_CONTROL_MISSING */
112        SORT_CONTROL_MISSING,
113        /** @see ResultCode#OFFSET_RANGE_ERROR */
114        OFFSET_RANGE_ERROR,
115        /** @see ResultCode#NAMING_VIOLATION */
116        NAMING_VIOLATION,
117        /** @see ResultCode#OBJECTCLASS_VIOLATION */
118        OBJECTCLASS_VIOLATION,
119        /** @see ResultCode#NOT_ALLOWED_ON_NONLEAF */
120        NOT_ALLOWED_ON_NONLEAF,
121        /** @see ResultCode#NOT_ALLOWED_ON_RDN */
122        NOT_ALLOWED_ON_RDN,
123        /** @see ResultCode#ENTRY_ALREADY_EXISTS */
124        ENTRY_ALREADY_EXISTS,
125        /** @see ResultCode#OBJECTCLASS_MODS_PROHIBITED */
126        OBJECTCLASS_MODS_PROHIBITED,
127        /** @see ResultCode#AFFECTS_MULTIPLE_DSAS */
128        AFFECTS_MULTIPLE_DSAS,
129        /** @see ResultCode#VIRTUAL_LIST_VIEW_ERROR */
130        VIRTUAL_LIST_VIEW_ERROR,
131        /** @see ResultCode#OTHER */
132        OTHER,
133        /** @see ResultCode#CLIENT_SIDE_SERVER_DOWN */
134        CLIENT_SIDE_SERVER_DOWN,
135        /** @see ResultCode#CLIENT_SIDE_LOCAL_ERROR */
136        CLIENT_SIDE_LOCAL_ERROR,
137        /** @see ResultCode#CLIENT_SIDE_ENCODING_ERROR */
138        CLIENT_SIDE_ENCODING_ERROR,
139        /** @see ResultCode#CLIENT_SIDE_DECODING_ERROR */
140        CLIENT_SIDE_DECODING_ERROR,
141        /** @see ResultCode#CLIENT_SIDE_TIMEOUT */
142        CLIENT_SIDE_TIMEOUT,
143        /** @see ResultCode#CLIENT_SIDE_AUTH_UNKNOWN */
144        CLIENT_SIDE_AUTH_UNKNOWN,
145        /** @see ResultCode#CLIENT_SIDE_FILTER_ERROR */
146        CLIENT_SIDE_FILTER_ERROR,
147        /** @see ResultCode#CLIENT_SIDE_USER_CANCELLED */
148        CLIENT_SIDE_USER_CANCELLED,
149        /** @see ResultCode#CLIENT_SIDE_PARAM_ERROR */
150        CLIENT_SIDE_PARAM_ERROR,
151        /** @see ResultCode#CLIENT_SIDE_NO_MEMORY */
152        CLIENT_SIDE_NO_MEMORY,
153        /** @see ResultCode#CLIENT_SIDE_CONNECT_ERROR */
154        CLIENT_SIDE_CONNECT_ERROR,
155        /** @see ResultCode#CLIENT_SIDE_NOT_SUPPORTED */
156        CLIENT_SIDE_NOT_SUPPORTED,
157        /** @see ResultCode#CLIENT_SIDE_CONTROL_NOT_FOUND */
158        CLIENT_SIDE_CONTROL_NOT_FOUND,
159        /** @see ResultCode#CLIENT_SIDE_NO_RESULTS_RETURNED */
160        CLIENT_SIDE_NO_RESULTS_RETURNED,
161        /** @see ResultCode#CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED */
162        CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED,
163        /** @see ResultCode#CLIENT_SIDE_CLIENT_LOOP */
164        CLIENT_SIDE_CLIENT_LOOP,
165        /** @see ResultCode#CLIENT_SIDE_REFERRAL_LIMIT_EXCEEDED */
166        CLIENT_SIDE_REFERRAL_LIMIT_EXCEEDED,
167        /** @see ResultCode#CANCELLED */
168        CANCELLED,
169        /** @see ResultCode#NO_SUCH_OPERATION */
170        NO_SUCH_OPERATION,
171        /** @see ResultCode#TOO_LATE */
172        TOO_LATE,
173        /** @see ResultCode#CANNOT_CANCEL */
174        CANNOT_CANCEL,
175        /** @see ResultCode#ASSERTION_FAILED */
176        ASSERTION_FAILED,
177        /** @see ResultCode#AUTHORIZATION_DENIED */
178        AUTHORIZATION_DENIED,
179        /** @see ResultCode#NO_OPERATION */
180        NO_OPERATION,
181        /** Used for unknown search scopes. */
182        UNKNOWN;
183        //@Checkstyle:on
184    }
185
186    private static final Map<Integer, ResultCode> ELEMENTS = new LinkedHashMap<>();
187
188    /**
189     * The result code that should only be used if the actual result code has
190     * not yet been determined.
191     * <p>
192     * Despite not being a standard result code, it is an implementation of the
193     * null object design pattern for this type.
194     */
195    public static final ResultCode UNDEFINED = registerErrorResultCode(-1,
196            INFO_RESULT_UNDEFINED.get(), Enum.UNDEFINED);
197
198    /**
199     * The result code that indicates that the operation completed successfully.
200     * <p>
201     * This result code corresponds to the LDAP result code value of {@code 0}.
202     */
203    public static final ResultCode SUCCESS =
204            registerSuccessResultCode(0, INFO_RESULT_SUCCESS.get(), Enum.SUCCESS);
205
206    /**
207     * The result code that indicates that an internal error prevented the
208     * operation from being processed properly.
209     * <p>
210     * This result code corresponds to the LDAP result code value of {@code 1}.
211     */
212    public static final ResultCode OPERATIONS_ERROR = registerErrorResultCode(1,
213            INFO_RESULT_OPERATIONS_ERROR.get(), Enum.OPERATIONS_ERROR);
214
215    /**
216     * The result code that indicates that the client sent a malformed or
217     * illegal request to the server.
218     * <p>
219     * This result code corresponds to the LDAP result code value of {@code 2}.
220     */
221    public static final ResultCode PROTOCOL_ERROR = registerErrorResultCode(2,
222            INFO_RESULT_PROTOCOL_ERROR.get(), Enum.PROTOCOL_ERROR);
223
224    /**
225     * The result code that indicates that a time limit was exceeded while
226     * attempting to process the request.
227     * <p>
228     * This result code corresponds to the LDAP result code value of {@code 3}.
229     */
230    public static final ResultCode TIME_LIMIT_EXCEEDED = registerErrorResultCode(3,
231            INFO_RESULT_TIME_LIMIT_EXCEEDED.get(), Enum.TIME_LIMIT_EXCEEDED);
232
233    /**
234     * The result code that indicates that a size limit was exceeded while
235     * attempting to process the request.
236     * <p>
237     * This result code corresponds to the LDAP result code value of {@code 4}.
238     */
239    public static final ResultCode SIZE_LIMIT_EXCEEDED = registerErrorResultCode(4,
240            INFO_RESULT_SIZE_LIMIT_EXCEEDED.get(), Enum.SIZE_LIMIT_EXCEEDED);
241
242    /**
243     * The result code that indicates that the attribute value assertion
244     * included in a compare request did not match the targeted entry.
245     * <p>
246     * This result code corresponds to the LDAP result code value of {@code 5}.
247     */
248    public static final ResultCode COMPARE_FALSE = registerSuccessResultCode(5,
249            INFO_RESULT_COMPARE_FALSE.get(), Enum.COMPARE_FALSE);
250
251    /**
252     * The result code that indicates that the attribute value assertion
253     * included in a compare request did match the targeted entry.
254     * <p>
255     * This result code corresponds to the LDAP result code value of {@code 6}.
256     */
257    public static final ResultCode COMPARE_TRUE = registerSuccessResultCode(6,
258            INFO_RESULT_COMPARE_TRUE.get(), Enum.COMPARE_TRUE);
259
260    /**
261     * The result code that indicates that the requested authentication attempt
262     * failed because it referenced an invalid SASL mechanism.
263     * <p>
264     * This result code corresponds to the LDAP result code value of {@code 7}.
265     */
266    public static final ResultCode AUTH_METHOD_NOT_SUPPORTED = registerErrorResultCode(7,
267            INFO_RESULT_AUTH_METHOD_NOT_SUPPORTED.get(), Enum.AUTH_METHOD_NOT_SUPPORTED);
268
269    /**
270     * The result code that indicates that the requested operation could not be
271     * processed because it requires that the client has completed a strong form
272     * of authentication.
273     * <p>
274     * This result code corresponds to the LDAP result code value of {@code 8}.
275     */
276    public static final ResultCode STRONG_AUTH_REQUIRED = registerErrorResultCode(8,
277            INFO_RESULT_STRONG_AUTH_REQUIRED.get(), Enum.STRONG_AUTH_REQUIRED);
278
279    /**
280     * The result code that indicates that a referral was encountered.
281     * <p>
282     * Strictly speaking this result code should not be exceptional since it is
283     * considered as a "success" response. However, referrals should occur
284     * rarely in practice and, when they do occur, should not be ignored since
285     * the application may believe that a request has succeeded when, in fact,
286     * nothing was done.
287     * <p>
288     * This result code corresponds to the LDAP result code value of {@code 10}.
289     */
290    public static final ResultCode REFERRAL = registerErrorResultCode(10, INFO_RESULT_REFERRAL
291            .get(), Enum.REFERRAL);
292
293    /**
294     * The result code that indicates that processing on the requested operation
295     * could not continue because an administrative limit was exceeded.
296     * <p>
297     * This result code corresponds to the LDAP result code value of {@code 11}.
298     */
299    public static final ResultCode ADMIN_LIMIT_EXCEEDED = registerErrorResultCode(11,
300            INFO_RESULT_ADMIN_LIMIT_EXCEEDED.get(), Enum.ADMIN_LIMIT_EXCEEDED);
301
302    /**
303     * The result code that indicates that the requested operation failed
304     * because it included a critical extension that is unsupported or
305     * inappropriate for that request.
306     * <p>
307     * This result code corresponds to the LDAP result code value of {@code 12}.
308     */
309    public static final ResultCode UNAVAILABLE_CRITICAL_EXTENSION = registerErrorResultCode(12,
310            INFO_RESULT_UNAVAILABLE_CRITICAL_EXTENSION.get(), Enum.UNAVAILABLE_CRITICAL_EXTENSION);
311
312    /**
313     * The result code that indicates that the requested operation could not be
314     * processed because it requires confidentiality for the communication
315     * between the client and the server.
316     * <p>
317     * This result code corresponds to the LDAP result code value of {@code 13}.
318     */
319    public static final ResultCode CONFIDENTIALITY_REQUIRED = registerErrorResultCode(13,
320            INFO_RESULT_CONFIDENTIALITY_REQUIRED.get(), Enum.CONFIDENTIALITY_REQUIRED);
321
322    /**
323     * The result code that should be used for intermediate responses in
324     * multi-stage SASL bind operations.
325     * <p>
326     * This result code corresponds to the LDAP result code value of {@code 14}.
327     */
328    public static final ResultCode SASL_BIND_IN_PROGRESS = registerSuccessResultCode(14,
329            INFO_RESULT_SASL_BIND_IN_PROGRESS.get(), Enum.SASL_BIND_IN_PROGRESS);
330
331    /**
332     * The result code that indicates that the requested operation failed
333     * because it targeted an attribute or attribute value that did not exist in
334     * the specified entry.
335     * <p>
336     * This result code corresponds to the LDAP result code value of {@code 16}.
337     */
338    public static final ResultCode NO_SUCH_ATTRIBUTE = registerErrorResultCode(16,
339            INFO_RESULT_NO_SUCH_ATTRIBUTE.get(), Enum.NO_SUCH_ATTRIBUTE);
340
341    /**
342     * The result code that indicates that the requested operation failed
343     * because it referenced an attribute that is not defined in the server
344     * schema.
345     * <p>
346     * This result code corresponds to the LDAP result code value of {@code 17}.
347     */
348    public static final ResultCode UNDEFINED_ATTRIBUTE_TYPE = registerErrorResultCode(17,
349            INFO_RESULT_UNDEFINED_ATTRIBUTE_TYPE.get(), Enum.UNDEFINED_ATTRIBUTE_TYPE);
350
351    /**
352     * The result code that indicates that the requested operation failed
353     * because it attempted to perform an inappropriate type of matching against
354     * an attribute.
355     * <p>
356     * This result code corresponds to the LDAP result code value of {@code 18}.
357     */
358    public static final ResultCode INAPPROPRIATE_MATCHING = registerErrorResultCode(18,
359            INFO_RESULT_INAPPROPRIATE_MATCHING.get(), Enum.INAPPROPRIATE_MATCHING);
360
361    /**
362     * The result code that indicates that the requested operation failed
363     * because it would have violated some constraint defined in the server.
364     * <p>
365     * This result code corresponds to the LDAP result code value of {@code 19}.
366     */
367    public static final ResultCode CONSTRAINT_VIOLATION = registerErrorResultCode(19,
368            INFO_RESULT_CONSTRAINT_VIOLATION.get(), Enum.CONSTRAINT_VIOLATION);
369
370    /**
371     * The result code that indicates that the requested operation failed
372     * because it would have resulted in a conflict with an existing attribute
373     * or attribute value in the target entry.
374     * <p>
375     * This result code corresponds to the LDAP result code value of {@code 20}.
376     */
377    public static final ResultCode ATTRIBUTE_OR_VALUE_EXISTS = registerErrorResultCode(20,
378            INFO_RESULT_ATTRIBUTE_OR_VALUE_EXISTS.get(), Enum.ATTRIBUTE_OR_VALUE_EXISTS);
379
380    /**
381     * The result code that indicates that the requested operation failed
382     * because it violated the syntax for a specified attribute.
383     * <p>
384     * This result code corresponds to the LDAP result code value of {@code 21}.
385     */
386    public static final ResultCode INVALID_ATTRIBUTE_SYNTAX = registerErrorResultCode(21,
387            INFO_RESULT_INVALID_ATTRIBUTE_SYNTAX.get(), Enum.INVALID_ATTRIBUTE_SYNTAX);
388
389    /**
390     * The result code that indicates that the requested operation failed
391     * because it referenced an entry that does not exist.
392     * <p>
393     * This result code corresponds to the LDAP result code value of {@code 32}.
394     */
395    public static final ResultCode NO_SUCH_OBJECT = registerErrorResultCode(32,
396            INFO_RESULT_NO_SUCH_OBJECT.get(), Enum.NO_SUCH_OBJECT);
397
398    /**
399     * The result code that indicates that the requested operation failed
400     * because it attempted to perform an illegal operation on an alias.
401     * <p>
402     * This result code corresponds to the LDAP result code value of {@code 33}.
403     */
404    public static final ResultCode ALIAS_PROBLEM = registerErrorResultCode(33,
405            INFO_RESULT_ALIAS_PROBLEM.get(), Enum.ALIAS_PROBLEM);
406
407    /**
408     * The result code that indicates that the requested operation failed
409     * because it would have resulted in an entry with an invalid or malformed
410     * DN.
411     * <p>
412     * This result code corresponds to the LDAP result code value of {@code 34}.
413     */
414    public static final ResultCode INVALID_DN_SYNTAX = registerErrorResultCode(34,
415            INFO_RESULT_INVALID_DN_SYNTAX.get(), Enum.INVALID_DN_SYNTAX);
416
417    /**
418     * The result code that indicates that a problem was encountered while
419     * attempting to dereference an alias for a search operation.
420     * <p>
421     * This result code corresponds to the LDAP result code value of {@code 36}.
422     */
423    public static final ResultCode ALIAS_DEREFERENCING_PROBLEM = registerErrorResultCode(36,
424            INFO_RESULT_ALIAS_DEREFERENCING_PROBLEM.get(), Enum.ALIAS_DEREFERENCING_PROBLEM);
425
426    /**
427     * The result code that indicates that an authentication attempt failed
428     * because the requested type of authentication was not appropriate for the
429     * targeted entry.
430     * <p>
431     * This result code corresponds to the LDAP result code value of {@code 48}.
432     */
433    public static final ResultCode INAPPROPRIATE_AUTHENTICATION = registerErrorResultCode(48,
434            INFO_RESULT_INAPPROPRIATE_AUTHENTICATION.get(), Enum.INAPPROPRIATE_AUTHENTICATION);
435
436    /**
437     * The result code that indicates that an authentication attempt failed
438     * because the user did not provide a valid set of credentials.
439     * <p>
440     * This result code corresponds to the LDAP result code value of {@code 49}.
441     */
442    public static final ResultCode INVALID_CREDENTIALS = registerErrorResultCode(49,
443            INFO_RESULT_INVALID_CREDENTIALS.get(), Enum.INVALID_CREDENTIALS);
444
445    /**
446     * The result code that indicates that the client does not have sufficient
447     * permission to perform the requested operation.
448     * <p>
449     * This result code corresponds to the LDAP result code value of {@code 50}.
450     */
451    public static final ResultCode INSUFFICIENT_ACCESS_RIGHTS = registerErrorResultCode(50,
452            INFO_RESULT_INSUFFICIENT_ACCESS_RIGHTS.get(), Enum.INSUFFICIENT_ACCESS_RIGHTS);
453
454    /**
455     * The result code that indicates that the server is too busy to process the
456     * requested operation.
457     * <p>
458     * This result code corresponds to the LDAP result code value of {@code 51}.
459     */
460    public static final ResultCode BUSY = registerErrorResultCode(51, INFO_RESULT_BUSY.get(), Enum.BUSY);
461
462    /**
463     * The result code that indicates that either the entire server or one or
464     * more required resources were not available for use in processing the
465     * request.
466     * <p>
467     * This result code corresponds to the LDAP result code value of {@code 52}.
468     */
469    public static final ResultCode UNAVAILABLE = registerErrorResultCode(52,
470            INFO_RESULT_UNAVAILABLE.get(), Enum.UNAVAILABLE);
471
472    /**
473     * The result code that indicates that the server is unwilling to perform
474     * the requested operation.
475     * <p>
476     * This result code corresponds to the LDAP result code value of {@code 53}.
477     */
478    public static final ResultCode UNWILLING_TO_PERFORM = registerErrorResultCode(53,
479            INFO_RESULT_UNWILLING_TO_PERFORM.get(), Enum.UNWILLING_TO_PERFORM);
480
481    /**
482     * The result code that indicates that a referral or chaining loop was
483     * detected while processing the request.
484     * <p>
485     * This result code corresponds to the LDAP result code value of {@code 54}.
486     */
487    public static final ResultCode LOOP_DETECT = registerErrorResultCode(54,
488            INFO_RESULT_LOOP_DETECT.get(), Enum.LOOP_DETECT);
489
490    /**
491     * The result code that indicates that a search request included a VLV
492     * request control without a server-side sort control.
493     * <p>
494     * This result code corresponds to the LDAP result code value of {@code 60}.
495     */
496    public static final ResultCode SORT_CONTROL_MISSING = registerErrorResultCode(60,
497            INFO_RESULT_SORT_CONTROL_MISSING.get(), Enum.SORT_CONTROL_MISSING);
498
499    /**
500     * The result code that indicates that a search request included a VLV
501     * request control with an invalid offset.
502     * <p>
503     * This result code corresponds to the LDAP result code value of {@code 61}.
504     */
505    public static final ResultCode OFFSET_RANGE_ERROR = registerErrorResultCode(61,
506            INFO_RESULT_OFFSET_RANGE_ERROR.get(), Enum.OFFSET_RANGE_ERROR);
507
508    /**
509     * The result code that indicates that the requested operation failed
510     * because it would have violated the server's naming configuration.
511     * <p>
512     * This result code corresponds to the LDAP result code value of {@code 64}.
513     */
514    public static final ResultCode NAMING_VIOLATION = registerErrorResultCode(64,
515            INFO_RESULT_NAMING_VIOLATION.get(), Enum.NAMING_VIOLATION);
516
517    /**
518     * The result code that indicates that the requested operation failed
519     * because it would have resulted in an entry that violated the server
520     * schema.
521     * <p>
522     * This result code corresponds to the LDAP result code value of {@code 65}.
523     */
524    public static final ResultCode OBJECTCLASS_VIOLATION = registerErrorResultCode(65,
525            INFO_RESULT_OBJECTCLASS_VIOLATION.get(), Enum.OBJECTCLASS_VIOLATION);
526
527    /**
528     * The result code that indicates that the requested operation is not
529     * allowed for non-leaf entries.
530     * <p>
531     * This result code corresponds to the LDAP result code value of {@code 66}.
532     */
533    public static final ResultCode NOT_ALLOWED_ON_NONLEAF = registerErrorResultCode(66,
534            INFO_RESULT_NOT_ALLOWED_ON_NONLEAF.get(), Enum.NOT_ALLOWED_ON_NONLEAF);
535
536    /**
537     * The result code that indicates that the requested operation is not
538     * allowed on an RDN attribute.
539     * <p>
540     * This result code corresponds to the LDAP result code value of {@code 67}.
541     */
542    public static final ResultCode NOT_ALLOWED_ON_RDN = registerErrorResultCode(67,
543            INFO_RESULT_NOT_ALLOWED_ON_RDN.get(), Enum.NOT_ALLOWED_ON_RDN);
544
545    /**
546     * The result code that indicates that the requested operation failed
547     * because it would have resulted in an entry that conflicts with an entry
548     * that already exists.
549     * <p>
550     * This result code corresponds to the LDAP result code value of {@code 68}.
551     */
552    public static final ResultCode ENTRY_ALREADY_EXISTS = registerErrorResultCode(68,
553            INFO_RESULT_ENTRY_ALREADY_EXISTS.get(), Enum.ENTRY_ALREADY_EXISTS);
554
555    /**
556     * The result code that indicates that the operation could not be processed
557     * because it would have modified the objectclasses associated with an entry
558     * in an illegal manner.
559     * <p>
560     * This result code corresponds to the LDAP result code value of {@code 69}.
561     */
562    public static final ResultCode OBJECTCLASS_MODS_PROHIBITED = registerErrorResultCode(69,
563            INFO_RESULT_OBJECTCLASS_MODS_PROHIBITED.get(), Enum.OBJECTCLASS_MODS_PROHIBITED);
564
565    /**
566     * The result code that indicates that the operation could not be processed
567     * because it would impact multiple DSAs or other repositories.
568     * <p>
569     * This result code corresponds to the LDAP result code value of {@code 71}.
570     */
571    public static final ResultCode AFFECTS_MULTIPLE_DSAS = registerErrorResultCode(71,
572            INFO_RESULT_AFFECTS_MULTIPLE_DSAS.get(), Enum.AFFECTS_MULTIPLE_DSAS);
573
574    /**
575     * The result code that indicates that the operation could not be processed
576     * because there was an error while processing the virtual list view
577     * control.
578     * <p>
579     * This result code corresponds to the LDAP result code value of {@code 76}.
580     */
581    public static final ResultCode VIRTUAL_LIST_VIEW_ERROR = registerErrorResultCode(76,
582            INFO_RESULT_VIRTUAL_LIST_VIEW_ERROR.get(), Enum.VIRTUAL_LIST_VIEW_ERROR);
583
584    /**
585     * The result code that should be used if no other result code is
586     * appropriate.
587     * <p>
588     * This result code corresponds to the LDAP result code value of {@code 80}.
589     */
590    public static final ResultCode OTHER = registerErrorResultCode(80, INFO_RESULT_OTHER.get(), Enum.OTHER);
591
592    /**
593     * The client-side result code that indicates that a previously-established
594     * connection to the server was lost. This is for client-side use only and
595     * should never be transferred over protocol.
596     * <p>
597     * This result code corresponds to the LDAP result code value of {@code 81}.
598     */
599    public static final ResultCode CLIENT_SIDE_SERVER_DOWN = registerErrorResultCode(81,
600            INFO_RESULT_CLIENT_SIDE_SERVER_DOWN.get(), Enum.CLIENT_SIDE_SERVER_DOWN);
601
602    /**
603     * The client-side result code that indicates that a local error occurred
604     * that had nothing to do with interaction with the server. This is for
605     * client-side use only and should never be transferred over protocol.
606     * <p>
607     * This result code corresponds to the LDAP result code value of {@code 82}.
608     */
609    public static final ResultCode CLIENT_SIDE_LOCAL_ERROR = registerErrorResultCode(82,
610            INFO_RESULT_CLIENT_SIDE_LOCAL_ERROR.get(), Enum.CLIENT_SIDE_LOCAL_ERROR);
611
612    /**
613     * The client-side result code that indicates that an error occurred while
614     * encoding a request to send to the server. This is for client-side use
615     * only and should never be transferred over protocol.
616     * <p>
617     * This result code corresponds to the LDAP result code value of {@code 83}.
618     */
619    public static final ResultCode CLIENT_SIDE_ENCODING_ERROR = registerErrorResultCode(83,
620            INFO_RESULT_CLIENT_SIDE_ENCODING_ERROR.get(), Enum.CLIENT_SIDE_ENCODING_ERROR);
621
622    /**
623     * The client-side result code that indicates that an error occurred while
624     * decoding a response from the server. This is for client-side use only and
625     * should never be transferred over protocol.
626     * <p>
627     * This result code corresponds to the LDAP result code value of {@code 84}.
628     */
629    public static final ResultCode CLIENT_SIDE_DECODING_ERROR = registerErrorResultCode(84,
630            INFO_RESULT_CLIENT_SIDE_DECODING_ERROR.get(), Enum.CLIENT_SIDE_DECODING_ERROR);
631
632    /**
633     * The client-side result code that indicates that the client did not
634     * receive an expected response in a timely manner. This is for client-side
635     * use only and should never be transferred over protocol.
636     * <p>
637     * This result code corresponds to the LDAP result code value of {@code 85}.
638     */
639    public static final ResultCode CLIENT_SIDE_TIMEOUT = registerErrorResultCode(85,
640            INFO_RESULT_CLIENT_SIDE_TIMEOUT.get(), Enum.CLIENT_SIDE_TIMEOUT);
641
642    /**
643     * The client-side result code that indicates that the user requested an
644     * unknown or unsupported authentication mechanism. This is for client-side
645     * use only and should never be transferred over protocol.
646     * <p>
647     * This result code corresponds to the LDAP result code value of {@code 86}.
648     */
649    public static final ResultCode CLIENT_SIDE_AUTH_UNKNOWN = registerErrorResultCode(86,
650            INFO_RESULT_CLIENT_SIDE_AUTH_UNKNOWN.get(), Enum.CLIENT_SIDE_AUTH_UNKNOWN);
651
652    /**
653     * The client-side result code that indicates that the filter provided by
654     * the user was malformed and could not be parsed. This is for client-side
655     * use only and should never be transferred over protocol.
656     * <p>
657     * This result code corresponds to the LDAP result code value of {@code 87}.
658     */
659    public static final ResultCode CLIENT_SIDE_FILTER_ERROR = registerErrorResultCode(87,
660            INFO_RESULT_CLIENT_SIDE_FILTER_ERROR.get(), Enum.CLIENT_SIDE_FILTER_ERROR);
661
662    /**
663     * The client-side result code that indicates that the user cancelled an
664     * operation. This is for client-side use only and should never be
665     * transferred over protocol.
666     * <p>
667     * This result code corresponds to the LDAP result code value of {@code 88}.
668     */
669    public static final ResultCode CLIENT_SIDE_USER_CANCELLED = registerErrorResultCode(88,
670            INFO_RESULT_CLIENT_SIDE_USER_CANCELLED.get(), Enum.CLIENT_SIDE_USER_CANCELLED);
671
672    /**
673     * The client-side result code that indicates that there was a problem with
674     * one or more of the parameters provided by the user. This is for
675     * client-side use only and should never be transferred over protocol.
676     * <p>
677     * This result code corresponds to the LDAP result code value of {@code 89}.
678     */
679    public static final ResultCode CLIENT_SIDE_PARAM_ERROR = registerErrorResultCode(89,
680            INFO_RESULT_CLIENT_SIDE_PARAM_ERROR.get(), Enum.CLIENT_SIDE_PARAM_ERROR);
681
682    /**
683     * The client-side result code that indicates that the client application
684     * was not able to allocate enough memory for the requested operation. This
685     * is for client-side use only and should never be transferred over
686     * protocol.
687     * <p>
688     * This result code corresponds to the LDAP result code value of {@code 90}.
689     */
690    public static final ResultCode CLIENT_SIDE_NO_MEMORY = registerErrorResultCode(90,
691            INFO_RESULT_CLIENT_SIDE_NO_MEMORY.get(), Enum.CLIENT_SIDE_NO_MEMORY);
692
693    /**
694     * The client-side result code that indicates that the client was not able
695     * to establish a connection to the server. This is for client-side use only
696     * and should never be transferred over protocol.
697     * <p>
698     * This result code corresponds to the LDAP result code value of {@code 91}.
699     */
700    public static final ResultCode CLIENT_SIDE_CONNECT_ERROR = registerErrorResultCode(91,
701            INFO_RESULT_CLIENT_SIDE_CONNECT_ERROR.get(), Enum.CLIENT_SIDE_CONNECT_ERROR);
702
703    /**
704     * The client-side result code that indicates that the user requested an
705     * operation that is not supported. This is for client-side use only and
706     * should never be transferred over protocol.
707     * <p>
708     * This result code corresponds to the LDAP result code value of {@code 92}.
709     */
710    public static final ResultCode CLIENT_SIDE_NOT_SUPPORTED = registerErrorResultCode(92,
711            INFO_RESULT_CLIENT_SIDE_NOT_SUPPORTED.get(), Enum.CLIENT_SIDE_NOT_SUPPORTED);
712
713    /**
714     * The client-side result code that indicates that the client expected a
715     * control to be present in the response from the server but it was not
716     * included. This is for client-side use only and should never be
717     * transferred over protocol.
718     * <p>
719     * This result code corresponds to the LDAP result code value of {@code 93}.
720     */
721    public static final ResultCode CLIENT_SIDE_CONTROL_NOT_FOUND = registerErrorResultCode(93,
722            INFO_RESULT_CLIENT_SIDE_CONTROL_NOT_FOUND.get(), Enum.CLIENT_SIDE_CONTROL_NOT_FOUND);
723
724    /**
725     * The client-side result code that indicates that the requested single
726     * entry search operation or read operation failed because the Directory
727     * Server did not return any matching entries. This is for client-side use
728     * only and should never be transferred over protocol.
729     * <p>
730     * This result code corresponds to the LDAP result code value of {@code 94}.
731     */
732    public static final ResultCode CLIENT_SIDE_NO_RESULTS_RETURNED = registerErrorResultCode(94,
733            INFO_RESULT_CLIENT_SIDE_NO_RESULTS_RETURNED.get(), Enum.CLIENT_SIDE_NO_RESULTS_RETURNED);
734
735    /**
736     * The client-side result code that the requested single entry search
737     * operation or read operation failed because the Directory Server returned
738     * multiple matching entries (or search references) when only a single
739     * matching entry was expected. This is for client-side use only and should
740     * never be transferred over protocol.
741     * <p>
742     * This result code corresponds to the LDAP result code value of {@code 95}.
743     */
744    public static final ResultCode CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED = registerErrorResultCode(95,
745            INFO_RESULT_CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED.get(), Enum.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED);
746
747    /**
748     * The client-side result code that indicates that the client detected a
749     * referral loop caused by servers referencing each other in a circular
750     * manner. This is for client-side use only and should never be transferred
751     * over protocol.
752     * <p>
753     * This result code corresponds to the LDAP result code value of {@code 96}.
754     */
755    public static final ResultCode CLIENT_SIDE_CLIENT_LOOP = registerErrorResultCode(96,
756            INFO_RESULT_CLIENT_SIDE_CLIENT_LOOP.get(), Enum.CLIENT_SIDE_CLIENT_LOOP);
757
758    /**
759     * The client-side result code that indicates that the client reached the
760     * maximum number of hops allowed when attempting to follow a referral
761     * (i.e., following one referral resulted in another referral which resulted
762     * in another referral and so on). This is for client-side use only and
763     * should never be transferred over protocol.
764     * <p>
765     * This result code corresponds to the LDAP result code value of {@code 97}.
766     */
767    public static final ResultCode CLIENT_SIDE_REFERRAL_LIMIT_EXCEEDED = registerErrorResultCode(
768            97, INFO_RESULT_CLIENT_SIDE_REFERRAL_LIMIT_EXCEEDED.get(), Enum.CLIENT_SIDE_REFERRAL_LIMIT_EXCEEDED);
769
770    /**
771     * The result code that indicates that a cancel request was successful, or
772     * that the specified operation was canceled.
773     * <p>
774     * This result code corresponds to the LDAP result code value of {@code 118}.
775     */
776    public static final ResultCode CANCELLED = registerErrorResultCode(118, INFO_RESULT_CANCELED
777            .get(), Enum.CANCELLED);
778
779    /**
780     * The result code that indicates that a cancel request was unsuccessful
781     * because the targeted operation did not exist or had already completed.
782     * <p>
783     * This result code corresponds to the LDAP result code value of {@code 119}.
784     */
785    public static final ResultCode NO_SUCH_OPERATION = registerErrorResultCode(119,
786            INFO_RESULT_NO_SUCH_OPERATION.get(), Enum.NO_SUCH_OPERATION);
787
788    /**
789     * The result code that indicates that a cancel request was unsuccessful
790     * because processing on the targeted operation had already reached a point
791     * at which it could not be canceled.
792     * <p>
793     * This result code corresponds to the LDAP result code value of {@code 120}.
794     */
795    public static final ResultCode TOO_LATE = registerErrorResultCode(120, INFO_RESULT_TOO_LATE
796            .get(), Enum.TOO_LATE);
797
798    /**
799     * The result code that indicates that a cancel request was unsuccessful
800     * because the targeted operation was one that could not be canceled.
801     * <p>
802     * This result code corresponds to the LDAP result code value of {@code 121}.
803     */
804    public static final ResultCode CANNOT_CANCEL = registerErrorResultCode(121,
805            INFO_RESULT_CANNOT_CANCEL.get(), Enum.CANNOT_CANCEL);
806
807    /**
808     * The result code that indicates that the filter contained in an assertion
809     * control failed to match the target entry.
810     * <p>
811     * This result code corresponds to the LDAP result code value of {@code 122}.
812     */
813    public static final ResultCode ASSERTION_FAILED = registerErrorResultCode(122,
814            INFO_RESULT_ASSERTION_FAILED.get(), Enum.ASSERTION_FAILED);
815
816    /**
817     * The result code that should be used if the server will not allow the
818     * client to use the requested authorization.
819     * <p>
820     * This result code corresponds to the LDAP result code value of {@code 123}.
821     */
822    public static final ResultCode AUTHORIZATION_DENIED = registerErrorResultCode(123,
823            INFO_RESULT_AUTHORIZATION_DENIED.get(), Enum.AUTHORIZATION_DENIED);
824
825    /**
826     * The result code that should be used if the server did not actually
827     * complete processing on the associated operation because the request
828     * included the LDAP No-Op control.
829     * <p>
830     * This result code corresponds to the LDAP result code value of
831     * {@code 16654}.
832     */
833    public static final ResultCode NO_OPERATION = registerSuccessResultCode(16654,
834            INFO_RESULT_NO_OPERATION.get(), Enum.NO_OPERATION);
835
836    /**
837     * Returns the result code having the specified integer value as defined in
838     * RFC 4511 section 4.1.9. If there is no result code associated with the
839     * specified integer value then a temporary result code is automatically
840     * created in order to handle cases where unexpected result codes are
841     * returned from the server.
842     *
843     * @param intValue
844     *            The integer value of the result code.
845     * @return The result code.
846     */
847    public static ResultCode valueOf(final int intValue) {
848        ResultCode result = ELEMENTS.get(intValue);
849        if (result == null) {
850            result = new ResultCode(
851                intValue, LocalizableMessage.raw("unknown(" + intValue + ")"), true, Enum.UNKNOWN);
852        }
853        return result;
854    }
855
856    private static final List<ResultCode> IMMUTABLE_ELEMENTS = Collections.unmodifiableList(new ArrayList<ResultCode>(
857            ELEMENTS.values()));
858
859    /**
860     * Returns an unmodifiable list containing the set of available result codes
861     * indexed on their integer value as defined in RFC 4511 section 4.1.9.
862     *
863     * @return An unmodifiable list containing the set of available result
864     *         codes.
865     */
866    public static List<ResultCode> values() {
867        return IMMUTABLE_ELEMENTS;
868    }
869
870    /**
871     * Creates and registers a new error result code with the application.
872     *
873     * @param intValue
874     *            The integer value of the error result code as defined in RFC
875     *            4511 section 4.1.9.
876     * @param name
877     *            The name of the error result code.
878     * @param resultCodeEnum
879     *            The enum equivalent for this result code
880     * @return The new error result code.
881     */
882    private static ResultCode registerErrorResultCode(final int intValue,
883            final LocalizableMessage name, final Enum resultCodeEnum) {
884        final ResultCode t = new ResultCode(intValue, name, true, resultCodeEnum);
885        ELEMENTS.put(intValue, t);
886        return t;
887    }
888
889    /**
890     * Creates and registers a new success result code with the application.
891     *
892     * @param intValue
893     *            The integer value of the success result code as defined in RFC
894     *            4511 section 4.1.9.
895     * @param name
896     *            The name of the success result code.
897     * @param resultCodeEnum
898     *            The enum equivalent for this result code
899     * @return The new success result code.
900     */
901    private static ResultCode registerSuccessResultCode(final int intValue,
902            final LocalizableMessage name, final Enum resultCodeEnum) {
903        final ResultCode t = new ResultCode(intValue, name, false, resultCodeEnum);
904        ELEMENTS.put(intValue, t);
905        return t;
906    }
907
908    private final int intValue;
909
910    private final LocalizableMessage name;
911
912    private final boolean exceptional;
913
914    private final Enum resultCodeEnum;
915
916    /** Prevent direct instantiation. */
917    private ResultCode(final int intValue, final LocalizableMessage name, final boolean exceptional,
918            final Enum resultCodeEnum) {
919        this.intValue = intValue;
920        this.name = name;
921        this.exceptional = exceptional;
922        this.resultCodeEnum = resultCodeEnum;
923    }
924
925    @Override
926    public boolean equals(final Object obj) {
927        if (this == obj) {
928            return true;
929        } else if (obj instanceof ResultCode) {
930            return this.intValue == ((ResultCode) obj).intValue;
931        } else {
932            return false;
933        }
934    }
935
936    /**
937     * Returns the short human-readable name of this result code.
938     *
939     * @return The short human-readable name of this result code.
940     */
941    public LocalizableMessage getName() {
942        return name;
943    }
944
945    @Override
946    public int hashCode() {
947        return intValue;
948    }
949
950    /**
951     * Returns the integer value of this result code.
952     *
953     * @return The integer value of this result code.
954     */
955    public int intValue() {
956        return intValue;
957    }
958
959    /**
960     * Returns the enum equivalent for this result code.
961     *
962     * @return The enum equivalent for this result code when a known mapping exists,
963     *         or {@link Enum#UNKNOWN} if this is an unknown result code.
964     */
965    public Enum asEnum() {
966        return this.resultCodeEnum;
967    }
968
969    /**
970     * Indicates whether this result code represents an error result.
971     * <p>
972     * The following result codes are NOT interpreted as error results:
973     * <ul>
974     * <li>{@link #SUCCESS}
975     * <li>{@link #COMPARE_FALSE}
976     * <li>{@link #COMPARE_TRUE}
977     * <li>{@link #SASL_BIND_IN_PROGRESS}
978     * <li>{@link #NO_OPERATION}
979     * </ul>
980     * In order to make it easier for application to detect referrals, the
981     * {@link #REFERRAL} result code is interpreted as an error result (the LDAP
982     * RFCs treat referrals as a success response).
983     *
984     * @return {@code true} if this result code represents an error result,
985     *         otherwise {@code false}.
986     */
987    public boolean isExceptional() {
988        return exceptional;
989    }
990
991    /**
992     * Returns the string representation of this result code.
993     *
994     * @return The string representation of this result code.
995     */
996    @Override
997    public String toString() {
998        return name.toString();
999    }
1000}