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