From f2160f4bd1c8ac67e5a86a6710d431e8932877f9 Mon Sep 17 00:00:00 2001
From: matthew_swift <matthew_swift@localhost>
Date: Fri, 28 May 2010 11:47:51 +0000
Subject: [PATCH] Synchronize SDK on java.net with internal repository.

---
 sdk/src/org/opends/sdk/asn1/ASN1.java                                                                    |   94 
 sdk/src/org/opends/sdk/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java                         |   40 
 sdk/src/org/opends/sdk/responses/IntermediateResponse.java                                               |   76 
 sdk/src/com/sun/opends/sdk/ldap/LDAPConnection.java                                                      | 1898 
 sdk/src/com/sun/opends/sdk/tools/MultiColumnPrinter.java                                                 |  300 
 sdk/src/com/sun/opends/sdk/util/Function.java                                                            |   14 
 sdk/examples/org/opends/sdk/examples/DummyServer.java                                                    |  260 
 sdk/src/com/sun/opends/sdk/controls/package-info.java                                                    |    9 
 sdk/src/com/sun/opends/sdk/tools/ArgumentParserConnectionFactory.java                                    |  750 
 sdk/src/com/sun/opends/sdk/util/Predicate.java                                                           |   18 
 sdk/src/com/sun/opends/sdk/tools/PromptingTrustManager.java                                              |  248 
 sdk/src/org/opends/sdk/AbstractConnection.java                                                           |  181 
 sdk/src/com/sun/opends/sdk/ldap/LDAPConstants.java                                                       |   75 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OtherMailboxSyntaxTest.java                        |   12 
 sdk/src/org/opends/sdk/LDAPConnectionFactory.java                                                        |  152 
 sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPFutureResultImpl.java                                        |  119 
 sdk/src/org/opends/sdk/controls/PasswordExpiringResponseControl.java                                     |  229 
 sdk/src/org/opends/sdk/requests/BindClientImpl.java                                                      |  151 
 sdk/src/org/opends/sdk/controls/PreReadRequestControl.java                                               |  354 
 sdk/src/org/opends/sdk/schema/NameAndOptionalUIDSyntaxImpl.java                                          |   37 
 sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPListenerOptions.java                                          |  116 
 sdk/src/org/opends/sdk/controls/AuthorizationIdentityResponseControl.java                                |  226 
 sdk/src/org/opends/sdk/schema/SchemaConstants.java                                                       |  596 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstringMatchingRuleTest.java                     |  274 
 sdk/src/org/opends/sdk/LocalizedIllegalArgumentException.java                                            |   46 
 sdk/src/org/opends/sdk/schema/DirectoryStringSyntaxImpl.java                                             |   28 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferWriterTestCase.java                    |   86 
 sdk/src/org/opends/sdk/asn1/ASN1OutputStreamWriter.java                                                  |  154 
 sdk/src/org/opends/sdk/schema/DistinguishedNameSyntaxImpl.java                                           |   17 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferReaderTestCase.java                    |   62 
 sdk/src/org/opends/sdk/responses/GenericExtendedResult.java                                              |  122 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/UtilTestCase.java                                |   14 
 sdk/src/org/opends/sdk/schema/Schema.java                                                                | 1117 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryReaderTestCase.java                         |   88 
 sdk/src/com/sun/opends/sdk/ldap/LDAPConnectionFactoryImpl.java                                           |  403 
 sdk/src/org/opends/sdk/ldif/ChangeRecord.java                                                            |   13 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DeleteRequestTestCase.java                       |   70 
 sdk/src/org/opends/sdk/schema/RegexSyntaxImpl.java                                                       |   22 
 sdk/src/org/opends/sdk/ldif/EntryReader.java                                                             |   25 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringSyntaxTest.java                           |   14 
 sdk/src/org/opends/sdk/requests/CancelExtendedRequestImpl.java                                           |  230 
 sdk/src/org/opends/sdk/schema/MatchingRuleSyntaxImpl.java                                                |   43 
 sdk/src/org/opends/sdk/schema/TelexNumberSyntaxImpl.java                                                 |   55 
 sdk/src/org/opends/sdk/requests/GenericBindRequestImpl.java                                              |   90 
 sdk/src/org/opends/sdk/requests/Requests.java                                                            |  600 
 sdk/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControl.java                                  |  191 
 sdk/src/org/opends/sdk/requests/AbstractSASLBindRequest.java                                             |   27 
 sdk/src/org/opends/sdk/schema/AbstractMatchingRuleImpl.java                                              |   49 
 sdk/src/com/sun/opends/sdk/tools/CLIException.java                                                       |   33 
 sdk/src/com/sun/opends/sdk/tools/ConsoleApplication.java                                                 |  267 
 sdk/src/com/sun/opends/sdk/tools/SearchRate.java                                                         |  583 
 sdk/src/org/opends/sdk/Attribute.java                                                                    |  301 
 sdk/src/org/opends/sdk/responses/ExtendedResult.java                                                     |  118 
 sdk/src/com/sun/opends/sdk/ldap/package-info.java                                                        |    9 
 sdk/src/org/opends/sdk/LocalizableMessageBuilder.java                                                    |  188 
 sdk/src/org/opends/sdk/ByteSequenceReader.java                                                           |  288 
 sdk/src/org/opends/sdk/schema/OctetStringSyntaxImpl.java                                                 |   28 
 sdk/src/org/opends/sdk/Entry.java                                                                        |  532 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleTest.java         |    9 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UTCTimeSyntaxTest.java                             |   30 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleTest.java             |    7 
 sdk/src/org/opends/sdk/responses/SearchResultEntry.java                                                  |  150 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/BindRequestTestCase.java                         |   71 
 sdk/src/org/opends/sdk/schema/ObjectIdentifierEqualityMatchingRuleImpl.java                              |   42 
 sdk/src/org/opends/sdk/schema/DITStructureRuleSyntaxImpl.java                                            |   34 
 sdk/src/org/opends/sdk/ServerConnection.java                                                             |  277 
 sdk/src/com/sun/opends/sdk/ldap/LDAPWriter.java                                                          |  677 
 sdk/src/com/sun/opends/sdk/extensions/package-info.java                                                  |    7 
 sdk/src/org/opends/sdk/asn1/ASN1Reader.java                                                              |  139 
 sdk/src/org/opends/sdk/ldif/ChangeRecordWriter.java                                                      |   76 
 sdk/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleImpl.java                                 |   28 
 sdk/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControl.java                                 |  570 
 sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequestImpl.java                                   |  437 
 sdk/src/org/opends/sdk/AsynchronousConnection.java                                                       |  670 
 sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResultImpl.java                                     |   41 
 sdk/src/org/opends/sdk/responses/SearchResultEntryImpl.java                                              |  183 
 sdk/src/com/sun/opends/sdk/util/SubstringReader.java                                                     |  139 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CompareRequestTestCase.java                      |   71 
 sdk/src/org/opends/sdk/requests/ExternalSASLBindRequest.java                                             |  160 
 sdk/src/com/sun/opends/sdk/tools/ToolConstants.java                                                      |   56 
 sdk/src/org/opends/sdk/schema/EnumOrderingMatchingRule.java                                              |   21 
 sdk/src/org/opends/sdk/ErrorResultException.java                                                         |  111 
 sdk/src/org/opends/sdk/schema/MatchingRuleImpl.java                                                      |   81 
 sdk/src/org/opends/sdk/requests/BindClient.java                                                          |   99 
 sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedRequest.java                                |  248 
 sdk/src/org/opends/sdk/schema/DistinguishedNameEqualityMatchingRuleImpl.java                             |   36 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTestCase.java                         |  477 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/responses/ResponsesTestCase.java                          |   16 
 sdk/src/org/opends/sdk/LDAPOptions.java                                                                  |  227 
 sdk/src/com/sun/opends/sdk/ldap/LDAPUtils.java                                                           |  234 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/LDAPTestCase.java                                |   15 
 sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequestImpl.java                                           |  194 
 sdk/src/org/opends/sdk/schema/GenerateCoreSchema.java                                                    |  290 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GuideSyntaxTest.java                               |   25 
 sdk/src/org/opends/sdk/controls/PersistentSearchChangeType.java                                          |  153 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/RDNTestCase.java                                          |  481 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ByteSequenceReaderTestCase.java                  |   18 
 sdk/src/org/opends/sdk/schema/UTCTimeSyntaxImpl.java                                                     |  264 
 sdk/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleImpl.java                                    |   16 
 sdk/src/org/opends/sdk/schema/AuthPasswordSyntaxImpl.java                                                |   68 
 sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResponseImpl.java                                   |   66 
 sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationContainer.java                         |   29 
 sdk/src/org/opends/sdk/schema/IA5StringSyntaxImpl.java                                                   |   32 
 sdk/src/org/opends/sdk/schema/UUIDOrderingMatchingRuleImpl.java                                          |   29 
 sdk/src/com/sun/opends/sdk/util/Collections2.java                                                        |   91 
 sdk/src/org/opends/sdk/controls/ProxiedAuthV2RequestControl.java                                         |  283 
 sdk/src/org/opends/sdk/schema/PresentationAddressSyntaxImpl.java                                         |   24 
 sdk/src/org/opends/sdk/controls/PasswordExpiredResponseControl.java                                      |  194 
 sdk/src/org/opends/sdk/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java                 |   41 
 sdk/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java                                |   24 
 sdk/ext/checkstyle/src-header.txt                                                                        |    0 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/EnumSyntaxTestCase.java                            |  156 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SyntaxTestCase.java                                |   46 
 sdk/src/org/opends/sdk/schema/Syntax.java                                                                |  198 
 sdk/src/org/opends/sdk/requests/GenericBindRequest.java                                                  |  187 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/GlobalTransportFactoryTestCase.java              |   68 
 sdk/src/org/opends/sdk/requests/PlainSASLBindRequestImpl.java                                            |  254 
 sdk/src/org/opends/sdk/requests/Request.java                                                             |   91 
 sdk/src/com/sun/opends/sdk/ldap/ASN1BufferReader.java                                                    |  278 
 sdk/src/org/opends/sdk/AbstractMapEntry.java                                                             |  204 
 sdk/src/org/opends/sdk/controls/PersistentSearchRequestControl.java                                      |  414 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControlTestCase.java  |   74 
 sdk/src/org/opends/sdk/responses/Result.java                                                             |  176 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTestCase.java                              |   21 
 sdk/src/org/opends/sdk/requests/DeleteRequestImpl.java                                                   |   19 
 sdk/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java                                 |   20 
 sdk/src/org/opends/sdk/schema/SupportedAlgorithmSyntaxImpl.java                                          |   29 
 sdk/src/org/opends/sdk/schema/BitStringSyntaxImpl.java                                                   |   46 
 sdk/resource/bin/_script-util.sh                                                                         |   55 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UUIDSyntaxTest.java                                |   25 
 sdk/src/org/opends/sdk/controls/ControlDecoder.java                                                      |   39 
 sdk/src/org/opends/sdk/ConnectionPool.java                                                               |  737 
 sdk/src/org/opends/sdk/LocalizableMessage.java                                                           |  270 
 sdk/src/com/sun/opends/sdk/util/StaticUtils.java                                                         | 1164 
 sdk/src/org/opends/sdk/KeyManagers.java                                                                  |  402 
 sdk/src/org/opends/sdk/SortKey.java                                                                      |  704 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPUrlTestCase.java                                      |  232 
 sdk/src/org/opends/sdk/schema/NumericStringSyntaxImpl.java                                               |   41 
 sdk/src/org/opends/sdk/requests/SearchRequestImpl.java                                                   |  116 
 sdk/src/org/opends/sdk/requests/UnbindRequestImpl.java                                                   |    7 
 sdk/src/com/sun/opends/sdk/tools/package-info.java                                                       |    3 
 sdk/src/org/opends/sdk/schema/NumericStringEqualityMatchingRuleImpl.java                                 |   14 
 sdk/src/org/opends/sdk/responses/CompareResultImpl.java                                                  |    9 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExtendedRequestTestCase.java                     |   20 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SchemaUtilsTest.java                               |   54 
 sdk/src/com/sun/opends/sdk/util/Validator.java                                                           |   96 
 sdk/src/org/opends/sdk/CancelledResultException.java                                                     |   16 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleTest.java           |  150 
 sdk/src/com/sun/opends/sdk/ldap/UnexpectedRequestException.java                                          |    5 
 sdk/src/com/sun/opends/sdk/tools/IntegerArgument.java                                                    |  793 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1InputStreamReaderTestCase.java                   |   18 
 sdk/src/com/sun/opends/sdk/tools/DataSource.java                                                         |  487 
 sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequest.java                                            |  151 
 sdk/src/org/opends/sdk/schema/DITContentRule.java                                                        |  224 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DigestMD5SASLBindRequestTestCase.java            |   71 
 sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPOptions.java                                                  |  116 
 sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequest.java                                            |  256 
 sdk/src/org/opends/sdk/schema/OIDSyntaxImpl.java                                                         |   25 
 sdk/src/org/opends/sdk/controls/package-info.java                                                        |    3 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringTestCase.java                                   |  167 
 sdk/src/org/opends/sdk/schema/GuideSyntaxImpl.java                                                       |  124 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/tools/ToolsTestCase.java                              |   15 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleSyntaxTest.java                        |   22 
 sdk/src/org/opends/sdk/asn1/ASN1InputStreamReader.java                                                   |  187 
 sdk/src/org/opends/sdk/ModificationType.java                                                             |  112 
 sdk/src/org/opends/sdk/DereferenceAliasesPolicy.java                                                     |  105 
 sdk/src/org/opends/sdk/schema/CertificateListSyntaxImpl.java                                             |   28 
 sdk/src/org/opends/sdk/schema/TelephoneNumberSubstringMatchingRuleImpl.java                              |   13 
 sdk/resource/bin/_client-script.bat                                                                      |   10 
 sdk/src/org/opends/sdk/schema/NumericStringOrderingMatchingRuleImpl.java                                 |   12 
 sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperation.java                                  |   26 
 sdk/src/org/opends/sdk/SSLContextBuilder.java                                                            |  255 
 sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedRequest.java                            | 1139 
 sdk/src/org/opends/sdk/DN.java                                                                           |  321 
 sdk/src/org/opends/sdk/requests/CompareRequestImpl.java                                                  |   37 
 sdk/src/com/sun/opends/sdk/util/SizeLimitInputStream.java                                                |  227 
 sdk/src/org/opends/sdk/schema/AbstractSyntaxImpl.java                                                    |    4 
 sdk/src/com/sun/opends/sdk/tools/LDAPSearch.java                                                         |  918 
 sdk/src/org/opends/sdk/schema/AbstractOrderingMatchingRuleImpl.java                                      |   25 
 sdk/src/org/opends/sdk/schema/EqualLengthApproximateMatchingRuleImpl.java                                |   14 
 sdk/src/org/opends/sdk/schema/GeneralizedTimeOrderingMatchingRuleImpl.java                               |    8 
 sdk/src/org/opends/sdk/AssertionFailureException.java                                                    |   19 
 sdk/src/org/opends/sdk/controls/PreReadResponseControl.java                                              |  260 
 sdk/src/org/opends/sdk/schema/OctetStringOrderingMatchingRuleImpl.java                                   |   10 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/DITContentRuleSyntaxTest.java                      |   58 
 sdk/src/org/opends/sdk/requests/SearchRequest.java                                                       |  408 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/ApproximateMatchingRuleTest.java                   |   46 
 sdk/src/org/opends/sdk/requests/SASLBindClientImpl.java                                                  |  275 
 sdk/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleImpl.java                                    |   15 
 sdk/src/com/sun/opends/sdk/messages/messages.properties                                                  |  142 
 sdk/src/org/opends/sdk/SearchResultHandler.java                                                          |   37 
 sdk/src/org/opends/sdk/schema/NameForm.java                                                              |  166 
 sdk/src/org/opends/sdk/schema/GeneralizedTimeEqualityMatchingRuleImpl.java                               |    8 
 sdk/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleImpl.java                                    |   12 
 sdk/src/com/sun/opends/sdk/ldap/LDAPServerFilter.java                                                    |  953 
 sdk/src/org/opends/sdk/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java                |   44 
 sdk/src/org/opends/sdk/requests/AddRequestImpl.java                                                      |  193 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleTest.java          |   12 
 sdk/src/org/opends/sdk/schema/EnhancedGuideSyntaxImpl.java                                               |   50 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/SuiteRunner.java                                          |    8 
 sdk/src/org/opends/sdk/controls/ServerSideSortResponseControl.java                                       |  376 
 sdk/src/org/opends/sdk/requests/ExtendedRequestDecoder.java                                              |   67 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleTest.java             |    6 
 sdk/src/org/opends/sdk/AbstractAsynchronousConnection.java                                               |  255 
 sdk/src/org/opends/sdk/AbstractAttribute.java                                                            |  132 
 sdk/src/org/opends/sdk/controls/PasswordPolicyRequestControl.java                                        |  195 
 sdk/src/org/opends/sdk/responses/WhoAmIExtendedResult.java                                               |  220 
 sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResult.java                                       |  235 
 sdk/src/org/opends/sdk/schema/IntegerSyntaxImpl.java                                                     |   48 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/ASCIICharPropTestCase.java                       |  183 
 sdk/src/com/sun/opends/sdk/ldap/InternalConnection.java                                                  |  335 
 sdk/src/org/opends/sdk/AuthorizationException.java                                                       |   62 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleTest.java            |    6 
 sdk/src/org/opends/sdk/controls/PasswordPolicyErrorType.java                                             |  190 
 sdk/src/com/sun/opends/sdk/tools/ArgumentException.java                                                  |   29 
 sdk/src/org/opends/sdk/controls/SubentriesRequestControl.java                                            |  195 
 sdk/src/org/opends/sdk/schema/AttributeTypeSyntaxImpl.java                                               |   40 
 sdk/src/org/opends/sdk/ldif/AbstractLDIFStream.java                                                      |   12 
 sdk/src/org/opends/sdk/DecodeException.java                                                              |   90 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GenericBindRequestTestCase.java                  |   77 
 sdk/src/org/opends/sdk/responses/ResultImpl.java                                                         |    8 
 sdk/src/org/opends/sdk/requests/DeleteRequest.java                                                       |  122 
 sdk/src/org/opends/sdk/schema/MatchingRuleUse.java                                                       |  115 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/TypesTestCase.java                                        |  156 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1WriterTestCase.java                              |  742 
 sdk/src/com/sun/opends/sdk/tools/PerformanceRunner.java                                                  | 1228 
 sdk/src/org/opends/sdk/asn1/ASN1Writer.java                                                              |   92 
 sdk/src/org/opends/sdk/LocalizableException.java                                                         |   10 
 sdk/src/org/opends/sdk/responses/AbstractResultImpl.java                                                 |   43 
 sdk/src/org/opends/sdk/ErrorResultIOException.java                                                       |   11 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AnonymousSASLBindRequestTestCase.java            |   68 
 sdk/src/org/opends/sdk/ldif/LDIFEntryReader.java                                                         |  148 
 sdk/src/org/opends/sdk/controls/VirtualListViewRequestControl.java                                       |  525 
 sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedResult.java                                 |  184 
 sdk/src/org/opends/sdk/requests/ModifyRequestImpl.java                                                   |   91 
 sdk/src/com/sun/opends/sdk/tools/LDAPCompare.java                                                        |  564 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GeneralizedTimeSyntaxTest.java                     |   31 
 sdk/src/org/opends/sdk/Matcher.java                                                                      |  189 
 sdk/src/org/opends/sdk/controls/Control.java                                                             |  118 
 sdk/src/org/opends/sdk/asn1/ASN1Constants.java                                                           |   74 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTestCase.java                         |  195 
 sdk/src/org/opends/sdk/schema/NameFormSyntaxImpl.java                                                    |   55 
 sdk/src/com/sun/opends/sdk/util/RecursiveFutureResult.java                                               |   69 
 sdk/src/org/opends/sdk/ConnectionSecurityLayer.java                                                      |   83 
 sdk/src/com/sun/opends/sdk/controls/VirtualAttributesOnlyRequestControl.java                             |  192 
 sdk/src/org/opends/sdk/controls/SubtreeDeleteRequestControl.java                                         |  192 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/IA5StringSyntaxTest.java                           |   11 
 sdk/src/org/opends/sdk/LDAPListener.java                                                                 |  281 
 sdk/src/org/opends/sdk/requests/PlainSASLBindRequest.java                                                |  222 
 sdk/src/org/opends/sdk/schema/EnumSyntaxImpl.java                                                        |   42 
 sdk/src/org/opends/sdk/schema/CaseIgnoreListEqualityMatchingRuleImpl.java                                |   12 
 sdk/src/com/sun/opends/sdk/ldap/LDAPSearchFutureResultImpl.java                                          |   67 
 sdk/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleImpl.java                                     |   12 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeTest.java                             |  626 
 sdk/src/org/opends/sdk/schema/ProtocolInformationEqualityMatchingRuleImpl.java                           |   16 
 sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequest.java                                              |  197 
 sdk/src/org/opends/sdk/Connection.java                                                                   |  928 
 sdk/src/org/opends/sdk/schema/ConflictingSchemaElementException.java                                     |   18 
 sdk/src/org/opends/sdk/asn1/package-info.java                                                            |    3 
 sdk/src/org/opends/sdk/schema/CertificateSyntaxImpl.java                                                 |   28 
 sdk/src/org/opends/sdk/responses/Responses.java                                                          |  129 
 sdk/src/org/opends/sdk/requests/AbandonRequestImpl.java                                                  |   13 
 sdk/src/com/sun/opends/sdk/util/ASCIICharProp.java                                                       |  149 
 sdk/src/org/opends/sdk/schema/GeneralizedTimeSyntaxImpl.java                                             |  357 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/UnbindRequestTestCase.java                       |   66 
 sdk/src/org/opends/sdk/schema/ObjectClassSyntaxImpl.java                                                 |   33 
 sdk/src/org/opends/sdk/FilterVisitor.java                                                                |   27 
 sdk/src/org/opends/sdk/controls/PostReadResponseControl.java                                             |  259 
 sdk/src/org/opends/sdk/schema/SchemaException.java                                                       |   19 
 sdk/src/org/opends/sdk/requests/SimpleBindRequestImpl.java                                               |   67 
 sdk/src/com/sun/opends/sdk/ldap/SASLFilter.java                                                          |  317 
 sdk/src/com/sun/opends/sdk/tools/LDAPModify.java                                                         |  833 
 sdk/src/org/opends/sdk/schema/UserPasswordExactEqualityMatchingRuleImpl.java                             |   17 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/OpenDSTestCase.java                                       |  113 
 sdk/src/com/sun/opends/sdk/ldap/TimeoutChecker.java                                                      |  157 
 sdk/src/org/opends/sdk/asn1/AbstractASN1Reader.java                                                      |   11 
 sdk/src/org/opends/sdk/requests/ExtendedRequest.java                                                     |  125 
 sdk/src/org/opends/sdk/AttributeDescription.java                                                         |  347 
 sdk/src/com/sun/opends/sdk/tools/Argument.java                                                           | 1048 
 sdk/src/org/opends/sdk/asn1/ASN1ByteSequenceReader.java                                                  |  108 
 sdk/src/org/opends/sdk/schema/OctetStringSubstringMatchingRuleImpl.java                                  |   10 
 sdk/src/com/sun/opends/sdk/tools/AuthenticatedConnectionFactory.java                                     |  688 
 sdk/src/org/opends/sdk/requests/GenericExtendedRequest.java                                              |  133 
 sdk/src/org/opends/sdk/ServerConnectionFactory.java                                                      |   59 
 sdk/src/org/opends/sdk/schema/UserPasswordSyntaxImpl.java                                                |   59 
 sdk/src/org/opends/sdk/SynchronousConnection.java                                                        |  397 
 sdk/src/com/sun/opends/sdk/ldap/LDAPMessageHandler.java                                                  |  140 
 sdk/src/org/opends/sdk/responses/AbstractIntermediateResponse.java                                       |   27 
 sdk/src/com/sun/opends/sdk/ldap/SASLDecoderTransformer.java                                              |  109 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/SynchronousConnectionTestCase.java                        |  164 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/LDAPSyntaxTest.java                                |   49 
 sdk/src/com/sun/opends/sdk/ldap/LDAPBindFutureResultImpl.java                                            |   68 
 sdk/src/org/opends/sdk/requests/StartTLSExtendedRequest.java                                             |  141 
 sdk/src/org/opends/sdk/requests/AbstractBindRequest.java                                                 |   17 
 sdk/src/org/opends/sdk/LDAPClientContext.java                                                            |  118 
 sdk/src/org/opends/sdk/requests/GenericExtendedRequestImpl.java                                          |  175 
 sdk/src/com/sun/opends/sdk/tools/StringArgument.java                                                     |  113 
 sdk/src/org/opends/sdk/ldif/ChangeRecordReader.java                                                      |   26 
 sdk/src/org/opends/sdk/requests/ExternalSASLBindRequestImpl.java                                         |  199 
 sdk/src/com/sun/opends/sdk/ldap/SASLEncoderTransformer.java                                              |  109 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPConnectionFactoryTestCase.java                        |   56 
 sdk/src/org/opends/sdk/schema/TelephoneNumberEqualityMatchingRuleImpl.java                               |   13 
 sdk/src/org/opends/sdk/schema/UUIDEqualityMatchingRuleImpl.java                                          |   32 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleTest.java            |  115 
 sdk/src/com/sun/opends/sdk/ldap/LDAPCompareFutureResultImpl.java                                         |   43 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/ConnectionFactoryTestCase.java                            |  171 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstitutionSyntaxTestCase.java                    |  123 
 sdk/src/com/sun/opends/sdk/ldap/LDAPExtendedFutureResultImpl.java                                        |   53 
 sdk/src/org/opends/sdk/requests/UnbindRequest.java                                                       |   75 
 sdk/src/com/sun/opends/sdk/util/Functions.java                                                           |  192 
 sdk/src/org/opends/sdk/schema/SubstringAssertionSyntaxImpl.java                                          |   38 
 sdk/src/org/opends/sdk/schema/PostalAddressSyntaxImpl.java                                               |   31 
 sdk/src/org/opends/sdk/Assertion.java                                                                    |   14 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExternalSASLBindRequestTestCase.java             |   67 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyRequestTestCase.java                       |   75 
 sdk/src/org/opends/sdk/schema/PresentationAddressEqualityMatchingRuleImpl.java                           |   16 
 sdk/src/org/opends/sdk/EntryNotFoundException.java                                                       |   26 
 sdk/src/org/opends/sdk/schema/AbstractSubstringMatchingRuleImpl.java                                     |  329 
 sdk/src/org/opends/sdk/RootDSE.java                                                                      |  386 
 sdk/src/org/opends/sdk/controls/VirtualListViewResponseControl.java                                      |  338 
 sdk/src/org/opends/sdk/TreeMapEntry.java                                                                 |  157 
 sdk/src/org/opends/sdk/requests/AddRequest.java                                                          |  166 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestsTestCase.java                            |   16 
 sdk/src/org/opends/sdk/schema/SchemaElement.java                                                         |   57 
 sdk/src/org/opends/sdk/schema/SyntaxImpl.java                                                            |   79 
 sdk/ext/checkstyle/check-tests.xml                                                                       |   16 
 sdk/src/org/opends/sdk/controls/GenericControl.java                                                      |  225 
 sdk/src/org/opends/sdk/requests/AbstractUnmodifiableRequestImpl.java                                     |   66 
 sdk/src/org/opends/sdk/AuthenticationException.java                                                      |   60 
 sdk/src/org/opends/sdk/requests/AbstractRequestImpl.java                                                 |   76 
 sdk/src/org/opends/sdk/IntermediateResponseHandler.java                                                  |   69 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleTest.java                              |   83 
 sdk/src/org/opends/sdk/AbstractEntry.java                                                                |  206 
 sdk/src/org/opends/sdk/ldif/AbstractLDIFReader.java                                                      |  146 
 sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequest.java                                               |  133 
 sdk/src/org/opends/sdk/FailoverLoadBalancingAlgorithm.java                                               |  135 
 sdk/src/org/opends/sdk/schema/CaseIgnoreListSubstringMatchingRuleImpl.java                               |   13 
 sdk/src/org/opends/sdk/ldif/EntryWriter.java                                                             |   32 
 sdk/src/org/opends/sdk/schema/AttributeUsage.java                                                        |   32 
 sdk/src/org/opends/sdk/SearchScope.java                                                                  |   96 
 sdk/src/org/opends/sdk/requests/package-info.java                                                        |    3 
 sdk/src/org/opends/sdk/schema/TelephoneNumberSyntaxImpl.java                                             |   73 
 sdk/src/org/opends/sdk/requests/CompareRequest.java                                                      |  171 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GSSAPISASLBindRequestTestCase.java               |   70 
 sdk/examples/org/opends/sdk/examples/package-info.java                                                   |    9 
 sdk/src/org/opends/sdk/controls/ProxiedAuthV1RequestControl.java                                         |  294 
 sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java                                                   |  590 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyDNRequestTestCase.java                     |   69 
 sdk/src/org/opends/sdk/Types.java                                                                        |  337 
 sdk/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleImpl.java                                   |   15 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeSyntaxTest.java                       |   22 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java        |  155 
 sdk/src/org/opends/sdk/responses/GenericIntermediateResponseImpl.java                                    |   61 
 sdk/src/org/opends/sdk/responses/SearchResultReference.java                                              |   92 
 sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedResult.java                             |  171 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleTest.java            |    3 
 sdk/src/com/sun/opends/sdk/util/Iterators.java                                                           |  258 
 sdk/src/org/opends/sdk/requests/ModifyRequest.java                                                       |  260 
 sdk/src/org/opends/sdk/ByteSequence.java                                                                 |  237 
 sdk/src/org/opends/sdk/responses/BindResultImpl.java                                                     |   15 
 sdk/src/org/opends/sdk/schema/UUIDSyntaxImpl.java                                                        |   27 
 sdk/src/org/opends/sdk/LinkedAttribute.java                                                              |  393 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AddRequestTestCase.java                          |   71 
 sdk/src/com/sun/opends/sdk/util/Platform.java                                                            | 1355 
 sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequest.java                                       |  274 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OrderingMatchingRuleTest.java                      |   83 
 sdk/src/org/opends/sdk/ByteStringBuilder.java                                                            |  400 
 sdk/src/org/opends/sdk/responses/package-info.java                                                       |    3 
 sdk/src/com/sun/opends/sdk/ldap/LDAPClientFilter.java                                                    |  587 
 sdk/src/com/sun/opends/sdk/util/ByteSequenceOutputStream.java                                            |  105 
 sdk/src/org/opends/sdk/Modification.java                                                                 |   53 
 sdk/src/org/opends/sdk/schema/AuthPasswordExactEqualityMatchingRuleImpl.java                             |   19 
 sdk/src/org/opends/sdk/schema/IntegerOrderingMatchingRuleImpl.java                                       |   14 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/HeartBeatConnectionFactoryTestCase.java                   |   71 
 sdk/src/org/opends/sdk/Filter.java                                                                       | 1257 
 sdk/src/org/opends/sdk/EntryFactory.java                                                                 |   53 
 sdk/src/org/opends/sdk/controls/SimplePagedResultsControl.java                                           |  344 
 sdk/src/org/opends/sdk/schema/NumericStringSubstringMatchingRuleImpl.java                                |   12 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/Base64TestCase.java                              |  238 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ReaderTestCase.java                              |  922 
 sdk/src/com/sun/opends/sdk/tools/BooleanArgument.java                                                    |   92 
 sdk/build.xml                                                                                            |   42 
 sdk/src/org/opends/sdk/controls/MatchedValuesRequestControl.java                                         |  463 
 sdk/src/org/opends/sdk/ldif/ChangeRecordVisitorWriter.java                                               |   48 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/InternalConnectionFactoryTestCase.java                    |   57 
 sdk/src/org/opends/sdk/ConnectionEventListener.java                                                      |   92 
 sdk/src/org/opends/sdk/schema/CountryStringSyntaxImpl.java                                               |   39 
 sdk/src/org/opends/sdk/TrustManagers.java                                                                |  553 
 sdk/src/org/opends/sdk/schema/KeywordEqualityMatchingRuleImpl.java                                       |   27 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteSequenceTestCase.java                                 |  247 
 sdk/src/org/opends/sdk/LoadBalancingAlgorithm.java                                                       |   14 
 sdk/src/org/opends/sdk/controls/PostReadRequestControl.java                                              |  354 
 sdk/src/org/opends/sdk/SchemaResolver.java                                                               |   63 
 sdk/src/org/opends/sdk/schema/BinarySyntaxImpl.java                                                      |   27 
 sdk/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleImpl.java                                     |   15 
 sdk/src/org/opends/sdk/LoadBalancingConnectionFactory.java                                               |   18 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AbstractSchemaElementTestCase.java                 |  213 
 sdk/src/org/opends/sdk/schema/CoreSchemaImpl.java                                                        |  645 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/messages/MessagesTestCase.java                        |   19 
 sdk/src/com/sun/opends/sdk/tools/MultiChoiceArgument.java                                                |  305 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/RegexSyntaxTestCase.java                           |   61 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestTestCase.java              |   69 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestTestCase.java                             |  136 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/controls/ControlsTestCase.java                            |   60 
 sdk/src/org/opends/sdk/FutureResult.java                                                                 |   77 
 sdk/src/org/opends/sdk/MultipleEntriesFoundException.java                                                |   17 
 sdk/src/com/sun/opends/sdk/tools/ArgumentParser.java                                                     | 2541 
 sdk/src/com/sun/opends/sdk/controls/RealAttributesOnlyRequestControl.java                                |  192 
 sdk/src/com/sun/opends/sdk/ldap/UnsupportedMessageException.java                                         |   12 
 sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPMessageHandler.java                                          |  240 
 sdk/src/com/sun/opends/sdk/extensions/GetSymmetricKeyExtendedRequest.java                                |  334 
 sdk/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleImpl.java                                     |   32 
 sdk/src/org/opends/sdk/requests/SASLBindRequest.java                                                     |  108 
 sdk/src/org/opends/sdk/responses/CompareResult.java                                                      |   96 
 sdk/src/org/opends/sdk/schema/UniqueMemberEqualityMatchingRuleImpl.java                                  |   12 
 sdk/src/org/opends/sdk/InternalConnectionFactory.java                                                    |   88 
 sdk/src/org/opends/sdk/schema/FaxSyntaxImpl.java                                                         |   28 
 sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResultImpl.java                                   |  189 
 sdk/src/org/opends/sdk/ldif/ConnectionEntryWriter.java                                                   |   51 
 sdk/src/org/opends/sdk/requests/AbstractExtendedRequest.java                                             |   47 
 sdk/src/org/opends/sdk/responses/WhoAmIExtendedResultImpl.java                                           |  152 
 sdk/src/org/opends/sdk/schema/BooleanSyntaxImpl.java                                                     |   42 
 sdk/src/org/opends/sdk/ResultHandler.java                                                                |   24 
 sdk/src/org/opends/sdk/LinkedHashMapEntry.java                                                           |  156 
 sdk/src/org/opends/sdk/controls/EntryChangeNotificationResponseControl.java                              |  396 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControlTestCase.java |   95 
 sdk/src/org/opends/sdk/ldif/ConnectionChangeRecordWriter.java                                            |  114 
 sdk/src/org/opends/sdk/responses/GenericExtendedResultImpl.java                                          |   48 
 sdk/src/com/sun/opends/sdk/util/FutureResultTransformer.java                                             |   99 
 sdk/src/org/opends/sdk/schema/DeliveryMethodSyntaxImpl.java                                              |   41 
 sdk/src/org/opends/sdk/controls/PermissiveModifyRequestControl.java                                      |  189 
 sdk/src/com/sun/opends/sdk/ldap/GlobalTransportFactory.java                                              |  183 
 sdk/src/org/opends/sdk/responses/ExtendedResultDecoder.java                                              |   89 
 sdk/src/org/opends/sdk/ReferralException.java                                                            |   19 
 sdk/src/org/opends/sdk/schema/OctetStringEqualityMatchingRuleImpl.java                                   |   10 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleUseSyntaxTest.java                     |   30 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/PlainSASLBindRequestTestCase.java                |   69 
 sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java                                               |  412 
 sdk/src/org/opends/sdk/requests/ModifyDNRequest.java                                                     |  262 
 sdk/src/org/opends/sdk/asn1/AbstractASN1Writer.java                                                      |   19 
 sdk/src/com/sun/opends/sdk/ldap/ASN1BufferWriter.java                                                    |  261 
 sdk/src/com/sun/opends/sdk/tools/Utils.java                                                              |  970 
 sdk/src/org/opends/sdk/ldif/LDIFChangeRecordWriter.java                                                  |  145 
 sdk/src/org/opends/sdk/LDAPUrl.java                                                                      |  978 
 sdk/src/org/opends/sdk/controls/ServerSideSortRequestControl.java                                        |  393 
 sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequest.java                                               |  330 
 sdk/src/org/opends/sdk/requests/ModifyDNRequestImpl.java                                                 |   39 
 sdk/ext/checkstyle/check-src.xml                                                                         |   58 
 sdk/src/com/sun/opends/sdk/tools/LDAPPasswordModify.java                                                 |  440 
 sdk/src/org/opends/sdk/AbstractFilterVisitor.java                                                        |   94 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleTest.java               |   24 
 sdk/src/org/opends/sdk/responses/GenericIntermediateResponse.java                                        |   76 
 sdk/src/org/opends/sdk/schema/SchemaCompatOptions.java                                                   |   78 
 sdk/src/com/sun/opends/sdk/util/LocalizableMessageDescriptor.java                                        |  417 
 sdk/src/org/opends/sdk/schema/ObjectClassType.java                                                       |   13 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/TestCaseUtils.java                                        |  141 
 sdk/src/org/opends/sdk/ByteString.java                                                                   |  264 
 sdk/src/org/opends/sdk/schema/UnknownSchemaElementException.java                                         |   14 
 sdk/src/org/opends/sdk/requests/CancelExtendedRequest.java                                               |  143 
 sdk/src/org/opends/sdk/schema/ObjectClass.java                                                           |  390 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/SdkTestCase.java                                          |   15 
 sdk/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleImpl.java                                       |   17 
 sdk/src/org/opends/sdk/schema/FacsimileNumberSyntaxImpl.java                                             |   61 
 sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationType.java                              |  323 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleTest.java             |    3 
 sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java                                                         |  129 
 sdk/src/org/opends/sdk/schema/CertificatePairSyntaxImpl.java                                             |   28 
 sdk/src/com/sun/opends/sdk/util/Base64.java                                                              |  161 
 sdk/src/org/opends/sdk/LDAPListenerOptions.java                                                          |  183 
 sdk/src/org/opends/sdk/controls/PasswordPolicyResponseControl.java                                       |  418 
 sdk/src/org/opends/sdk/controls/PasswordPolicyWarningType.java                                           |  147 
 sdk/src/org/opends/sdk/ConditionResult.java                                                              |  161 
 sdk/src/org/opends/sdk/schema/LDAPSyntaxDescriptionSyntaxImpl.java                                       |   58 
 sdk/src/com/sun/opends/sdk/ldap/LDAPFutureResultImpl.java                                                |   48 
 sdk/src/com/sun/opends/sdk/tools/ArgumentGroup.java                                                      |  172 
 sdk/src/org/opends/sdk/requests/BindRequest.java                                                         |  115 
 sdk/src/com/sun/opends/sdk/ldap/UnexpectedResponseException.java                                         |    6 
 sdk/src/org/opends/sdk/schema/MatchingRuleUseSyntaxImpl.java                                             |   46 
 sdk/src/org/opends/sdk/ConnectionException.java                                                          |    6 
 sdk/src/org/opends/sdk/responses/SearchResultReferenceImpl.java                                          |   49 
 sdk/src/org/opends/sdk/schema/TeletexTerminalIdentifierSyntaxImpl.java                                   |   63 
 sdk/resource/bin/_script-util.bat                                                                        |    4 
 sdk/src/org/opends/sdk/controls/AssertionRequestControl.java                                             |  242 
 sdk/src/org/opends/sdk/schema/OtherMailboxSyntaxImpl.java                                                |   45 
 sdk/src/com/sun/opends/sdk/util/AbstractFutureResult.java                                                |  213 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/FilterTestCase.java                                       |  219 
 sdk/src/org/opends/sdk/ldif/LDIFChangeRecordReader.java                                                  |  221 
 sdk/src/org/opends/sdk/ldif/ChangeRecordVisitor.java                                                     |   21 
 sdk/src/org/opends/sdk/AbstractConnectionFactory.java                                                    |   62 
 sdk/lib/grizzly.jar                                                                                      |    0 
 sdk/src/org/opends/sdk/controls/AuthorizationIdentityRequestControl.java                                 |  199 
 sdk/src/org/opends/sdk/schema/CoreSchema.java                                                            | 3585 +-
 sdk/src/com/sun/opends/sdk/tools/FileBasedArgument.java                                                  |  246 
 sdk/src/org/opends/sdk/responses/AbstractExtendedResult.java                                             |   39 
 sdk/src/org/opends/sdk/schema/SchemaBuilder.java                                                         | 1153 
 sdk/src/com/sun/opends/sdk/tools/ApplicationKeyManager.java                                              |  138 
 sdk/src/org/opends/sdk/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java                            |  113 
 sdk/src/org/opends/sdk/ConstraintViolationException.java                                                 |   80 
 sdk/src/org/opends/sdk/schema/MatchingRule.java                                                          |  204 
 sdk/src/org/opends/sdk/responses/BindResult.java                                                         |  139 
 sdk/src/org/opends/sdk/AttributeFactory.java                                                             |   54 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AbandonRequestTestCase.java                      |   67 
 sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StringPrepProfileTestCase.java                   |  119 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/SimpleBindRequestTestCase.java                   |   68 
 sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestImpl.java                                          |  272 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/TestListener.java                                         |  465 
 sdk/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleImpl.java                                  |   20 
 sdk/src/org/opends/sdk/ldif/AbstractLDIFWriter.java                                                      |   88 
 sdk/src/org/opends/sdk/schema/AttributeType.java                                                         |  233 
 sdk/src/org/opends/sdk/schema/IntegerEqualityMatchingRuleImpl.java                                       |   17 
 sdk/src/org/opends/sdk/ConnectionFactory.java                                                            |   63 
 sdk/src/org/opends/sdk/requests/StartTLSExtendedRequestImpl.java                                         |  203 
 sdk/src/com/sun/opends/sdk/ldap/LDAPReader.java                                                          | 1817 +
 sdk/src/org/opends/sdk/DecodeOptions.java                                                                |  241 
 sdk/src/org/opends/sdk/ResultCode.java                                                                   |  567 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFTestCase.java                                    |   16 
 sdk/src/org/opends/sdk/schema/WordEqualityMatchingRuleImpl.java                                          |   27 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/AuthenticatedConnectionFactoryTestCase.java               |   62 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringBuilderTestCase.java                            |  296 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/EntryTestCase.java                                        |  119 
 sdk/src/org/opends/sdk/schema/JPEGSyntaxImpl.java                                                        |   28 
 sdk/src/com/sun/opends/sdk/util/package-info.java                                                        |    7 
 sdk/src/org/opends/sdk/AVA.java                                                                          |  954 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1OutputStreamWriterTestCase.java                  |   69 
 sdk/src/com/sun/opends/sdk/tools/ModRate.java                                                            |  502 
 sdk/src/org/opends/sdk/requests/AbandonRequest.java                                                      |   89 
 sdk/src/com/sun/opends/sdk/util/Iterables.java                                                           |  292 
 sdk/src/org/opends/sdk/schema/DITContentRuleSyntaxImpl.java                                              |   29 
 sdk/src/org/opends/sdk/TimeoutResultException.java                                                       |    7 
 sdk/src/org/opends/sdk/schema/ProtocolInformationSyntaxImpl.java                                         |   23 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/TelexSyntaxTest.java                               |   14 
 sdk/src/org/opends/sdk/schema/PrintableStringSyntaxImpl.java                                             |   50 
 sdk/src/com/sun/opends/sdk/ldap/LDAPListenerImpl.java                                                    |  139 
 sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequestImpl.java                                        |  404 
 sdk/src/org/opends/sdk/responses/Response.java                                                           |   87 
 sdk/src/org/opends/sdk/schema/package-info.java                                                          |    3 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/DNTestCase.java                                           |  997 
 sdk/src/org/opends/sdk/requests/SimpleBindRequest.java                                                   |  229 
 sdk/src/com/sun/opends/sdk/util/StringPrepProfile.java                                                   |  787 
 sdk/src/org/opends/sdk/Connections.java                                                                  |  137 
 /dev/null                                                                                                |   88 
 sdk/src/com/sun/opends/sdk/util/CompletedFutureResult.java                                               |  109 
 sdk/src/org/opends/sdk/controls/ManageDsaITRequestControl.java                                           |  194 
 sdk/src/org/opends/sdk/schema/DITStructureRule.java                                                      |   88 
 sdk/ext/checkstyle/checkstyle-all-5.1.jar                                                                |    0 
 sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequestImpl.java                                           |  573 
 sdk/src/org/opends/sdk/RDN.java                                                                          |  729 
 sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequestImpl.java                                        |  129 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleTest.java         |  118 
 sdk/src/org/opends/sdk/controls/GetEffectiveRightsRequestControl.java                                    |  432 
 sdk/src/org/opends/sdk/responses/AbstractResponseImpl.java                                               |   76 
 sdk/src/org/opends/sdk/schema/SchemaUtils.java                                                           |  341 
 sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPServer.java                                           |  590 
 553 files changed, 70,043 insertions(+), 33,388 deletions(-)

diff --git a/sdk/build.xml b/sdk/build.xml
index 1b8c4fa..af2b296 100755
--- a/sdk/build.xml
+++ b/sdk/build.xml
@@ -22,7 +22,7 @@
  ! CDDL HEADER END
  !
  !
- !      Copyright 2009 Sun Microsystems, Inc.
+ !      Copyright 2009-2010 Sun Microsystems, Inc.
  ! -->
 
 <project name="OpenDS LDAP SDK" basedir="." default="package">
@@ -36,7 +36,8 @@
 
     <!-- General server-wide properties -->
     <property name="src.dir" location="src" />
-    <property name="srcgen.dir" location="src-generated" />
+	<property name="examples.dir" location="examples" />
+	<property name="srcgen.dir" location="src-generated" />
     <property name="build.dir" location="build" />
     <property name="classes.dir" location="${build.dir}/classes" />
     <property name="build.lib.dir" location="${build.dir}/lib" />
@@ -105,13 +106,13 @@
 
     <!-- The build target that should be used before committing code. -->
     <target name="precommit"
-            depends="checkstyle,clean,checkprecommit,testwithcoverage"
+            depends="clean,checkprecommit,package,checkstyle,testwithcoverage"
             description="Perform all processing needed before committing code.">
     </target>
 
     <!-- The build target that should be used to build everything. -->
     <target name="all"
-            depends="checkstyle,clean,checkprecommit,srczip,javadoc,testwithcoverage"
+            depends="clean,checkprecommit,srczip,package,checkstyle,testwithcoverage"
             description="Build using all defined targets.">
     </target>
 
@@ -333,27 +334,22 @@
     </target>
 
     <!-- Ensure that the source code meets basic style requirements. -->
-    <target name="checkstyle">
-        <mkdir dir="${checkstyle.cache.dir}" />
-
+    <target name="checkstyle" depends="compile">
         <taskdef resource="checkstyletask.properties"
-                 classpath="${checkstyle.dir}/checkstyle-all-4.1.jar" />
+                 classpath="${checkstyle.dir}/checkstyle-all-5.1.jar" />
 
-        <checkstyle config="${checkstyle.dir}/opends-checkstyle.xml"
-                    failOnViolation="true">
-            <fileset dir="${src.dir}">
+        <checkstyle config="${checkstyle.dir}/check-src.xml"
+                    failOnViolation="true" classpath="${classes.dir}">
+        	<fileset dir="${src.dir}">
                 <include name="**/*.java" />
             </fileset>
+        	<fileset dir="${examples.dir}">
+        	    <include name="**/*.java" />
+        	</fileset>
             <formatter type="plain" />
         </checkstyle>
 
-        <checkstyle config="${checkstyle.dir}/opends-doctarget-checkstyle.xml"
-                    failOnViolation="true">
-            <fileset dir="${src.dir}/org" includes="**/*.java" />
-            <formatter type="plain" />
-        </checkstyle>
-
-        <checkstyle config="${checkstyle.dir}/opends-unittest-checkstyle.xml"
+        <checkstyle config="${checkstyle.dir}/check-tests.xml"
                     failOnViolation="true">
             <fileset dir="${unittest.testng.src.dir}" includes="**/*.java" />
             <formatter type="plain" />
@@ -909,9 +905,16 @@
         <echo message="      The unit tests will not start to run until the debugger is attached" />
         <echo message="      unless you also specify -Dtest.remote.debug.suspend=n." />
         <echo message="" />
+        <echo message="  -Dorg.opends.sdk.ldapserver=localhost@389@cn=Directory Manager@password " />
+        <echo message="      for example will allow you to use an external LDAP server of your choice" />
+        <echo message="      for executing the server-dependent unit tests. In absence of this parameter,"/>
+        <echo message="      a local LDAP server is started and used for the unit tests. Also, if the test" />
+        <echo message="      can not establish a connection to the specified server, it will use the local" />
+        <echo message="      server instead." />
+        <echo message="" />
     </target>
 
-
+ 
 
     <!-- Internal target to execute the OpenDS LDAP SDK TestNG unit tests in text mode after everything has been initialized. -->
     <target name="runtests">
@@ -1045,6 +1048,7 @@
             <jvmarg value="-Dorg.opends.test.suppressOutput=${org.opends.test.suppressOutput}" />
             <jvmarg value="-Dorg.opends.test.pauseOnFailure=${org.opends.test.pauseOnFailure}" />
             <jvmarg value="-Dtest.progress=${test.progress}" />
+            <jvmarg value="-Dorg.opends.sdk.ldapserver=${org.opends.sdk.ldapserver}" />
             <jvmarg value="-Xms${MEM}" />
             <jvmarg value="-Xmx${MEM}" />
             <jvmarg value="${jvm.debug.arg1}" />
diff --git a/sdk/examples/org/opends/sdk/examples/DummyServer.java b/sdk/examples/org/opends/sdk/examples/DummyServer.java
new file mode 100644
index 0000000..4179cec
--- /dev/null
+++ b/sdk/examples/org/opends/sdk/examples/DummyServer.java
@@ -0,0 +1,260 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.examples;
+
+
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.KeyStore;
+
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+
+import org.opends.sdk.*;
+import org.opends.sdk.requests.*;
+import org.opends.sdk.responses.*;
+
+
+
+/**
+ * A simple dummy server that just returns one entry.
+ */
+public class DummyServer implements
+    ServerConnectionFactory<LDAPClientContext, Integer>
+{
+
+  private static final class DummyServerConnection implements
+      ServerConnection<Integer>
+  {
+    private final LDAPClientContext clientContext;
+
+
+
+    private DummyServerConnection(final LDAPClientContext clientContext)
+    {
+      this.clientContext = clientContext;
+    }
+
+
+
+    public void abandon(final Integer context, final AbandonRequest request)
+        throws UnsupportedOperationException
+    {
+    }
+
+
+
+    public void add(final Integer context, final AddRequest request,
+        final ResultHandler<Result> handler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException
+    {
+    }
+
+
+
+    public void bind(final Integer context, final int version,
+        final BindRequest request,
+        final ResultHandler<? super BindResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException
+    {
+      resultHandler.handleResult(Responses.newBindResult(ResultCode.SUCCESS));
+    }
+
+
+
+    public void closed(final Integer context, final UnbindRequest request)
+    {
+      System.out.println(request);
+    }
+
+
+
+    public void closed(final Throwable error)
+    {
+      System.out.println(error);
+    }
+
+
+
+    public void compare(final Integer context, final CompareRequest request,
+        final ResultHandler<? super CompareResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException
+    {
+    }
+
+
+
+    public void delete(final Integer context, final DeleteRequest request,
+        final ResultHandler<Result> handler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException
+    {
+    }
+
+
+
+    public <R extends ExtendedResult> void extendedRequest(
+        final Integer context, final ExtendedRequest<R> request,
+        final ResultHandler<R> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException
+    {
+      if (request.getOID().equals(StartTLSExtendedRequest.OID))
+      {
+        final R result = request.getResultDecoder().adaptExtendedErrorResult(
+            ResultCode.SUCCESS, "", "");
+        resultHandler.handleResult(result);
+        clientContext.startTLS(sslContext);
+      }
+    }
+
+
+
+    public void modify(final Integer context, final ModifyRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException
+    {
+    }
+
+
+
+    public void modifyDN(final Integer context, final ModifyDNRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException
+    {
+    }
+
+
+
+    public void search(final Integer context, final SearchRequest request,
+        final ResultHandler<Result> resultHandler,
+        final SearchResultHandler searchResulthandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException
+    {
+      searchResulthandler.handleEntry(ENTRY);
+      resultHandler.handleResult(RESULT);
+    }
+  }
+
+
+
+  private static final SearchResultEntry ENTRY = Responses
+      .newSearchResultEntry(
+          "dn: uid=user.6901,ou=People,dc=example,dc=com",
+          "objectClass: person",
+          "objectClass: inetorgperson",
+          "objectClass: organizationalperson",
+          "objectClass: top",
+          "cn: Romy Ledet",
+          "description: This is the description for Romy Ledet.",
+          "employeeNumber: 6901",
+          "givenName: Romy",
+          "homePhone: ,1 060 737 0385",
+          "initials: RRL",
+          "l: Hampton Roads",
+          "mail: user.6901@example.com",
+          "mobile: ,1 101 041 2007",
+          "pager: ,1 508 271 7836",
+          "postalAddress: Romy Ledet$08019 Dogwood Street$Hampton Roads, MD  55656",
+          "postalCode: 55656", "sn: Ledet", "st: MD",
+          "street: 08019 Dogwood Street", "telephoneNumber: ,1 361 352 6603",
+          "uid: user.6901",
+          "userPassword: {SSHA}CIieVowKJtlbNMzaVK8cluycDU20b,YXYYszFA==");
+  private static final BindResult RESULT = Responses
+      .newBindResult(ResultCode.SUCCESS);
+
+  private static SSLContext sslContext;
+
+
+
+  /**
+   * Dummy LDAP server implementation.
+   *
+   * @param args
+   *          Command line arguments (ignored).
+   * @throws Exception
+   *           If an error occurred.
+   */
+  public static void main(final String[] args) throws Exception
+  {
+    KeyManagerFactory kmf;
+    KeyStore ks;
+    final char[] storepass = "newpass".toCharArray();
+    final char[] keypass = "wshr.ut".toCharArray();
+    final String storename = "newstore";
+
+    sslContext = SSLContext.getInstance("TLS");
+    kmf = KeyManagerFactory.getInstance("SunX509");
+    final FileInputStream fin = new FileInputStream(storename);
+    ks = KeyStore.getInstance("JKS");
+    ks.load(fin, storepass);
+
+    kmf.init(ks, keypass);
+    sslContext.init(kmf.getKeyManagers(), null, null);
+    final LDAPListenerOptions options = new LDAPListenerOptions()
+        .setBacklog(4096);
+
+    LDAPListener listener = null;
+    try
+    {
+      listener = new LDAPListener(11389, new DummyServer(), options);
+      System.out.println("Press any key to stop the server...");
+      System.in.read();
+    }
+    catch (final IOException e)
+    {
+      System.out.println("Error listening to port 11389");
+      e.printStackTrace();
+    }
+    finally
+    {
+      if (listener != null)
+      {
+        listener.close();
+      }
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ServerConnection<Integer> accept(final LDAPClientContext context)
+  {
+    System.out.println("Connection from: " + context.getPeerAddress());
+    return new DummyServerConnection(context);
+  }
+}
diff --git a/sdk/src/org/opends/sdk/sasl/package-info.java b/sdk/examples/org/opends/sdk/examples/package-info.java
old mode 100755
new mode 100644
similarity index 86%
copy from sdk/src/org/opends/sdk/sasl/package-info.java
copy to sdk/examples/org/opends/sdk/examples/package-info.java
index 6683fa9..e85f12d
--- a/sdk/src/org/opends/sdk/sasl/package-info.java
+++ b/sdk/examples/org/opends/sdk/examples/package-info.java
@@ -22,10 +22,13 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
 /**
- * Classes and interfaces for common LDAP SASL Bind requests.
+ * Examples which use the OpenDS LDAP SDK.
  */
-package org.opends.sdk.sasl;
+package org.opends.sdk.examples;
+
+
+
diff --git a/sdk/ext/checkstyle/check-src.xml b/sdk/ext/checkstyle/check-src.xml
new file mode 100644
index 0000000..0d1599a
--- /dev/null
+++ b/sdk/ext/checkstyle/check-src.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<module name="Checker">
+	<module name="TreeWalker">
+		<module name="JavadocMethod">
+			<property name="scope" value="protected" />
+		</module>
+		<module name="JavadocStyle">
+			<property name="scope" value="protected" />
+			<property name="checkEmptyJavadoc" value="true" />
+		</module>
+		<module name="JavadocType">
+			<property name="scope" value="protected" />
+		</module>
+		<module name="JavadocVariable">
+			<property name="scope" value="protected" />
+		</module>
+		<module name="ConstantName" />
+		<module name="ClassTypeParameterName">
+			<property name="format" value="^[A-Z][0-9]*$" />
+		</module>
+		<module name="LocalFinalVariableName" />
+		<module name="LocalVariableName" />
+		<module name="MemberName" />
+		<module name="MethodName" />
+		<module name="MethodTypeParameterName" />
+		<module name="PackageName" />
+		<module name="ParameterName" />
+		<module name="StaticVariableName" />
+		<module name="TypeName" />
+		<module name="IllegalImport" />
+		<module name="RedundantImport" />
+		<module name="UnusedImports" />
+		<module name="LineLength">
+			<property name="max" value="100" />
+		</module>
+		<module name="EqualsHashCode" />
+		<module name="EmptyStatement" />
+		<module name="StringLiteralEquality" />
+		<module name="PackageDeclaration" />
+		<module name="FallThrough" />
+		<module name="FinalClass" />
+		<module name="HideUtilityClassConstructor" />
+		<module name="UpperEll" />
+	</module>
+	<module name="JavadocPackage" />
+	<module name="Header">
+		<property name="headerFile" value="${basedir}/ext/checkstyle/src-header.txt" />
+	</module>
+	<module name="FileTabCharacter">
+		<property name="eachLine" value="true" />
+	</module>
+	<module name="RegexpSingleline">
+		<property name="format" value="\s$" />
+		<property name="message" value="Line ends with whitespace." />
+	</module>
+</module>
diff --git a/sdk/ext/checkstyle/check-tests.xml b/sdk/ext/checkstyle/check-tests.xml
new file mode 100644
index 0000000..fdf5248
--- /dev/null
+++ b/sdk/ext/checkstyle/check-tests.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" "http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
+
+<module name="Checker">
+  <module name="Header">
+    <property name="headerFile" value="${basedir}/ext/checkstyle/src-header.txt"/>
+  </module>
+  <module name="FileTabCharacter">
+    <property name="eachLine" value="true"/>
+  </module>
+  <module name="RegexpSingleline">
+    <property name="format" value="\s$"/>
+    <property name="message" value="Line ends with whitespace."/>
+  </module>
+</module>
+
diff --git a/sdk/ext/checkstyle/checkstyle-all-4.1.jar b/sdk/ext/checkstyle/checkstyle-all-4.1.jar
deleted file mode 100644
index ea018b6..0000000
--- a/sdk/ext/checkstyle/checkstyle-all-4.1.jar
+++ /dev/null
Binary files differ
diff --git a/sdk/ext/checkstyle/checkstyle-all-5.1.jar b/sdk/ext/checkstyle/checkstyle-all-5.1.jar
new file mode 100644
index 0000000..8d8a438
--- /dev/null
+++ b/sdk/ext/checkstyle/checkstyle-all-5.1.jar
Binary files differ
diff --git a/sdk/ext/checkstyle/opends-checkstyle.xml b/sdk/ext/checkstyle/opends-checkstyle.xml
deleted file mode 100644
index bd8582b..0000000
--- a/sdk/ext/checkstyle/opends-checkstyle.xml
+++ /dev/null
@@ -1,97 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE module PUBLIC
-    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
-    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
-
-
-<module name="Checker">
-  <module name="TreeWalker">
-    <property name="cacheFile" value="${basedir}/.checkstyle-cache/opends-checkstyle.cache" />
-
-    <!-- Ensure that each source file starts with the appropriate header -->
-    <module name="Header">
-      <property name="headerFile" value="${basedir}/ext/checkstyle/opends.sourceheader" />
-    </module>
-
-
-    <!-- Ensure that all classes and interfaces are documented -->
-    <module name="JavadocType">
-      <property name="scope" value="private" />
-    </module>
-
-
-    <!-- Ensure that all non-private methods are documented -->
-    <module name="JavadocMethod">
-      <property name="scope" value="package" />
-      <property name="allowUndeclaredRTE" value="false" />
-      <property name="allowMissingParamTags" value="false" />
-      <property name="allowMissingJavadoc" value="false" />
-    </module>
-
-
-    <!-- Ensure that all public and protected fields are documented -->
-    <module name="JavadocVariable">
-      <property name="scope" value="protected" />
-    </module>
-
-
-    <!-- Ensure that all Javadoc comments are well-formed -->
-    <module name="JavadocStyle">
-      <property name="scope" value="private" />
-      <property name="checkFirstSentence" value="true" />
-      <property name="checkEmptyJavadoc" value="true" />
-      <property name="checkHtml" value="true" />
-    </module>
-
-
-    <!-- Ensure that no line exceeds 80 characters in length -->
-    <module name="LineLength">
-      <property name="max" value="80" />
-    </module>
-
-
-    <!-- Ensure that no tab characters are used -->
-    <module name="TabCharacter" />
-
-
-    <!-- Ensure that no line ends with whitespace -->
-    <module name="GenericIllegalRegexp">
-      <property name="format" value="\s$" />
-      <property name="message" value="Line ends with whitespace." />
-    </module>
-
-
-    <!-- Check for string == rather than .equals checks -->
-    <module name="StringLiteralEquality" />
-
-
-    <!-- Check to ensure that anything implmenting .equals(Object) also
-         implements .hashCode() -->
-    <module name="EqualsHashCode" />
-
-
-    <!-- Make sure that all classes have a package statement -->
-    <module name="PackageDeclaration" />
-
-
-    <!-- Identify any switch statements with fall-through -->
-    <module name="FallThrough" />
-
-
-    <!-- Make sure that long constants are defined with an uppercase L -->
-    <module name="UpperEll" />
-
-
-    <!-- Perform basic validation on imports -->
-    <module name="RedundantImport" />
-    <module name="UnusedImports" />
-    <module name="IllegalImport">
-      <property name="illegalPkgs" value="sun" />
-    </module>
-
-
-    <!-- Don't allow empty statements (those that contain just a semicolon) -->
-    <module name="EmptyStatement" />
-  </module>
-</module>
-
diff --git a/sdk/ext/checkstyle/opends-doctarget-checkstyle.xml b/sdk/ext/checkstyle/opends-doctarget-checkstyle.xml
deleted file mode 100644
index cb8b943..0000000
--- a/sdk/ext/checkstyle/opends-doctarget-checkstyle.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE module PUBLIC
-    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
-    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
-
-
-<module name="Checker">
-  <module name="TreeWalker">
-    <property name="cacheFile" value="${basedir}/.checkstyle-cache/opends-doctarget-checkstyle.cache" />
-
-    <!-- Ensure that all methods (including private) are documented -->
-    <module name="JavadocMethod">
-      <property name="scope" value="private" />
-      <property name="allowUndeclaredRTE" value="false" />
-      <property name="allowMissingParamTags" value="false" />
-      <property name="allowMissingJavadoc" value="false" />
-    </module>
-
-
-    <!-- Ensure that all Javadoc comments are well-formed -->
-    <module name="JavadocStyle">
-      <property name="scope" value="private" />
-      <property name="checkFirstSentence" value="true" />
-      <property name="checkEmptyJavadoc" value="true" />
-      <property name="checkHtml" value="true" />
-    </module>
-
-
-    <!-- Ensure that no line exceeds 70 characters in length -->
-    <module name="LineLength">
-      <property name="max" value="70" />
-    </module>
-  </module>
-</module>
-
diff --git a/sdk/ext/checkstyle/opends-functest-checkstyle.xml b/sdk/ext/checkstyle/opends-functest-checkstyle.xml
deleted file mode 100644
index fef53d1..0000000
--- a/sdk/ext/checkstyle/opends-functest-checkstyle.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE module PUBLIC
-    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
-    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
-
-
-<module name="Checker">
-  <module name="TreeWalker">
-    <property name="cacheFile" value="${basedir}/.checkstyle-cache/opends-functest-checkstyle.cache" />
-
-    <!-- Ensure that each source file starts with the appropriate header -->
-    <module name="Header">
-      <property name="headerFile" value="${basedir}/ext/checkstyle/opends.sourceheader" />
-    </module>
-  </module>
-</module>
-
diff --git a/sdk/ext/checkstyle/opends-unittest-checkstyle.xml b/sdk/ext/checkstyle/opends-unittest-checkstyle.xml
deleted file mode 100644
index f5f791a..0000000
--- a/sdk/ext/checkstyle/opends-unittest-checkstyle.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE module PUBLIC
-    "-//Puppy Crawl//DTD Check Configuration 1.2//EN"
-    "http://www.puppycrawl.com/dtds/configuration_1_2.dtd">
-
-
-<module name="Checker">
-  <module name="TreeWalker">
-    <property name="cacheFile" value="${basedir}/.checkstyle-cache/opends-unittest-checkstyle.cache" />
-
-    <!-- Ensure that each source file starts with the appropriate header -->
-    <module name="Header">
-      <property name="headerFile" value="${basedir}/ext/checkstyle/opends.sourceheader" />
-    </module>
-  </module>
-</module>
-
diff --git a/sdk/ext/checkstyle/opends.sourceheader b/sdk/ext/checkstyle/src-header.txt
similarity index 100%
rename from sdk/ext/checkstyle/opends.sourceheader
rename to sdk/ext/checkstyle/src-header.txt
diff --git a/sdk/lib/grizzly.jar b/sdk/lib/grizzly.jar
index 3ea9abd..67375f7 100644
--- a/sdk/lib/grizzly.jar
+++ b/sdk/lib/grizzly.jar
Binary files differ
diff --git a/sdk/resource/bin/_client-script.bat b/sdk/resource/bin/_client-script.bat
index b5a4ac5..aa390ed 100755
--- a/sdk/resource/bin/_client-script.bat
+++ b/sdk/resource/bin/_client-script.bat
@@ -32,15 +32,7 @@
 for %%i in (%~sf0) do set DIR_HOME=%%~dPsi..
 set INSTALL_ROOT=%DIR_HOME%
 
-set INSTANCE_DIR=
-for /f "delims=" %%a in (%INSTALL_ROOT%\instance.loc) do (
-  set INSTANCE_DIR=%%a
-)
-set CUR_DIR=%~dp0
-cd /d %INSTALL_ROOT%
-cd /d %INSTANCE_DIR%
-set INSTANCE_ROOT=%CD%
-cd /d %CUR_DIR%
+if "%NO_CHECK%" == "" set NO_CHECK=true
 
 if "%OPENDS_INVOKE_CLASS%" == "" goto noInvokeClass
 goto launchCommand
diff --git a/sdk/resource/bin/_script-util.bat b/sdk/resource/bin/_script-util.bat
index 820bfe2..046888c 100755
--- a/sdk/resource/bin/_script-util.bat
+++ b/sdk/resource/bin/_script-util.bat
@@ -43,10 +43,6 @@
 setlocal
 for %%i in (%~sf0) do set DIR_HOME=%%~dPsi..
 set INSTALL_ROOT=%DIR_HOME%
-set INSTANCE_DIR=
-for /f "delims=" %%a in (%INSTALL_ROOT%\instance.loc) do (
-  set INSTANCE_DIR=%%a
-)
 set CUR_DIR=%~dp0
 cd /d %INSTALL_ROOT%
 cd /d %INSTANCE_DIR%
diff --git a/sdk/resource/bin/_script-util.sh b/sdk/resource/bin/_script-util.sh
index 549196e..a88a820 100755
--- a/sdk/resource/bin/_script-util.sh
+++ b/sdk/resource/bin/_script-util.sh
@@ -190,61 +190,6 @@
   cd "${WORKING_DIR}"
 fi
 
-if test "${INSTANCE_ROOT}" = ""
-then
-  if [ -f ${INSTALL_ROOT}/configure ]
-  then
-    if [ -f /etc/opends/instance.loc ]
-    then
-      if [ "${SCRIPT_NAME}" = "configure" ]
-      then
-        isVersionOrHelp $*
-	if [ $? -eq 1 ]
-	then
-          echo "${INSTALL_ROOT}/configure has already been run. Exiting."
-          exit 0
-	fi
-      fi
-      read INSTANCE_ROOT <  /etc/opends/instance.loc
-    else
-      if [ "${SCRIPT_NAME}" != "configure" ]
-      then
-        isVersionOrHelp $*
-        if [ $? -eq 1 ]
-        then
-          echo "No instance found. Run ${INSTALL_ROOT}/configure to create it."
-          exit 1
-        fi
-      fi
-    fi
-  else
-    if [ -f ${INSTALL_ROOT}/instance.loc ]
-    then
-      read location < ${INSTALL_ROOT}/instance.loc
-      case `echo ${location}` in
-           /*)
-              INSTANCE_ROOT=${location}
-              break
-              ;;
-           *)
-              INSTANCE_ROOT=${INSTALL_ROOT}/${location}
-              break
-              ;;
-      esac
-    else
-         INSTANCE_ROOT=${INSTALL_ROOT}
-    fi
-  fi
-  if [ -d "${INSTANCE_ROOT}" ]
-  then
-      CURRENT_DIR=`pwd`
-      cd "${INSTANCE_ROOT}"
-      INSTANCE_ROOT=`pwd`
-      export INSTANCE_ROOT
-      cd "${CURRENT_DIR}"
-  fi
-fi
-
 if test "${SCRIPT_UTIL_CMD}" = "set-full-environment-and-test-java"
 then
   set_java_home_and_args
diff --git a/sdk/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControl.java b/sdk/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControl.java
new file mode 100644
index 0000000..75797d9
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControl.java
@@ -0,0 +1,191 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package com.sun.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_ACCTUSABLEREQ_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_ACCTUSABLEREQ_CONTROL_HAS_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The Sun-defined account usability request control. The OID for this control
+ * is 1.3.6.1.4.1.42.2.27.9.5.8, and it does not have a value.
+ *
+ * @see AccountUsabilityResponseControl
+ */
+public final class AccountUsabilityRequestControl implements Control
+{
+  /**
+   * The OID for the account usability request control.
+   */
+  public static final String OID = "1.3.6.1.4.1.42.2.27.9.5.8";
+
+  private final boolean isCritical;
+
+  private static final AccountUsabilityRequestControl CRITICAL_INSTANCE =
+    new AccountUsabilityRequestControl(true);
+  private static final AccountUsabilityRequestControl NONCRITICAL_INSTANCE =
+    new AccountUsabilityRequestControl(false);
+
+  /**
+   * A decoder which can be used for decoding the account usability request
+   * control.
+   */
+  public static final ControlDecoder<AccountUsabilityRequestControl> DECODER =
+    new ControlDecoder<AccountUsabilityRequestControl>()
+  {
+
+    public AccountUsabilityRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof AccountUsabilityRequestControl)
+      {
+        return (AccountUsabilityRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_ACCTUSABLEREQ_CONTROL_BAD_OID
+            .get(control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (control.hasValue())
+      {
+        final LocalizableMessage message = ERR_ACCTUSABLEREQ_CONTROL_HAS_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new account usability request control having the provided
+   * criticality.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @return The new control.
+   */
+  public static AccountUsabilityRequestControl newControl(
+      final boolean isCritical)
+  {
+    return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+  }
+
+
+
+  // Prevent direct instantiation.
+  private AccountUsabilityRequestControl(final boolean isCritical)
+  {
+    this.isCritical = isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("AccountUsableRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControl.java b/sdk/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControl.java
new file mode 100644
index 0000000..6a4f776
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControl.java
@@ -0,0 +1,570 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package com.sun.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_ACCTUSABLERES_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_ACCTUSABLERES_DECODE_ERROR;
+import static com.sun.opends.sdk.messages.Messages.ERR_ACCTUSABLERES_NO_CONTROL_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ACCTUSABLERES_UNKNOWN_VALUE_ELEMENT_TYPE;
+import static com.sun.opends.sdk.util.StaticUtils.byteToHex;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The Sun-defined account usability response control. The OID for this control
+ * is 1.3.6.1.4.1.42.2.27.9.5.8, and it has a value encoded according to the
+ * following BNF:
+ *
+ * <pre>
+ * ACCOUNT_USABLE_RESPONSE ::= CHOICE {
+ *      is_available           [0] INTEGER, -- Seconds before expiration --
+ *      is_not_available       [1] MORE_INFO }
+ *
+ * MORE_INFO ::= SEQUENCE {
+ *      inactive               [0] BOOLEAN DEFAULT FALSE,
+ *      reset                  [1] BOOLEAN DEFAULT FALSE,
+ *      expired                [2] BOOLEAN DEFAULT_FALSE,
+ *      remaining_grace        [3] INTEGER OPTIONAL,
+ *      seconds_before_unlock  [4] INTEGER OPTIONAL }
+ * </pre>
+ *
+ * @see AccountUsabilityRequestControl
+ */
+public final class AccountUsabilityResponseControl implements Control
+{
+  /**
+   * The OID for the account usability response control.
+   */
+  public static final String OID = AccountUsabilityRequestControl.OID;
+
+  /**
+   * A decoder which can be used for decoding the account usability response
+   * control.
+   */
+  public static final ControlDecoder<AccountUsabilityResponseControl> DECODER =
+    new ControlDecoder<AccountUsabilityResponseControl>()
+  {
+
+    public AccountUsabilityResponseControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof AccountUsabilityResponseControl)
+      {
+        return (AccountUsabilityResponseControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_ACCTUSABLERES_CONTROL_BAD_OID
+            .get(control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The response control must always have a value.
+        final LocalizableMessage message = ERR_ACCTUSABLERES_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      try
+      {
+        final ASN1Reader reader = ASN1.getReader(control.getValue());
+        switch (reader.peekType())
+        {
+        case TYPE_SECONDS_BEFORE_EXPIRATION:
+          final int secondsBeforeExpiration = (int) reader.readInteger();
+          return new AccountUsabilityResponseControl(control.isCritical(),
+              true, false, false, false, -1, false, 0, secondsBeforeExpiration);
+        case TYPE_MORE_INFO:
+          boolean isInactive = false;
+          boolean isReset = false;
+          boolean isExpired = false;
+          boolean isLocked = false;
+          int remainingGraceLogins = -1;
+          int secondsBeforeUnlock = 0;
+
+          reader.readStartSequence();
+          if (reader.hasNextElement() && (reader.peekType() == TYPE_INACTIVE))
+          {
+            isInactive = reader.readBoolean();
+          }
+          if (reader.hasNextElement() && (reader.peekType() == TYPE_RESET))
+          {
+            isReset = reader.readBoolean();
+          }
+          if (reader.hasNextElement() && (reader.peekType() == TYPE_EXPIRED))
+          {
+            isExpired = reader.readBoolean();
+          }
+          if (reader.hasNextElement()
+              && (reader.peekType() == TYPE_REMAINING_GRACE_LOGINS))
+          {
+            remainingGraceLogins = (int) reader.readInteger();
+          }
+          if (reader.hasNextElement()
+              && (reader.peekType() == TYPE_SECONDS_BEFORE_UNLOCK))
+          {
+            isLocked = true;
+            secondsBeforeUnlock = (int) reader.readInteger();
+          }
+          reader.readEndSequence();
+
+          return new AccountUsabilityResponseControl(control.isCritical(),
+              false, isInactive, isReset, isExpired, remainingGraceLogins,
+              isLocked, secondsBeforeUnlock, -1);
+
+        default:
+          final LocalizableMessage message = ERR_ACCTUSABLERES_UNKNOWN_VALUE_ELEMENT_TYPE
+              .get(byteToHex(reader.peekType()));
+          throw DecodeException.error(message);
+        }
+      }
+      catch (final IOException e)
+      {
+        StaticUtils.DEBUG_LOG.throwing(
+            "AccountUsabilityResponseControl.decodeControl", "decode", e);
+
+        final LocalizableMessage message = ERR_ACCTUSABLERES_DECODE_ERROR
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message);
+      }
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+  /**
+   * The BER type to use for the seconds before expiration when the account is
+   * available.
+   */
+  private static final byte TYPE_SECONDS_BEFORE_EXPIRATION = (byte) 0x80;
+
+  /**
+   * The BER type to use for the MORE_INFO sequence when the account is not
+   * available.
+   */
+  private static final byte TYPE_MORE_INFO = (byte) 0xA1;
+
+  /**
+   * The BER type to use for the MORE_INFO element that indicates that the
+   * account has been inactivated.
+   */
+  private static final byte TYPE_INACTIVE = (byte) 0x80;
+
+  /**
+   * The BER type to use for the MORE_INFO element that indicates that the
+   * password has been administratively reset.
+   */
+  private static final byte TYPE_RESET = (byte) 0x81;
+
+  /**
+   * The BER type to use for the MORE_INFO element that indicates that the
+   * user's password is expired.
+   */
+  private static final byte TYPE_EXPIRED = (byte) 0x82;
+
+  /**
+   * The BER type to use for the MORE_INFO element that provides the number of
+   * remaining grace logins.
+   */
+  private static final byte TYPE_REMAINING_GRACE_LOGINS = (byte) 0x83;
+
+  /**
+   * The BER type to use for the MORE_INFO element that indicates that the
+   * password has been administratively reset.
+   */
+  private static final byte TYPE_SECONDS_BEFORE_UNLOCK = (byte) 0x84;
+
+
+
+  /**
+   * Creates a new account usability response control that may be used to
+   * indicate that the account is not available and provide information about
+   * the underlying reason.
+   *
+   * @param isInactive
+   *          Indicates whether the user's account has been inactivated by an
+   *          administrator.
+   * @param isReset
+   *          Indicates whether the user's password has been reset by an
+   *          administrator.
+   * @param isExpired
+   *          Indicates whether the user's password has expired.
+   * @param remainingGraceLogins
+   *          The number of grace logins remaining. A value of {@code 0}
+   *          indicates that there are none remaining. A value of {@code -1}
+   *          indicates that grace login functionality is not enabled.
+   * @param isLocked
+   *          Indicates whether the user's account is currently locked out.
+   * @param secondsBeforeUnlock
+   *          The length of time in seconds until the account is unlocked. A
+   *          value of {@code -1} indicates that the account will not be
+   *          automatically unlocked and must be reset by an administrator.
+   * @return The new control.
+   */
+  public static AccountUsabilityResponseControl newControl(
+      final boolean isInactive, final boolean isReset, final boolean isExpired,
+      final int remainingGraceLogins, final boolean isLocked,
+      final int secondsBeforeUnlock)
+  {
+    return new AccountUsabilityResponseControl(false, false, isInactive,
+        isReset, isExpired, remainingGraceLogins, isLocked,
+        secondsBeforeUnlock, -1);
+  }
+
+
+
+  /**
+   * Creates a new account usability response control that may be used to
+   * indicate that the account is available and provide the number of seconds
+   * until expiration.
+   *
+   * @param secondsBeforeExpiration
+   *          The length of time in seconds until the user's password expires,
+   *          or {@code -1} if the user's password will not expire or the
+   *          expiration time is unknown.
+   * @return The new control.
+   */
+  public static AccountUsabilityResponseControl newControl(
+      final int secondsBeforeExpiration)
+  {
+    return new AccountUsabilityResponseControl(false, true, false, false,
+        false, -1, false, 0, secondsBeforeExpiration);
+  }
+
+
+
+  // Indicates whether the user's account is usable.
+  private final boolean isUsable;
+
+  // Indicates whether the user's password is expired.
+  private final boolean isExpired;
+
+  // Indicates whether the user's account is inactive.
+  private final boolean isInactive;
+
+  // Indicates whether the user's account is currently locked.
+  private final boolean isLocked;
+
+  // Indicates whether the user's password has been reset and must be
+  // changed before anything else can be done.
+  private final boolean isReset;
+
+  // The number of remaining grace logins, if available.
+  private final int remainingGraceLogins;
+
+  // The length of time in seconds before the user's password expires,
+  // if available.
+  private final int secondsBeforeExpiration;
+
+  // The length of time before the user's account is unlocked, if
+  // available.
+  private final int secondsBeforeUnlock;
+
+  private final boolean isCritical;
+
+
+
+  // Prevent direct instantiation.
+  private AccountUsabilityResponseControl(final boolean isCritical,
+      final boolean isUsable, final boolean isInactive, final boolean isReset,
+      final boolean isExpired, final int remainingGraceLogins,
+      final boolean isLocked, final int secondsBeforeUnlock,
+      final int secondsBeforeExpiration)
+  {
+    this.isCritical = isCritical;
+    this.isUsable = isUsable;
+    this.isInactive = isInactive;
+    this.isReset = isReset;
+    this.isExpired = isExpired;
+    this.remainingGraceLogins = remainingGraceLogins;
+    this.isLocked = isLocked;
+    this.secondsBeforeUnlock = secondsBeforeUnlock;
+    this.secondsBeforeExpiration = secondsBeforeExpiration;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * Returns the number of remaining grace logins for the user. This value is
+   * unreliable if the user's password has not expired.
+   *
+   * @return The number of remaining grace logins for the user, or {@code -1} if
+   *         the grace logins feature is not enabled for the user.
+   */
+  public int getRemainingGraceLogins()
+  {
+    return remainingGraceLogins;
+  }
+
+
+
+  /**
+   * Returns the length of time in seconds before the user's password expires.
+   * This value is unreliable if the account is not available.
+   *
+   * @return The length of time in seconds before the user's password expires,
+   *         or {@code -1} if it is unknown or password expiration is not
+   *         enabled for the user.
+   */
+  public int getSecondsBeforeExpiration()
+  {
+    return secondsBeforeExpiration;
+  }
+
+
+
+  /**
+   * Returns the length of time in seconds before the user's account is
+   * automatically unlocked. This value is unreliable is the user's account is
+   * not locked.
+   *
+   * @return The length of time in seconds before the user's account is
+   *         automatically unlocked, or {@code -1} if it requires administrative
+   *         action to unlock the account.
+   */
+  public int getSecondsBeforeUnlock()
+  {
+    return secondsBeforeUnlock;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      if (secondsBeforeExpiration < 0)
+      {
+        writer.writeInteger(TYPE_SECONDS_BEFORE_EXPIRATION,
+            secondsBeforeExpiration);
+      }
+      else
+      {
+        writer.writeStartSequence(TYPE_MORE_INFO);
+        if (isInactive)
+        {
+          writer.writeBoolean(TYPE_INACTIVE, true);
+        }
+
+        if (isReset)
+        {
+          writer.writeBoolean(TYPE_RESET, true);
+        }
+
+        if (isExpired)
+        {
+          writer.writeBoolean(TYPE_EXPIRED, true);
+
+          if (remainingGraceLogins >= 0)
+          {
+            writer.writeInteger(TYPE_REMAINING_GRACE_LOGINS,
+                remainingGraceLogins);
+          }
+        }
+
+        if (isLocked)
+        {
+          writer.writeInteger(TYPE_SECONDS_BEFORE_UNLOCK, secondsBeforeUnlock);
+        }
+        writer.writeEndSequence();
+      }
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * Returns {@code true} if the user's password has expired.
+   *
+   * @return <CODE>true</CODE> if the user's password has expired, or
+   *         <CODE>false</CODE> if not.
+   */
+  public boolean isExpired()
+  {
+    return isExpired;
+  }
+
+
+
+  /**
+   * Returns {@code true} if the user's account has been inactivated by an
+   * administrator.
+   *
+   * @return <CODE>true</CODE> if the user's account has been inactivated by an
+   *         administrator, or <CODE>false</CODE> if not.
+   */
+  public boolean isInactive()
+  {
+    return isInactive;
+  }
+
+
+
+  /**
+   * Returns {@code true} if the user's account is locked for some reason.
+   *
+   * @return <CODE>true</CODE> if the user's account is locked, or
+   *         <CODE>false</CODE> if it is not.
+   */
+  public boolean isLocked()
+  {
+    return isLocked;
+  }
+
+
+
+  /**
+   * Returns {@code true} if the user's password has been administratively reset
+   * and the user must change that password before any other operations will be
+   * allowed.
+   *
+   * @return <CODE>true</CODE> if the user's password has been administratively
+   *         reset, or <CODE>false</CODE> if not.
+   */
+  public boolean isReset()
+  {
+    return isReset;
+  }
+
+
+
+  /**
+   * Returns {@code true} if the associated user account is available for use.
+   *
+   * @return <CODE>true</CODE> if the associated user account is available, or
+   *         <CODE>false</CODE> if not.
+   */
+  public boolean isUsable()
+  {
+    return isUsable;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("AccountUsableResponseControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", isUsable=");
+    builder.append(isUsable);
+    if (isUsable)
+    {
+      builder.append(",secondsBeforeExpiration=");
+      builder.append(secondsBeforeExpiration);
+    }
+    else
+    {
+      builder.append(",isInactive=");
+      builder.append(isInactive);
+      builder.append(",isReset=");
+      builder.append(isReset);
+      builder.append(",isExpired=");
+      builder.append(isExpired);
+      builder.append(",remainingGraceLogins=");
+      builder.append(remainingGraceLogins);
+      builder.append(",isLocked=");
+      builder.append(isLocked);
+      builder.append(",secondsBeforeUnlock=");
+      builder.append(secondsBeforeUnlock);
+    }
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/controls/RealAttributesOnlyRequestControl.java b/sdk/src/com/sun/opends/sdk/controls/RealAttributesOnlyRequestControl.java
new file mode 100644
index 0000000..3fa3e46
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/controls/RealAttributesOnlyRequestControl.java
@@ -0,0 +1,192 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package com.sun.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_REAL_ATTRS_ONLY_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_REAL_ATTRS_ONLY_INVALID_CONTROL_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The Sun-defined real attributes only request control. The OID for this
+ * control is 2.16.840.1.113730.3.4.17, and it does not have a value.
+ */
+public final class RealAttributesOnlyRequestControl implements Control
+{
+  /**
+   * The OID for the real attributes only request control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.17";
+
+  private static final RealAttributesOnlyRequestControl CRITICAL_INSTANCE =
+    new RealAttributesOnlyRequestControl(true);
+
+  private static final RealAttributesOnlyRequestControl NONCRITICAL_INSTANCE =
+    new RealAttributesOnlyRequestControl(false);
+
+  /**
+   * A decoder which can be used for decoding the real attributes only request
+   * control.
+   */
+  public static final ControlDecoder<RealAttributesOnlyRequestControl> DECODER =
+    new ControlDecoder<RealAttributesOnlyRequestControl>()
+  {
+
+    public RealAttributesOnlyRequestControl decodeControl(
+        final Control control, final DecodeOptions options)
+        throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof RealAttributesOnlyRequestControl)
+      {
+        return (RealAttributesOnlyRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_REAL_ATTRS_ONLY_CONTROL_BAD_OID
+            .get(control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (control.hasValue())
+      {
+        final LocalizableMessage message = ERR_REAL_ATTRS_ONLY_INVALID_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new real attributes only request control having the provided
+   * criticality.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @return The new control.
+   */
+  public static RealAttributesOnlyRequestControl newControl(
+      final boolean isCritical)
+  {
+    return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+  }
+
+
+
+  private final boolean isCritical;
+
+
+
+  private RealAttributesOnlyRequestControl(final boolean isCritical)
+  {
+    this.isCritical = isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("RealAttributesOnlyRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/com/sun/opends/sdk/controls/VirtualAttributesOnlyRequestControl.java b/sdk/src/com/sun/opends/sdk/controls/VirtualAttributesOnlyRequestControl.java
new file mode 100644
index 0000000..023348f
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/controls/VirtualAttributesOnlyRequestControl.java
@@ -0,0 +1,192 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package com.sun.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_VIRTUAL_ATTRS_ONLY_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_VIRTUAL_ATTRS_ONLY_INVALID_CONTROL_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The Sun-defined virtual attributes only request control. The OID for this
+ * control is 2.16.840.1.113730.3.4.19, and it does not have a value.
+ */
+public final class VirtualAttributesOnlyRequestControl implements Control
+{
+  /**
+   * The OID for the virtual attributes only request control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.19";
+
+  private static final VirtualAttributesOnlyRequestControl CRITICAL_INSTANCE =
+    new VirtualAttributesOnlyRequestControl(true);
+
+  private static final VirtualAttributesOnlyRequestControl NONCRITICAL_INSTANCE =
+    new VirtualAttributesOnlyRequestControl(false);
+
+  /**
+   * A decoder which can be used for decoding the virtual attributes only
+   * request control.
+   */
+  public static final ControlDecoder<VirtualAttributesOnlyRequestControl>
+    DECODER = new ControlDecoder<VirtualAttributesOnlyRequestControl>()
+  {
+
+    public VirtualAttributesOnlyRequestControl decodeControl(
+        final Control control, final DecodeOptions options)
+        throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof VirtualAttributesOnlyRequestControl)
+      {
+        return (VirtualAttributesOnlyRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_VIRTUAL_ATTRS_ONLY_CONTROL_BAD_OID
+            .get(control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (control.hasValue())
+      {
+        final LocalizableMessage message = ERR_VIRTUAL_ATTRS_ONLY_INVALID_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new virtual attributes only request control having the provided
+   * criticality.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @return The new control.
+   */
+  public static VirtualAttributesOnlyRequestControl newControl(
+      final boolean isCritical)
+  {
+    return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+  }
+
+
+
+  private final boolean isCritical;
+
+
+
+  private VirtualAttributesOnlyRequestControl(final boolean isCritical)
+  {
+    this.isCritical = isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("VirtualAttributesOnlyRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/sasl/package-info.java b/sdk/src/com/sun/opends/sdk/controls/package-info.java
old mode 100755
new mode 100644
similarity index 86%
copy from sdk/src/org/opends/sdk/sasl/package-info.java
copy to sdk/src/com/sun/opends/sdk/controls/package-info.java
index 6683fa9..d35f771
--- a/sdk/src/org/opends/sdk/sasl/package-info.java
+++ b/sdk/src/com/sun/opends/sdk/controls/package-info.java
@@ -22,10 +22,13 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
 /**
- * Classes and interfaces for common LDAP SASL Bind requests.
+ * Classes implementing Sun proprietary LDAP controls.
  */
-package org.opends.sdk.sasl;
+package com.sun.opends.sdk.controls;
+
+
+
diff --git a/sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedRequest.java b/sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedRequest.java
new file mode 100644
index 0000000..6166612
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedRequest.java
@@ -0,0 +1,248 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.extensions;
+
+
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.requests.AbstractExtendedRequest;
+import org.opends.sdk.requests.ExtendedRequest;
+import org.opends.sdk.requests.ExtendedRequestDecoder;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+
+
+
+/**
+ * Get connection ID extended request. This operation can be used to retrieve
+ * the client connection ID.
+ *
+ * @see GetConnectionIDExtendedResult
+ */
+public final class GetConnectionIDExtendedRequest
+    extends
+    AbstractExtendedRequest<GetConnectionIDExtendedRequest, GetConnectionIDExtendedResult>
+{
+  private static final class RequestDecoder
+      implements
+      ExtendedRequestDecoder<GetConnectionIDExtendedRequest, GetConnectionIDExtendedResult>
+  {
+
+    public GetConnectionIDExtendedRequest decodeExtendedRequest(
+        final ExtendedRequest<?> request, final DecodeOptions options)
+        throws DecodeException
+    {
+      // TODO: Check the OID and that the value is not present.
+      final GetConnectionIDExtendedRequest newRequest = new GetConnectionIDExtendedRequest();
+      for (final Control control : request.getControls())
+      {
+        newRequest.addControl(control);
+      }
+      return newRequest;
+
+    }
+  }
+
+
+
+  private static final class ResultDecoder implements
+      ExtendedResultDecoder<GetConnectionIDExtendedResult>
+  {
+    /**
+     * {@inheritDoc}
+     */
+    public GetConnectionIDExtendedResult adaptExtendedErrorResult(
+        final ResultCode resultCode, final String matchedDN,
+        final String diagnosticMessage)
+    {
+      if (!resultCode.isExceptional())
+      {
+        // A successful response must contain a response name and
+        // value.
+        throw new IllegalArgumentException(
+            "No response name and value for result code "
+                + resultCode.intValue());
+      }
+      return GetConnectionIDExtendedResult.newResult(resultCode, -1)
+          .setMatchedDN(matchedDN).setDiagnosticMessage(diagnosticMessage);
+    }
+
+
+
+    public GetConnectionIDExtendedResult decodeExtendedResult(
+        final ExtendedResult result, final DecodeOptions options)
+        throws DecodeException
+    {
+      if (result instanceof GetConnectionIDExtendedResult)
+      {
+        return (GetConnectionIDExtendedResult) result;
+      }
+      else
+      {
+        final ResultCode resultCode = result.getResultCode();
+        final ByteString responseValue = result.getValue();
+
+        if (!resultCode.isExceptional()
+            && ((responseValue == null) || (responseValue.length() <= 0)))
+        {
+          throw DecodeException.error(LocalizableMessage
+              .raw("Empty response value"));
+        }
+
+        try
+        {
+          final ASN1Reader reader = ASN1.getReader(responseValue);
+          final int connectionID = (int) reader.readInteger();
+          final GetConnectionIDExtendedResult newResult = GetConnectionIDExtendedResult
+              .newResult(resultCode, connectionID).setMatchedDN(
+                  result.getMatchedDN()).setDiagnosticMessage(
+                  result.getDiagnosticMessage());
+
+          for (final Control control : result.getControls())
+          {
+            newResult.addControl(control);
+          }
+
+          return newResult;
+        }
+        catch (final IOException e)
+        {
+          throw DecodeException.error(LocalizableMessage
+              .raw("Error decoding response value"), e);
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * The OID for the extended operation that can be used to get the client
+   * connection ID. It will be both the request and response OID.
+   */
+  public static final String OID = "1.3.6.1.4.1.26027.1.6.2";
+
+  // Singleton.
+  private static final GetConnectionIDExtendedRequest INSTANCE =
+    new GetConnectionIDExtendedRequest();
+
+  /**
+   * A decoder which can be used to decode get connection ID extended operation
+   * requests.
+   */
+  public static final RequestDecoder REQUEST_DECODER = new RequestDecoder();
+
+  // No need to expose this.
+  private static final ResultDecoder RESULT_DECODER = new ResultDecoder();
+
+
+
+  /**
+   * Creates a new get connection ID extended request.
+   *
+   * @return The new get connection ID extended request.
+   */
+  public static GetConnectionIDExtendedRequest newRequest()
+  {
+    return INSTANCE;
+  }
+
+
+
+  // Prevent instantiation.
+  private GetConnectionIDExtendedRequest()
+  {
+    // Nothing to do.
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ExtendedResultDecoder<GetConnectionIDExtendedResult> getResultDecoder()
+  {
+    return RESULT_DECODER;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("GetConnectionIDExtendedRequest(requestName=");
+    builder.append(getOID());
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedResult.java b/sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedResult.java
new file mode 100644
index 0000000..9228497
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedResult.java
@@ -0,0 +1,184 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.extensions;
+
+
+
+import java.io.IOException;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.ByteStringBuilder;
+import org.opends.sdk.ResultCode;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.responses.AbstractExtendedResult;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * Get connection ID extended result.
+ *
+ * @see GetConnectionIDExtendedRequest
+ */
+public final class GetConnectionIDExtendedResult extends
+    AbstractExtendedResult<GetConnectionIDExtendedResult>
+{
+  /**
+   * Creates a new get connection ID extended result.
+   *
+   * @param resultCode
+   *          The result code.
+   * @param connectionID
+   *          The client connection ID.
+   * @return The new get connection ID extended result.
+   * @throws NullPointerException
+   *           If {@code resultCode} was {@code null}.
+   */
+  public static GetConnectionIDExtendedResult newResult(
+      final ResultCode resultCode, final int connectionID)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(resultCode);
+    return new GetConnectionIDExtendedResult(resultCode, connectionID);
+  }
+
+
+
+  private int connectionID;
+
+
+
+  private GetConnectionIDExtendedResult(final ResultCode resultCode,
+      final int connectionID)
+  {
+    super(resultCode);
+    this.connectionID = connectionID;
+  }
+
+
+
+  /**
+   * Returns the client connection ID.
+   *
+   * @return The client connection ID.
+   */
+  public int getConnectionID()
+  {
+    return connectionID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    return GetConnectionIDExtendedRequest.OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder(6);
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+
+    try
+    {
+      writer.writeInteger(connectionID);
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+
+    return buffer.toByteString();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * Sets the client connection ID.
+   *
+   * @param connectionID
+   *          The client connection ID.
+   * @return This get connection ID result.
+   */
+  public GetConnectionIDExtendedResult setConnectionID(final int connectionID)
+  {
+    this.connectionID = connectionID;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("GetConnectionIDExtendedResponse(resultCode=");
+    builder.append(getResultCode());
+    builder.append(", matchedDN=");
+    builder.append(getMatchedDN());
+    builder.append(", diagnosticMessage=");
+    builder.append(getDiagnosticMessage());
+    builder.append(", referrals=");
+    builder.append(getReferralURIs());
+    builder.append(", responseName=");
+    builder.append(getOID());
+    builder.append(", connectionID=");
+    builder.append(connectionID);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/extensions/GetSymmetricKeyExtendedRequest.java b/sdk/src/com/sun/opends/sdk/extensions/GetSymmetricKeyExtendedRequest.java
new file mode 100644
index 0000000..4056c87
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/extensions/GetSymmetricKeyExtendedRequest.java
@@ -0,0 +1,334 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.extensions;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_GET_SYMMETRIC_KEY_ASN1_DECODE_EXCEPTION;
+import static com.sun.opends.sdk.messages.Messages.ERR_GET_SYMMETRIC_KEY_NO_VALUE;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.requests.AbstractExtendedRequest;
+import org.opends.sdk.requests.ExtendedRequest;
+import org.opends.sdk.requests.ExtendedRequestDecoder;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+import org.opends.sdk.responses.Responses;
+
+import com.sun.opends.sdk.util.StaticUtils;
+
+
+
+/**
+ * Get symmetric key extended request.
+ */
+public final class GetSymmetricKeyExtendedRequest extends
+    AbstractExtendedRequest<GetSymmetricKeyExtendedRequest, ExtendedResult>
+{
+  private static final class RequestDecoder implements
+      ExtendedRequestDecoder<GetSymmetricKeyExtendedRequest, ExtendedResult>
+  {
+
+    public GetSymmetricKeyExtendedRequest decodeExtendedRequest(
+        final ExtendedRequest<?> request, final DecodeOptions options)
+        throws DecodeException
+    {
+      final ByteString requestValue = request.getValue();
+      if (requestValue == null)
+      {
+        // The request must always have a value.
+        final LocalizableMessage message = ERR_GET_SYMMETRIC_KEY_NO_VALUE.get();
+        throw DecodeException.error(message);
+      }
+
+      String requestSymmetricKey = null;
+      String instanceKeyID = null;
+
+      try
+      {
+        final ASN1Reader reader = ASN1.getReader(requestValue);
+        reader.readStartSequence();
+        if (reader.hasNextElement()
+            && (reader.peekType() == TYPE_SYMMETRIC_KEY_ELEMENT))
+        {
+          requestSymmetricKey = reader.readOctetStringAsString();
+        }
+        if (reader.hasNextElement()
+            && (reader.peekType() == TYPE_INSTANCE_KEY_ID_ELEMENT))
+        {
+          instanceKeyID = reader.readOctetStringAsString();
+        }
+        reader.readEndSequence();
+
+        final GetSymmetricKeyExtendedRequest newRequest = new GetSymmetricKeyExtendedRequest()
+            .setRequestSymmetricKey(requestSymmetricKey).setInstanceKeyID(
+                instanceKeyID);
+
+        for (final Control control : request.getControls())
+        {
+          newRequest.addControl(control);
+        }
+
+        return newRequest;
+      }
+      catch (final IOException ae)
+      {
+        StaticUtils.DEBUG_LOG.throwing("GetSymmetricKeyRequest.Operation",
+            "decodeRequest", ae);
+
+        final LocalizableMessage message = ERR_GET_SYMMETRIC_KEY_ASN1_DECODE_EXCEPTION
+            .get(ae.getMessage());
+        throw DecodeException.error(message, ae);
+      }
+    }
+  }
+
+
+
+  private static final class ResultDecoder implements
+      ExtendedResultDecoder<ExtendedResult>
+  {
+
+    public ExtendedResult adaptExtendedErrorResult(final ResultCode resultCode,
+        final String matchedDN, final String diagnosticMessage)
+    {
+      return Responses.newGenericExtendedResult(resultCode).setMatchedDN(
+          matchedDN).setDiagnosticMessage(diagnosticMessage);
+    }
+
+
+
+    public ExtendedResult decodeExtendedResult(final ExtendedResult result,
+        final DecodeOptions options) throws DecodeException
+    {
+      return result;
+    }
+  }
+
+
+
+  /**
+   * The request OID for the get symmetric key extended operation.
+   */
+  public static final String OID = "1.3.6.1.4.1.26027.1.6.3";
+
+  /**
+   * The BER type value for the symmetric key element of the operation value.
+   */
+  private static final byte TYPE_SYMMETRIC_KEY_ELEMENT = (byte) 0x80;
+
+  /**
+   * The BER type value for the instance key ID element of the operation value.
+   */
+  private static final byte TYPE_INSTANCE_KEY_ID_ELEMENT = (byte) 0x81;
+
+  /**
+   * A decoder which can be used to decode get symmetric key extended operation
+   * requests.
+   */
+  public static final RequestDecoder REQUEST_DECODER = new RequestDecoder();
+
+  // No need to expose this.
+  private static final ResultDecoder RESULT_DECODER = new ResultDecoder();
+
+
+
+  /**
+   * Creates a new get symmetric key extended request.
+   *
+   * @return The new get symmetric key extended request.
+   */
+  public static GetSymmetricKeyExtendedRequest newRequest()
+  {
+    return new GetSymmetricKeyExtendedRequest();
+  }
+
+
+
+  private String requestSymmetricKey = null;
+
+  private String instanceKeyID = null;
+
+
+
+  // Instantiation via factory.
+  private GetSymmetricKeyExtendedRequest()
+  {
+
+  }
+
+
+
+  /**
+   * Returns the instance key ID.
+   *
+   * @return The instance key ID.
+   */
+  public String getInstanceKeyID()
+  {
+    return instanceKeyID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * Returns the request symmetric key.
+   *
+   * @return The request symmetric key.
+   */
+  public String getRequestSymmetricKey()
+  {
+    return requestSymmetricKey;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ExtendedResultDecoder<ExtendedResult> getResultDecoder()
+  {
+    return RESULT_DECODER;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+
+    try
+    {
+      writer.writeStartSequence();
+      if (requestSymmetricKey != null)
+      {
+        writer
+            .writeOctetString(TYPE_SYMMETRIC_KEY_ELEMENT, requestSymmetricKey);
+      }
+      if (instanceKeyID != null)
+      {
+        writer.writeOctetString(TYPE_INSTANCE_KEY_ID_ELEMENT, instanceKeyID);
+      }
+      writer.writeEndSequence();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+
+    return buffer.toByteString();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * Sets the instance key ID.
+   *
+   * @param instanceKeyID
+   *          The instance key ID.
+   * @return This get symmetric key request.
+   */
+  public GetSymmetricKeyExtendedRequest setInstanceKeyID(
+      final String instanceKeyID)
+  {
+    this.instanceKeyID = instanceKeyID;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the request symmetric key.
+   *
+   * @param requestSymmetricKey
+   *          The request symmetric key.
+   * @return This get symmetric key request.
+   */
+  public GetSymmetricKeyExtendedRequest setRequestSymmetricKey(
+      final String requestSymmetricKey)
+  {
+    this.requestSymmetricKey = requestSymmetricKey;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("GetSymmetricKeyExtendedRequest(requestName=");
+    builder.append(getOID());
+    builder.append(", requestSymmetricKey=");
+    builder.append(requestSymmetricKey);
+    builder.append(", instanceKeyID=");
+    builder.append(instanceKeyID);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedRequest.java b/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedRequest.java
new file mode 100644
index 0000000..59a06e1
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedRequest.java
@@ -0,0 +1,1139 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.extensions;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_PWPSTATE_EXTOP_DECODE_FAILURE;
+import static com.sun.opends.sdk.messages.Messages.ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_PWPSTATE_EXTOP_UNKNOWN_OP_TYPE;
+import static com.sun.opends.sdk.util.StaticUtils.formatAsGeneralizedTime;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.requests.AbstractExtendedRequest;
+import org.opends.sdk.requests.ExtendedRequest;
+import org.opends.sdk.requests.ExtendedRequestDecoder;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * This class implements an LDAP extended operation that can be used to query
+ * and update elements of the Directory Server password policy state for a given
+ * user. The ASN.1 definition for the value of the extended request is: <BR>
+ *
+ * <PRE>
+ * PasswordPolicyStateValue ::= SEQUENCE {
+ *      targetUser     LDAPDN
+ *      operations     SEQUENCE OF PasswordPolicyStateOperation OPTIONAL }
+ * PasswordPolicyStateOperation ::= SEQUENCE {
+ *      opType       ENUMERATED {
+ *           getPasswordPolicyDN                          (0),
+ *           getAccountDisabledState                      (1),
+ *           setAccountDisabledState                      (2),
+ *           clearAccountDisabledState                    (3),
+ *           getAccountExpirationTime                     (4),
+ *           setAccountExpirationTime                     (5),
+ *           clearAccountExpirationTime                   (6),
+ *           getSecondsUntilAccountExpiration             (7),
+ *           getPasswordChangedTime                       (8),
+ *           setPasswordChangedTime                       (9),
+ *           clearPasswordChangedTime                     (10),
+ *           getPasswordExpirationWarnedTime              (11),
+ *           setPasswordExpirationWarnedTime              (12),
+ *           clearPasswordExpirationWarnedTime            (13),
+ *           getSecondsUntilPasswordExpiration            (14),
+ *           getSecondsUntilPasswordExpirationWarning     (15),
+ *           getAuthenticationFailureTimes                (16),
+ *           addAuthenticationFailureTime                 (17),
+ *           setAuthenticationFailureTimes                (18),
+ *           clearAuthenticationFailureTimes              (19),
+ *           getSecondsUntilAuthenticationFailureUnlock   (20),
+ *           getRemainingAuthenticationFailureCount       (21),
+ *           getLastLoginTime                             (22),
+ *           setLastLoginTime                             (23),
+ *           clearLastLoginTime                           (24),
+ *           getSecondsUntilIdleLockout                   (25),
+ *           getPasswordResetState                        (26),
+ *           setPasswordResetState                        (27),
+ *           clearPasswordResetState                      (28),
+ *           getSecondsUntilPasswordResetLockout          (29),
+ *           getGraceLoginUseTimes                        (30),
+ *           addGraceLoginUseTime                         (31),
+ *           setGraceLoginUseTimes                        (32),
+ *           clearGraceLoginUseTimes                      (33),
+ *           getRemainingGraceLoginCount                  (34),
+ *           getPasswordChangedByRequiredTime             (35),
+ *           setPasswordChangedByRequiredTime             (36),
+ *           clearPasswordChangedByRequiredTime           (37),
+ *           getSecondsUntilRequiredChangeTime            (38),
+ *           getPasswordHistory                           (39),
+ *           clearPasswordHistory                         (40),
+ *           ... },
+ *      opValues     SEQUENCE OF OCTET STRING OPTIONAL }
+ * </PRE>
+ *
+ * <BR>
+ * Both the request and response values use the same encoded form, and they both
+ * use the same OID of "1.3.6.1.4.1.26027.1.6.1". The response value will only
+ * include get* elements. If the request did not include any operations, then
+ * the response will include all get* elements; otherwise, the response will
+ * only include the get* elements that correspond to the state fields referenced
+ * in the request (regardless of whether that operation was included in a get*,
+ * set*, add*, remove*, or clear* operation).
+ */
+public final class PasswordPolicyStateExtendedRequest
+    extends
+    AbstractExtendedRequest<PasswordPolicyStateExtendedRequest, PasswordPolicyStateExtendedResult>
+    implements PasswordPolicyStateOperationContainer
+{
+  private static final class MultiValueOperation implements
+      PasswordPolicyStateOperation
+  {
+    private final PasswordPolicyStateOperationType property;
+
+    private final List<ByteString> values;
+
+
+
+    private MultiValueOperation(
+        final PasswordPolicyStateOperationType property, final ByteString value)
+    {
+      this.property = property;
+      this.values = Collections.singletonList(value);
+    }
+
+
+
+    private MultiValueOperation(
+        final PasswordPolicyStateOperationType property,
+        final List<ByteString> values)
+    {
+      this.property = property;
+      this.values = values;
+    }
+
+
+
+    public PasswordPolicyStateOperationType getOperationType()
+    {
+      return property;
+    }
+
+
+
+    public Iterable<ByteString> getValues()
+    {
+      return values;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String toString()
+    {
+      return property.toString() + ": " + values;
+    }
+  }
+
+
+
+  private static final class RequestDecoder
+      implements
+      ExtendedRequestDecoder<PasswordPolicyStateExtendedRequest, PasswordPolicyStateExtendedResult>
+  {
+
+    public PasswordPolicyStateExtendedRequest decodeExtendedRequest(
+        final ExtendedRequest<?> request, final DecodeOptions options)
+        throws DecodeException
+    {
+      final ByteString requestValue = request.getValue();
+
+      if ((requestValue == null) || (requestValue.length() <= 0))
+      {
+        throw DecodeException.error(ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE.get());
+      }
+
+      try
+      {
+        final ASN1Reader reader = ASN1.getReader(requestValue);
+        reader.readStartSequence();
+
+        // Read the target user DN
+        final PasswordPolicyStateExtendedRequest newRequest =
+          new PasswordPolicyStateExtendedRequest(
+              reader.readOctetStringAsString());
+
+        decodeOperations(reader, newRequest);
+        reader.readEndSequence();
+
+        for (final Control control : request.getControls())
+        {
+          newRequest.addControl(control);
+        }
+
+        return newRequest;
+      }
+      catch (final IOException ioe)
+      {
+        final LocalizableMessage message = ERR_PWPSTATE_EXTOP_DECODE_FAILURE
+            .get(getExceptionMessage(ioe));
+        throw DecodeException.error(message, ioe);
+      }
+    }
+  }
+
+
+
+  private static final class ResultDecoder implements
+      ExtendedResultDecoder<PasswordPolicyStateExtendedResult>
+  {
+
+    /**
+     * {@inheritDoc}
+     */
+    public PasswordPolicyStateExtendedResult adaptExtendedErrorResult(
+        final ResultCode resultCode, final String matchedDN,
+        final String diagnosticMessage)
+    {
+      if (!resultCode.isExceptional())
+      {
+        // A successful response must contain a response name and
+        // value.
+        throw new IllegalArgumentException(
+            "No response name and value for result code "
+                + resultCode.intValue());
+      }
+
+      return new PasswordPolicyStateExtendedResult(resultCode, (String) null)
+          .setMatchedDN(matchedDN).setDiagnosticMessage(diagnosticMessage);
+    }
+
+
+
+    public PasswordPolicyStateExtendedResult decodeExtendedResult(
+        final ExtendedResult result, final DecodeOptions options)
+        throws DecodeException
+    {
+      final ResultCode resultCode = result.getResultCode();
+      final ByteString responseValue = result.getValue();
+
+      if (!resultCode.isExceptional()
+          && ((responseValue == null) || (responseValue.length() <= 0)))
+      {
+        throw DecodeException.error(ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE.get());
+      }
+
+      try
+      {
+        final ASN1Reader reader = ASN1.getReader(responseValue);
+        reader.readStartSequence();
+
+        // Read the target user DN
+        final PasswordPolicyStateExtendedResult newResult = new PasswordPolicyStateExtendedResult(
+            resultCode, reader.readOctetStringAsString()).setMatchedDN(
+            result.getMatchedDN()).setDiagnosticMessage(
+            result.getDiagnosticMessage());
+
+        decodeOperations(reader, newResult);
+        reader.readEndSequence();
+
+        for (final Control control : result.getControls())
+        {
+          newResult.addControl(control);
+        }
+
+        return newResult;
+      }
+      catch (final IOException ioe)
+      {
+        final LocalizableMessage message = ERR_PWPSTATE_EXTOP_DECODE_FAILURE
+            .get(getExceptionMessage(ioe));
+        throw DecodeException.error(message, ioe);
+      }
+    }
+  }
+
+
+
+  /**
+   * The OID for the password policy state extended operation (both the request
+   * and response types).
+   */
+  public static final String OID = "1.3.6.1.4.1.26027.1.6.1";
+
+  private final String targetUser;
+
+  private final List<PasswordPolicyStateOperation> operations =
+    new ArrayList<PasswordPolicyStateOperation>();
+
+  static final String PASSWORD_POLICY_DN_NAME = "Password Policy DN";
+
+  static final String ACCOUNT_DISABLED_STATE_NAME = "Account Disabled State";
+
+  static final String ACCOUNT_EXPIRATION_TIME_NAME = "Account Expiration Time";
+
+  static final String SECONDS_UNTIL_ACCOUNT_EXPIRATION_NAME =
+    "Seconds Until Account Expiration";
+
+  static final String PASSWORD_CHANGED_TIME_NAME = "Password Changed Time";
+
+  static final String PASSWORD_EXPIRATION_WARNED_TIME_NAME =
+    "Password Expiration Warned Time";
+
+  static final String SECONDS_UNTIL_PASSWORD_EXPIRATION_NAME =
+    "Seconds Until Password Expiration";
+
+  static final String SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING_NAME =
+    "Seconds Until Password Expiration Warning";
+
+  static final String AUTHENTICATION_FAILURE_TIMES_NAME =
+    "Authentication Failure Times";
+
+  static final String SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK_NAME =
+    "Seconds Until Authentication Failure Unlock";
+
+  static final String REMAINING_AUTHENTICATION_FAILURE_COUNT_NAME =
+    "Remaining Authentication Failure Count";
+
+  static final String LAST_LOGIN_TIME_NAME = "Last Login Time";
+
+  static final String SECONDS_UNTIL_IDLE_LOCKOUT_NAME =
+    "Seconds Until Idle Lockout";
+
+  static final String PASSWORD_RESET_STATE_NAME = "Password Reset State";
+
+  static final String SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT_NAME =
+    "Seconds Until Password Reset Lockout";
+
+  static final String GRACE_LOGIN_USE_TIMES_NAME = "Grace Login Use Times";
+
+  static final String REMAINING_GRACE_LOGIN_COUNT_NAME =
+    "Remaining Grace Login Count";
+
+  static final String PASSWORD_CHANGED_BY_REQUIRED_TIME_NAME =
+    "Password Changed By Required Time";
+
+  static final String SECONDS_UNTIL_REQUIRED_CHANGE_TIME_NAME =
+    "Seconds Until Required Change Time";
+
+  static final String PASSWORD_HISTORY_NAME = "Password History";
+
+  /**
+   * A decoder which can be used to decode password policy state extended
+   * operation requests.
+   */
+  public static final RequestDecoder REQUEST_DECODER = new RequestDecoder();
+
+  // No need to expose this.
+  private static final ResultDecoder RESULT_DECODER = new ResultDecoder();
+
+
+
+  static ByteString encode(final String targetUser,
+      final List<PasswordPolicyStateOperation> operations)
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder(6);
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+
+    try
+    {
+      writer.writeStartSequence();
+      writer.writeOctetString(targetUser);
+      if (!operations.isEmpty())
+      {
+        writer.writeStartSequence();
+        for (final PasswordPolicyStateOperation operation : operations)
+        {
+          writer.writeStartSequence();
+          writer.writeEnumerated(operation.getOperationType().ordinal());
+          if (operation.getValues() != null)
+          {
+            writer.writeStartSequence();
+            for (final ByteString value : operation.getValues())
+            {
+              writer.writeOctetString(value);
+            }
+            writer.writeEndSequence();
+          }
+          writer.writeEndSequence();
+        }
+        writer.writeEndSequence();
+      }
+      writer.writeEndSequence();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+
+    return buffer.toByteString();
+  }
+
+
+
+  private static void decodeOperations(final ASN1Reader reader,
+      final PasswordPolicyStateOperationContainer container)
+      throws IOException, DecodeException
+  {
+    // See if we have operations
+    if (reader.hasNextElement())
+    {
+      reader.readStartSequence();
+      int opType;
+      PasswordPolicyStateOperationType type;
+      while (reader.hasNextElement())
+      {
+        reader.readStartSequence();
+        // Read the opType
+        opType = reader.readEnumerated();
+        try
+        {
+          type = PasswordPolicyStateOperationType.values()[opType];
+        }
+        catch (final IndexOutOfBoundsException iobe)
+        {
+          throw DecodeException.error(ERR_PWPSTATE_EXTOP_UNKNOWN_OP_TYPE
+              .get(String.valueOf(opType)), iobe);
+        }
+
+        // See if we have any values
+        if (reader.hasNextElement())
+        {
+          reader.readStartSequence();
+          final ArrayList<ByteString> values = new ArrayList<ByteString>();
+          while (reader.hasNextElement())
+          {
+            values.add(reader.readOctetString());
+          }
+          reader.readEndSequence();
+          container.addOperation(new MultiValueOperation(type, values));
+        }
+        else
+        {
+          container.addOperation(type);
+        }
+        reader.readEndSequence();
+      }
+      reader.readEndSequence();
+    }
+  }
+
+
+
+  /**
+   * Creates a new password policy state extended request using the provided
+   * user name.
+   *
+   * @param targetUser
+   *          The name of the user.
+   */
+  public PasswordPolicyStateExtendedRequest(final DN targetUser)
+  {
+    Validator.ensureNotNull(targetUser);
+    this.targetUser = targetUser.toString();
+  }
+
+
+
+  /**
+   * Creates a new password policy state extended request using the provided
+   * user name.
+   *
+   * @param targetUser
+   *          The name of the user.
+   */
+  public PasswordPolicyStateExtendedRequest(final String targetUser)
+  {
+    Validator.ensureNotNull(targetUser);
+    this.targetUser = targetUser;
+  }
+
+
+
+  /**
+   * Adds the provided authentication failure time to this request.
+   *
+   * @param date
+   *          The authentication failure time.
+   */
+  public void addAuthenticationFailureTime(final Date date)
+  {
+    if (date == null)
+    {
+      operations
+          .add(PasswordPolicyStateOperationType.ADD_AUTHENTICATION_FAILURE_TIMES);
+    }
+    else
+    {
+      operations.add(new MultiValueOperation(
+          PasswordPolicyStateOperationType.ADD_AUTHENTICATION_FAILURE_TIMES,
+          ByteString.valueOf(formatAsGeneralizedTime(date))));
+    }
+  }
+
+
+
+  /**
+   * Adds the provided grace login use time to this request.
+   *
+   * @param date
+   *          The grace login use time.
+   */
+  public void addGraceLoginUseTime(final Date date)
+  {
+    if (date == null)
+    {
+      operations.add(PasswordPolicyStateOperationType.ADD_GRACE_LOGIN_USE_TIME);
+    }
+    else
+    {
+      operations.add(new MultiValueOperation(
+          PasswordPolicyStateOperationType.ADD_GRACE_LOGIN_USE_TIME, ByteString
+              .valueOf(formatAsGeneralizedTime(date))));
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void addOperation(final PasswordPolicyStateOperation operation)
+  {
+    operations.add(operation);
+  }
+
+
+
+  /**
+   * Clears the account disabled state.
+   */
+  public void clearAccountDisabledState()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.CLEAR_ACCOUNT_DISABLED_STATE);
+  }
+
+
+
+  /**
+   * Clears the account expiration time.
+   */
+  public void clearAccountExpirationTime()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.CLEAR_ACCOUNT_EXPIRATION_TIME);
+  }
+
+
+
+  /**
+   * Clears the authentication failure times.
+   */
+  public void clearAuthenticationFailureTimes()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.CLEAR_AUTHENTICATION_FAILURE_TIMES);
+  }
+
+
+
+  /**
+   * Clears the grace login use times.
+   */
+  public void clearGraceLoginUseTimes()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.CLEAR_GRACE_LOGIN_USE_TIMES);
+  }
+
+
+
+  /**
+   * Clears the last login time.
+   */
+  public void clearLastLoginTime()
+  {
+    operations.add(PasswordPolicyStateOperationType.CLEAR_LAST_LOGIN_TIME);
+  }
+
+
+
+  /**
+   * Clears the password changed by required time.
+   */
+  public void clearPasswordChangedByRequiredTime()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME);
+  }
+
+
+
+  /**
+   * Clears the password changed time.
+   */
+  public void clearPasswordChangedTime()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.CLEAR_PASSWORD_CHANGED_TIME);
+  }
+
+
+
+  /**
+   * Clears the password expiration warned time.
+   */
+  public void clearPasswordExpirationWarnedTime()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.CLEAR_PASSWORD_EXPIRATION_WARNED_TIME);
+  }
+
+
+
+  /**
+   * Clears the password history.
+   */
+  public void clearPasswordHistory()
+  {
+    operations.add(PasswordPolicyStateOperationType.CLEAR_PASSWORD_HISTORY);
+  }
+
+
+
+  /**
+   * Clears the password reset state.
+   */
+  public void clearPasswordResetState()
+  {
+    operations.add(PasswordPolicyStateOperationType.CLEAR_PASSWORD_RESET_STATE);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Iterable<PasswordPolicyStateOperation> getOperations()
+  {
+    return operations;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ExtendedResultDecoder<PasswordPolicyStateExtendedResult> getResultDecoder()
+  {
+    return RESULT_DECODER;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    return encode(targetUser, operations);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * Returns the account disabled state.
+   */
+  public void requestAccountDisabledState()
+  {
+    operations.add(PasswordPolicyStateOperationType.GET_ACCOUNT_DISABLED_STATE);
+  }
+
+
+
+  /**
+   * Returns the account expiration time.
+   */
+  public void requestAccountExpirationTime()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_ACCOUNT_EXPIRATION_TIME);
+  }
+
+
+
+  /**
+   * Returns the authentication failure times.
+   */
+  public void requestAuthenticationFailureTimes()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_AUTHENTICATION_FAILURE_TIMES);
+  }
+
+
+
+  /**
+   * Returns the grace login use times.
+   */
+  public void requestGraceLoginUseTimes()
+  {
+    operations.add(PasswordPolicyStateOperationType.GET_GRACE_LOGIN_USE_TIMES);
+  }
+
+
+
+  /**
+   * Returns the last login time.
+   */
+  public void requestLastLoginTime()
+  {
+    operations.add(PasswordPolicyStateOperationType.GET_LAST_LOGIN_TIME);
+  }
+
+
+
+  /**
+   * Returns the password changed by required time.
+   */
+  public void requestPasswordChangedByRequiredTime()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_PASSWORD_CHANGED_BY_REQUIRED_TIME);
+  }
+
+
+
+  /**
+   * Returns the password changed time.
+   */
+  public void requestPasswordChangedTime()
+  {
+    operations.add(PasswordPolicyStateOperationType.GET_PASSWORD_CHANGED_TIME);
+  }
+
+
+
+  /**
+   * Returns the password expiration warned time.
+   */
+  public void requestPasswordExpirationWarnedTime()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_PASSWORD_EXPIRATION_WARNED_TIME);
+  }
+
+
+
+  /**
+   * Returns the password history.
+   */
+  public void requestPasswordHistory()
+  {
+    operations.add(PasswordPolicyStateOperationType.GET_PASSWORD_HISTORY);
+  }
+
+
+
+  /**
+   * Returns the password policy DN.
+   */
+  public void requestPasswordPolicyDN()
+  {
+    operations.add(PasswordPolicyStateOperationType.GET_PASSWORD_POLICY_DN);
+  }
+
+
+
+  /**
+   * Returns the password reset state.
+   */
+  public void requestPasswordResetState()
+  {
+    operations.add(PasswordPolicyStateOperationType.GET_PASSWORD_RESET_STATE);
+  }
+
+
+
+  /**
+   * Returns the remaining authentication failure count.
+   */
+  public void requestRemainingAuthenticationFailureCount()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_REMAINING_AUTHENTICATION_FAILURE_COUNT);
+  }
+
+
+
+  /**
+   * Returns the remaining grace login count.
+   */
+  public void requestRemainingGraceLoginCount()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_REMAINING_GRACE_LOGIN_COUNT);
+  }
+
+
+
+  /**
+   * Returns the seconds until account expiration.
+   */
+  public void requestSecondsUntilAccountExpiration()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION);
+  }
+
+
+
+  /**
+   * Returns the seconds until authentication failure unlock.
+   */
+  public void requestSecondsUntilAuthenticationFailureUnlock()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK);
+  }
+
+
+
+  /**
+   * Returns the seconds until idle lockout.
+   */
+  public void requestSecondsUntilIdleLockout()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_IDLE_LOCKOUT);
+  }
+
+
+
+  /**
+   * Returns the seconds until password expiration.
+   */
+  public void requestSecondsUntilPasswordExpiration()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_PASSWORD_EXPIRATION);
+  }
+
+
+
+  /**
+   * Returns the seconds until password expiration warning.
+   */
+  public void requestSecondsUntilPasswordExpirationWarning()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING);
+  }
+
+
+
+  /**
+   * Returns the seconds until password reset lockout.
+   */
+  public void requestSecondsUntilPasswordResetLockout()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT);
+  }
+
+
+
+  /**
+   * Returns the seconds until required change time.
+   */
+  public void requestSecondsUntilRequiredChangeTime()
+  {
+    operations
+        .add(PasswordPolicyStateOperationType.GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME);
+  }
+
+
+
+  /**
+   * Sets the account disabled state.
+   *
+   * @param state
+   *          The account disabled state.
+   */
+  public void setAccountDisabledState(final boolean state)
+  {
+    operations.add(new MultiValueOperation(
+        PasswordPolicyStateOperationType.SET_ACCOUNT_DISABLED_STATE, ByteString
+            .valueOf(String.valueOf(state))));
+  }
+
+
+
+  /**
+   * Sets the account expiration time.
+   *
+   * @param date
+   *          The account expiration time.
+   */
+  public void setAccountExpirationTime(final Date date)
+  {
+    if (date == null)
+    {
+      operations
+          .add(PasswordPolicyStateOperationType.SET_ACCOUNT_EXPIRATION_TIME);
+    }
+    else
+    {
+      operations.add(new MultiValueOperation(
+          PasswordPolicyStateOperationType.SET_ACCOUNT_EXPIRATION_TIME,
+          ByteString.valueOf(formatAsGeneralizedTime(date))));
+    }
+  }
+
+
+
+  /**
+   * Sets the authentication failure times.
+   *
+   * @param dates
+   *          The authentication failure times.
+   */
+  public void setAuthenticationFailureTimes(final Date... dates)
+  {
+    if (dates == null)
+    {
+      operations
+          .add(PasswordPolicyStateOperationType.SET_AUTHENTICATION_FAILURE_TIMES);
+    }
+    else
+    {
+      final ArrayList<ByteString> times = new ArrayList<ByteString>(
+          dates.length);
+      for (final Date date : dates)
+      {
+        times.add(ByteString.valueOf(formatAsGeneralizedTime(date)));
+      }
+      operations.add(new MultiValueOperation(
+          PasswordPolicyStateOperationType.SET_AUTHENTICATION_FAILURE_TIMES,
+          times));
+    }
+  }
+
+
+
+  /**
+   * Sets the grace login use times.
+   *
+   * @param dates
+   *          The grace login use times.
+   */
+  public void setGraceLoginUseTimes(final Date... dates)
+  {
+    if (dates == null)
+    {
+      operations
+          .add(PasswordPolicyStateOperationType.SET_GRACE_LOGIN_USE_TIMES);
+    }
+    else
+    {
+      final ArrayList<ByteString> times = new ArrayList<ByteString>(
+          dates.length);
+      for (final Date date : dates)
+      {
+        times.add(ByteString.valueOf(formatAsGeneralizedTime(date)));
+      }
+      operations.add(new MultiValueOperation(
+          PasswordPolicyStateOperationType.SET_GRACE_LOGIN_USE_TIMES, times));
+    }
+  }
+
+
+
+  /**
+   * Sets the last login time.
+   *
+   * @param date
+   *          The last login time.
+   */
+  public void setLastLoginTime(final Date date)
+  {
+    if (date == null)
+    {
+      operations.add(PasswordPolicyStateOperationType.SET_LAST_LOGIN_TIME);
+
+    }
+    else
+    {
+      operations.add(new MultiValueOperation(
+          PasswordPolicyStateOperationType.SET_LAST_LOGIN_TIME, ByteString
+              .valueOf(formatAsGeneralizedTime(date))));
+    }
+  }
+
+
+
+  /**
+   * Sets the password changed by required time.
+   *
+   * @param state
+   *          The password changed by required time.
+   */
+  public void setPasswordChangedByRequiredTime(final boolean state)
+  {
+    operations.add(new MultiValueOperation(
+        PasswordPolicyStateOperationType.SET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
+        ByteString.valueOf(String.valueOf(state))));
+  }
+
+
+
+  /**
+   * Sets the password changed time.
+   *
+   * @param date
+   *          The password changed time.
+   */
+  public void setPasswordChangedTime(final Date date)
+  {
+    if (date == null)
+    {
+      operations
+          .add(PasswordPolicyStateOperationType.SET_PASSWORD_CHANGED_TIME);
+    }
+    else
+    {
+      operations.add(new MultiValueOperation(
+          PasswordPolicyStateOperationType.SET_PASSWORD_CHANGED_TIME,
+          ByteString.valueOf(formatAsGeneralizedTime(date))));
+    }
+  }
+
+
+
+  /**
+   * Sets the password expiration warned time.
+   *
+   * @param date
+   *          The password expiration warned time.
+   */
+  public void setPasswordExpirationWarnedTime(final Date date)
+  {
+    if (date == null)
+    {
+      operations
+          .add(PasswordPolicyStateOperationType.SET_PASSWORD_EXPIRATION_WARNED_TIME);
+
+    }
+    else
+    {
+      operations.add(new MultiValueOperation(
+          PasswordPolicyStateOperationType.SET_PASSWORD_EXPIRATION_WARNED_TIME,
+          ByteString.valueOf(formatAsGeneralizedTime(date))));
+    }
+  }
+
+
+
+  /**
+   * Sets the password reset state.
+   *
+   * @param state
+   *          The password reset state.
+   */
+  public void setPasswordResetState(final boolean state)
+  {
+    operations.add(new MultiValueOperation(
+        PasswordPolicyStateOperationType.SET_LAST_LOGIN_TIME, ByteString
+            .valueOf(String.valueOf(state))));
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PasswordPolicyStateExtendedRequest(requestName=");
+    builder.append(getOID());
+    builder.append(", targetUser=");
+    builder.append(targetUser);
+    builder.append(", operations=");
+    builder.append(operations);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedResult.java b/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedResult.java
new file mode 100644
index 0000000..2bb5f5f
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedResult.java
@@ -0,0 +1,171 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.extensions;
+
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DN;
+import org.opends.sdk.ResultCode;
+import org.opends.sdk.responses.AbstractExtendedResult;
+
+
+
+/**
+ * The password policy state extended result.
+ */
+public final class PasswordPolicyStateExtendedResult extends
+    AbstractExtendedResult<PasswordPolicyStateExtendedResult> implements
+    PasswordPolicyStateOperationContainer
+{
+  private final String targetUser;
+
+  private final List<PasswordPolicyStateOperation> operations =
+    new ArrayList<PasswordPolicyStateOperation>();
+
+
+
+  /**
+   * Creates a new password policy state extended result with the provided
+   * result code and target user.
+   *
+   * @param resultCode
+   *          The result code.
+   * @param targetUser
+   *          The user name.
+   */
+  public PasswordPolicyStateExtendedResult(final ResultCode resultCode,
+      final DN targetUser)
+  {
+    this(resultCode, String.valueOf(targetUser));
+  }
+
+
+
+  /**
+   * Creates a new password policy state extended result with the provided
+   * result code and target user.
+   *
+   * @param resultCode
+   *          The result code.
+   * @param targetUser
+   *          The user name.
+   */
+  public PasswordPolicyStateExtendedResult(final ResultCode resultCode,
+      final String targetUser)
+  {
+    super(resultCode);
+    this.targetUser = targetUser;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void addOperation(final PasswordPolicyStateOperation operation)
+  {
+    operations.add(operation);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    // No response name defined.
+    return PasswordPolicyStateExtendedRequest.OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Iterable<PasswordPolicyStateOperation> getOperations()
+  {
+    return operations;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    return PasswordPolicyStateExtendedRequest.encode(targetUser, operations);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PasswordPolicyStateExtendedResponse(resultCode=");
+    builder.append(getResultCode());
+    builder.append(", matchedDN=");
+    builder.append(getMatchedDN());
+    builder.append(", diagnosticMessage=");
+    builder.append(getDiagnosticMessage());
+    builder.append(", referrals=");
+    builder.append(getReferralURIs());
+    builder.append(", responseName=");
+    builder.append(getOID());
+    builder.append(", targetUser=");
+    builder.append(targetUser);
+    builder.append(", operations=");
+    builder.append(operations);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperation.java
similarity index 65%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperation.java
index 62b3ae3..0330aae 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperation.java
@@ -22,21 +22,35 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package com.sun.opends.sdk.extensions;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.opends.sdk.ByteString;
 
 
 
 /**
- * Password call-back.
+ * Password policy state operation.
  */
-public interface PasswordCallbackHandler
+public interface PasswordPolicyStateOperation
 {
-  public boolean handle(PasswordCallback callback);
+  /**
+   * Returns the type of operation.
+   *
+   * @return The type of operation.
+   */
+  PasswordPolicyStateOperationType getOperationType();
+
+
+
+  /**
+   * Returns the operation values.
+   *
+   * @return The operation values.
+   */
+  Iterable<ByteString> getValues();
 }
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationContainer.java
similarity index 63%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationContainer.java
index 62b3ae3..ddf8680 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationContainer.java
@@ -22,21 +22,32 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
-
-
-
-import javax.security.auth.callback.PasswordCallback;
+package com.sun.opends.sdk.extensions;
 
 
 
 /**
- * Password call-back.
+ * Password policy state operation container.
  */
-public interface PasswordCallbackHandler
+interface PasswordPolicyStateOperationContainer
 {
-  public boolean handle(PasswordCallback callback);
+  /**
+   * Adds an operation to this container.
+   *
+   * @param operation
+   *          The operation to be added.
+   */
+  void addOperation(PasswordPolicyStateOperation operation);
+
+
+
+  /**
+   * Returns the operations in this container.
+   *
+   * @return The operations in this container.
+   */
+  Iterable<PasswordPolicyStateOperation> getOperations();
 }
diff --git a/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationType.java b/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationType.java
new file mode 100644
index 0000000..0e3f17c
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationType.java
@@ -0,0 +1,323 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.extensions;
+
+
+
+import org.opends.sdk.ByteString;
+
+
+
+/**
+ * Password policy state operation type.
+ */
+public enum PasswordPolicyStateOperationType implements
+    PasswordPolicyStateOperation
+{
+  /**
+   * Get password policy DN operation.
+   */
+  GET_PASSWORD_POLICY_DN(
+      PasswordPolicyStateExtendedRequest.PASSWORD_POLICY_DN_NAME),
+
+  /**
+   * Get account disabled state operation.
+   */
+  GET_ACCOUNT_DISABLED_STATE(
+      PasswordPolicyStateExtendedRequest.ACCOUNT_DISABLED_STATE_NAME),
+
+  /**
+   * Set account disabled state operation.
+   */
+  SET_ACCOUNT_DISABLED_STATE(
+      PasswordPolicyStateExtendedRequest.ACCOUNT_DISABLED_STATE_NAME),
+
+  /**
+   * Clear account disabled state operation.
+   */
+  CLEAR_ACCOUNT_DISABLED_STATE(
+      PasswordPolicyStateExtendedRequest.ACCOUNT_DISABLED_STATE_NAME),
+
+  /**
+   * Get account expiration time operation.
+   */
+  GET_ACCOUNT_EXPIRATION_TIME(
+      PasswordPolicyStateExtendedRequest.ACCOUNT_EXPIRATION_TIME_NAME),
+
+  /**
+   * Set account expiration time operation.
+   */
+  SET_ACCOUNT_EXPIRATION_TIME(
+      PasswordPolicyStateExtendedRequest.ACCOUNT_EXPIRATION_TIME_NAME),
+
+  /**
+   * Clear account expiration time operation.
+   */
+  CLEAR_ACCOUNT_EXPIRATION_TIME(
+      PasswordPolicyStateExtendedRequest.ACCOUNT_EXPIRATION_TIME_NAME),
+
+  /**
+   * Get seconds until account expiration operation.
+   */
+  GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION(
+      PasswordPolicyStateExtendedRequest.SECONDS_UNTIL_ACCOUNT_EXPIRATION_NAME),
+
+  /**
+   * Get password changed time operation.
+   */
+  GET_PASSWORD_CHANGED_TIME(
+      PasswordPolicyStateExtendedRequest.PASSWORD_CHANGED_TIME_NAME),
+
+  /**
+   * Set password changed time operation.
+   */
+  SET_PASSWORD_CHANGED_TIME(
+      PasswordPolicyStateExtendedRequest.PASSWORD_CHANGED_TIME_NAME),
+
+  /**
+   * Clear password changed time operation.
+   */
+  CLEAR_PASSWORD_CHANGED_TIME(
+      PasswordPolicyStateExtendedRequest.PASSWORD_CHANGED_TIME_NAME),
+
+  /**
+   * Get password expiration warned time operation.
+   */
+  GET_PASSWORD_EXPIRATION_WARNED_TIME(
+      PasswordPolicyStateExtendedRequest.PASSWORD_EXPIRATION_WARNED_TIME_NAME),
+
+  /**
+   * Set password expiration warned time operation.
+   */
+  SET_PASSWORD_EXPIRATION_WARNED_TIME(
+      PasswordPolicyStateExtendedRequest.PASSWORD_EXPIRATION_WARNED_TIME_NAME),
+
+  /**
+   * Clear password expiration warned time operation.
+   */
+  CLEAR_PASSWORD_EXPIRATION_WARNED_TIME(
+      PasswordPolicyStateExtendedRequest.PASSWORD_EXPIRATION_WARNED_TIME_NAME),
+
+  /**
+   * Get seconds until password expiration operation.
+   */
+  GET_SECONDS_UNTIL_PASSWORD_EXPIRATION(
+      PasswordPolicyStateExtendedRequest.SECONDS_UNTIL_PASSWORD_EXPIRATION_NAME),
+
+  /**
+   * Get seconds until password expiration warning operation.
+   */
+  GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING(
+      PasswordPolicyStateExtendedRequest.SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING_NAME),
+
+  /**
+   * Get authentication failure times operation.
+   */
+  GET_AUTHENTICATION_FAILURE_TIMES(
+      PasswordPolicyStateExtendedRequest.AUTHENTICATION_FAILURE_TIMES_NAME),
+
+  /**
+   * Add authentication failure times operation.
+   */
+  ADD_AUTHENTICATION_FAILURE_TIMES(
+      PasswordPolicyStateExtendedRequest.AUTHENTICATION_FAILURE_TIMES_NAME),
+
+  /**
+   * Set authentication failure times operation.
+   */
+  SET_AUTHENTICATION_FAILURE_TIMES(
+      PasswordPolicyStateExtendedRequest.AUTHENTICATION_FAILURE_TIMES_NAME),
+
+  /**
+   * Clear authentication failure times operation.
+   */
+  CLEAR_AUTHENTICATION_FAILURE_TIMES(
+      PasswordPolicyStateExtendedRequest.AUTHENTICATION_FAILURE_TIMES_NAME),
+
+  /**
+   * Get seconds until authentication failure unlock operation.
+   */
+  GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK(
+      PasswordPolicyStateExtendedRequest.SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK_NAME),
+
+  /**
+   * Get remaining authentication failure count operation.
+   */
+  GET_REMAINING_AUTHENTICATION_FAILURE_COUNT(
+      PasswordPolicyStateExtendedRequest.REMAINING_AUTHENTICATION_FAILURE_COUNT_NAME),
+
+  /**
+   * Get last login time operation.
+   */
+  GET_LAST_LOGIN_TIME(PasswordPolicyStateExtendedRequest.LAST_LOGIN_TIME_NAME),
+
+  /**
+   * Set last login time operation.
+   */
+  SET_LAST_LOGIN_TIME(PasswordPolicyStateExtendedRequest.LAST_LOGIN_TIME_NAME),
+
+  /**
+   * Clear last login time operation.
+   */
+  CLEAR_LAST_LOGIN_TIME(PasswordPolicyStateExtendedRequest.LAST_LOGIN_TIME_NAME),
+
+  /**
+   * Get seconds until idle lockout operation.
+   */
+  GET_SECONDS_UNTIL_IDLE_LOCKOUT(
+      PasswordPolicyStateExtendedRequest.SECONDS_UNTIL_IDLE_LOCKOUT_NAME),
+
+  /**
+   * Get password reset state operation.
+   */
+  GET_PASSWORD_RESET_STATE(
+      PasswordPolicyStateExtendedRequest.PASSWORD_RESET_STATE_NAME),
+
+  /**
+   * Set password reset state operation.
+   */
+  SET_PASSWORD_RESET_STATE(
+      PasswordPolicyStateExtendedRequest.PASSWORD_RESET_STATE_NAME),
+
+  /**
+   * Clear password reset state operation.
+   */
+  CLEAR_PASSWORD_RESET_STATE(
+      PasswordPolicyStateExtendedRequest.PASSWORD_RESET_STATE_NAME),
+
+  /**
+   * Get seconds until password reset lockout operation.
+   */
+  GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT(
+      PasswordPolicyStateExtendedRequest.SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT_NAME),
+
+  /**
+   * Get grace login use times operation.
+   */
+  GET_GRACE_LOGIN_USE_TIMES(
+      PasswordPolicyStateExtendedRequest.GRACE_LOGIN_USE_TIMES_NAME),
+
+  /**
+   * Add grace login use times operation.
+   */
+  ADD_GRACE_LOGIN_USE_TIME(
+      PasswordPolicyStateExtendedRequest.GRACE_LOGIN_USE_TIMES_NAME),
+
+  /**
+   * Set grace login use times operation.
+   */
+  SET_GRACE_LOGIN_USE_TIMES(
+      PasswordPolicyStateExtendedRequest.GRACE_LOGIN_USE_TIMES_NAME),
+
+  /**
+   * Clear grace login use times operation.
+   */
+  CLEAR_GRACE_LOGIN_USE_TIMES(
+      PasswordPolicyStateExtendedRequest.GRACE_LOGIN_USE_TIMES_NAME),
+
+  /**
+   * Get remaining grace login count operation.
+   */
+  GET_REMAINING_GRACE_LOGIN_COUNT(
+      PasswordPolicyStateExtendedRequest.REMAINING_GRACE_LOGIN_COUNT_NAME),
+
+  /**
+   * Get password changed by required time operation.
+   */
+  GET_PASSWORD_CHANGED_BY_REQUIRED_TIME(
+      PasswordPolicyStateExtendedRequest.PASSWORD_CHANGED_BY_REQUIRED_TIME_NAME),
+
+  /**
+   * Set password changed by required time operation.
+   */
+  SET_PASSWORD_CHANGED_BY_REQUIRED_TIME(
+      PasswordPolicyStateExtendedRequest.PASSWORD_CHANGED_BY_REQUIRED_TIME_NAME),
+
+  /**
+   * Clear password changed by required time operation.
+   */
+  CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME(
+      PasswordPolicyStateExtendedRequest.PASSWORD_CHANGED_BY_REQUIRED_TIME_NAME),
+
+  /**
+   * Get seconds until required change time operation.
+   */
+  GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME(
+      PasswordPolicyStateExtendedRequest.SECONDS_UNTIL_REQUIRED_CHANGE_TIME_NAME),
+
+  /**
+   * Get password history operation.
+   */
+  GET_PASSWORD_HISTORY(PasswordPolicyStateExtendedRequest.PASSWORD_HISTORY_NAME),
+
+  /**
+   * Clear password history operation.
+   */
+  CLEAR_PASSWORD_HISTORY(
+      PasswordPolicyStateExtendedRequest.PASSWORD_HISTORY_NAME);
+
+  private String propertyName;
+
+
+
+  private PasswordPolicyStateOperationType(final String propertyName)
+  {
+    this.propertyName = propertyName;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PasswordPolicyStateOperationType getOperationType()
+  {
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Iterable<ByteString> getValues()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    return propertyName;
+  }
+}
diff --git a/sdk/src/org/opends/sdk/sasl/package-info.java b/sdk/src/com/sun/opends/sdk/extensions/package-info.java
old mode 100755
new mode 100644
similarity index 89%
copy from sdk/src/org/opends/sdk/sasl/package-info.java
copy to sdk/src/com/sun/opends/sdk/extensions/package-info.java
index 6683fa9..750dd41
--- a/sdk/src/org/opends/sdk/sasl/package-info.java
+++ b/sdk/src/com/sun/opends/sdk/extensions/package-info.java
@@ -26,6 +26,9 @@
  */
 
 /**
- * Classes and interfaces for common LDAP SASL Bind requests.
+ * Classes implementing Sun proprietary LDAP extended operations.
  */
-package org.opends.sdk.sasl;
+package com.sun.opends.sdk.extensions;
+
+
+
diff --git a/sdk/src/com/sun/opends/sdk/ldap/ASN1StreamReader.java b/sdk/src/com/sun/opends/sdk/ldap/ASN1BufferReader.java
similarity index 71%
rename from sdk/src/com/sun/opends/sdk/ldap/ASN1StreamReader.java
rename to sdk/src/com/sun/opends/sdk/ldap/ASN1BufferReader.java
index d6ab025..156c288 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/ASN1StreamReader.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/ASN1BufferReader.java
@@ -22,17 +22,20 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
+
 package com.sun.opends.sdk.ldap;
 
 
 
+import static com.sun.opends.sdk.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES;
+import static com.sun.opends.sdk.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
+import static com.sun.opends.sdk.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_TYPE;
+import static com.sun.opends.sdk.ldap.LDAPConstants.ELEMENT_READ_STATE_NEED_VALUE_BYTES;
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.ldap.LDAPConstants.*;
 
 import java.io.IOException;
-import java.nio.BufferUnderflowException;
 import java.util.logging.Level;
 
 import org.opends.sdk.ByteString;
@@ -42,8 +45,9 @@
 import org.opends.sdk.asn1.ASN1Reader;
 import org.opends.sdk.asn1.AbstractASN1Reader;
 
-import com.sun.grizzly.streams.StreamReader;
-import com.sun.grizzly.utils.PoolableObject;
+import com.sun.grizzly.Buffer;
+import com.sun.grizzly.memory.ByteBuffersBuffer;
+import com.sun.grizzly.memory.CompositeBuffer;
 import com.sun.opends.sdk.util.StaticUtils;
 
 
@@ -51,10 +55,9 @@
 /**
  * Grizzly ASN1 reader implementation.
  */
-public final class ASN1StreamReader extends AbstractASN1Reader implements
-    PoolableObject, ASN1Reader
+final class ASN1BufferReader extends AbstractASN1Reader implements ASN1Reader
 {
-  class ChildSequenceLimiter implements SequenceLimiter
+  private final class ChildSequenceLimiter implements SequenceLimiter
   {
     private SequenceLimiter parent;
 
@@ -66,12 +69,12 @@
 
 
 
-    public void checkLimit(int readSize) throws IOException,
-        BufferUnderflowException
+    public void checkLimit(final int readSize) throws IOException
     {
       if ((readLimit > 0) && (bytesRead + readSize > readLimit))
       {
-        throw new BufferUnderflowException();
+        final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTE.get();
+        throw DecodeException.fatalError(message);
       }
 
       parent.checkLimit(readSize);
@@ -85,17 +88,17 @@
     {
       parent.checkLimit(remaining());
 
-      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE)
-          && remaining() > 0)
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE) && remaining() > 0)
       {
-        StaticUtils.DEBUG_LOG.fine(String.format(
-            "Ignoring %d unused trailing bytes in ASN.1 SEQUENCE",
-            remaining()));
+        StaticUtils.DEBUG_LOG
+            .fine(String.format(
+                "Ignoring %d unused trailing bytes in ASN.1 SEQUENCE",
+                remaining()));
       }
 
       for (int i = 0; i < remaining(); i++)
       {
-        streamReader.readByte();
+        buffer.get();
       }
 
       return parent;
@@ -110,7 +113,7 @@
 
 
 
-    public ChildSequenceLimiter startSequence(int readLimit)
+    public ChildSequenceLimiter startSequence(final int readLimit)
     {
       if (child == null)
       {
@@ -127,21 +130,27 @@
 
 
 
-  class RootSequenceLimiter implements SequenceLimiter
+  private final class RootSequenceLimiter implements SequenceLimiter
   {
     private ChildSequenceLimiter child;
 
 
 
-    public void checkLimit(int readSize)
+    public void checkLimit(final int readSize) throws IOException
     {
+      if (buffer.remaining() < readSize)
+      {
+        final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTE.get();
+        throw DecodeException.fatalError(message);
+      }
     }
 
 
 
     public ChildSequenceLimiter endSequence() throws DecodeException
     {
-      LocalizableMessage message = ERR_ASN1_SEQUENCE_READ_NOT_STARTED.get();
+      final LocalizableMessage message = ERR_ASN1_SEQUENCE_READ_NOT_STARTED
+          .get();
       throw new IllegalStateException(message.toString());
     }
 
@@ -149,12 +158,12 @@
 
     public int remaining()
     {
-      return streamReader.availableDataSize();
+      return buffer.remaining();
     }
 
 
 
-    public ChildSequenceLimiter startSequence(int readLimit)
+    public ChildSequenceLimiter startSequence(final int readLimit)
     {
       if (child == null)
       {
@@ -173,8 +182,7 @@
 
   private interface SequenceLimiter
   {
-    public void checkLimit(int readSize) throws IOException,
-        BufferUnderflowException;
+    public void checkLimit(int readSize) throws IOException;
 
 
 
@@ -203,29 +211,28 @@
 
   private final int maxElementSize;
 
-  private StreamReader streamReader;
-
-  private final RootSequenceLimiter rootLimiter;
+  private final CompositeBuffer buffer;
 
   private SequenceLimiter readLimiter;
 
-  private final byte[] buffer;
+  private final byte[] stringBuffer;
 
 
 
   /**
-   * Creates a new ASN1 reader whose source is the provided input stream
-   * and having a user defined maximum BER element size.
+   * Creates a new ASN1 reader whose source is the provided input stream and
+   * having a user defined maximum BER element size.
    *
    * @param maxElementSize
-   *          The maximum BER element size, or <code>0</code> to
-   *          indicate that there is no limit.
+   *          The maximum BER element size, or <code>0</code> to indicate that
+   *          there is no limit.
    */
-  public ASN1StreamReader(int maxElementSize)
+  ASN1BufferReader(final int maxElementSize)
   {
-    this.readLimiter = this.rootLimiter = new RootSequenceLimiter();
-    this.buffer = new byte[MAX_STRING_BUFFER_SIZE];
+    this.readLimiter = new RootSequenceLimiter();
+    this.stringBuffer = new byte[MAX_STRING_BUFFER_SIZE];
     this.maxElementSize = maxElementSize;
+    this.buffer = ByteBuffersBuffer.create();
   }
 
 
@@ -238,55 +245,45 @@
    */
   public void close() throws IOException
   {
-    // close the stream reader.
-    streamReader.close();
+    buffer.dispose();
   }
 
 
 
   /**
-   * Determines if a complete ASN.1 element is ready to be read from the
-   * stream reader.
+   * Determines if a complete ASN.1 element is ready to be read from the stream
+   * reader.
    *
-   * @return <code>true</code> if another complete element is available
-   *         or <code>false</code> otherwise.
+   * @return <code>true</code> if another complete element is available or
+   *         <code>false</code> otherwise.
    * @throws IOException
-   *           If an error occurs while trying to decode an ASN1
-   *           element.
+   *           If an error occurs while trying to decode an ASN1 element.
    */
   public boolean elementAvailable() throws IOException
   {
-    if ((state == ELEMENT_READ_STATE_NEED_TYPE) && !needTypeState(true))
-    {
-      return false;
-    }
-    if ((state == ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE)
-        && !needFirstLengthByteState(true))
-    {
-      return false;
-    }
-    return !((state == ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES)
-        && !needAdditionalLengthBytesState(true)) &&
-        peekLength <= readLimiter.remaining();
+    return !((state == ELEMENT_READ_STATE_NEED_TYPE) && !needTypeState(true))
+        && !((state == ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE)
+            && !needFirstLengthByteState(true))
+        && !((state == ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES)
+            && !needAdditionalLengthBytesState(true))
+        && peekLength <= readLimiter.remaining();
 
   }
 
 
 
   /**
-   * Determines if the input stream contains at least one ASN.1 element
-   * to be read.
+   * Determines if the input stream contains at least one ASN.1 element to be
+   * read.
    *
    * @return <code>true</code> if another element is available or
    *         <code>false</code> otherwise.
    * @throws IOException
-   *           If an error occurs while trying to decode an ASN1
-   *           element.
+   *           If an error occurs while trying to decode an ASN1 element.
    */
   public boolean hasNextElement() throws IOException
   {
-    return (state != ELEMENT_READ_STATE_NEED_TYPE)
-        || needTypeState(true);
+    return (state != ELEMENT_READ_STATE_NEED_TYPE) || needTypeState(true);
   }
 
 
@@ -328,13 +325,6 @@
 
 
 
-  public void prepare()
-  {
-    // Nothing to do
-  }
-
-
-
   /**
    * {@inheritDoc}
    */
@@ -345,18 +335,19 @@
 
     if (peekLength != 1)
     {
-      LocalizableMessage message = ERR_ASN1_BOOLEAN_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_BOOLEAN_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
     readLimiter.checkLimit(peekLength);
-    byte readByte = streamReader.readByte();
+    final byte readByte = buffer.get();
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)",
-          peekType, peekLength, String.valueOf(readByte != 0x00)));
+          "READ ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)", peekType,
+          peekLength, String.valueOf(readByte != 0x00)));
     }
 
     state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -368,15 +359,13 @@
   /**
    * {@inheritDoc}
    */
-  public void readEndSequence() throws IOException,
-      IllegalStateException
+  public void readEndSequence() throws IOException, IllegalStateException
   {
     readLimiter = readLimiter.endSequence();
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String
-          .format("READ ASN.1 END SEQUENCE"));
+      StaticUtils.DEBUG_LOG.finest(String.format("READ ASN.1 END SEQUENCE"));
     }
 
     // Reset the state
@@ -407,7 +396,8 @@
 
     if ((peekLength < 1) || (peekLength > 4))
     {
-      LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
@@ -428,7 +418,8 @@
 
     if ((peekLength < 1) || (peekLength > 8))
     {
-      LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
@@ -438,7 +429,7 @@
       long longValue = 0;
       for (int i = 0; i < peekLength; i++)
       {
-        int readByte = streamReader.readByte();
+        final int readByte = buffer.get();
         if ((i == 0) && (((byte) readByte) < 0))
         {
           longValue = 0xFFFFFFFFFFFFFFFFL;
@@ -454,7 +445,7 @@
       int intValue = 0;
       for (int i = 0; i < peekLength; i++)
       {
-        int readByte = streamReader.readByte();
+        final int readByte = buffer.get();
         if ((i == 0) && (((byte) readByte) < 0))
         {
           intValue = 0xFFFFFFFF;
@@ -465,8 +456,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "READ ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            peekType, peekLength, intValue));
+            "READ ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", peekType,
+            peekLength, intValue));
       }
 
       state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -487,15 +478,15 @@
     // Make sure that the decoded length is exactly zero byte.
     if (peekLength != 0)
     {
-      LocalizableMessage message = ERR_ASN1_NULL_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_NULL_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String
-          .format("READ ASN.1 NULL(type=0x%x, length=%d)", peekType,
-              peekLength));
+      StaticUtils.DEBUG_LOG.finest(String.format(
+          "READ ASN.1 NULL(type=0x%x, length=%d)", peekType, peekLength));
     }
 
     state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -519,14 +510,14 @@
 
     readLimiter.checkLimit(peekLength);
     // Copy the value and construct the element to return.
-    byte[] value = new byte[peekLength];
-    streamReader.readByteArray(value);
+    final byte[] value = new byte[peekLength];
+    buffer.get(value);
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 OCTETSTRING(type=0x%x, length=%d)", peekType,
-          peekLength));
+      StaticUtils.DEBUG_LOG
+          .finest(String.format("READ ASN.1 OCTETSTRING(type=0x%x, length=%d)",
+              peekType, peekLength));
     }
 
     state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -538,7 +529,7 @@
   /**
    * {@inheritDoc}
    */
-  public ByteStringBuilder readOctetString(ByteStringBuilder builder)
+  public ByteStringBuilder readOctetString(final ByteStringBuilder builder)
       throws IOException
   {
     // Read the header if haven't done so already
@@ -555,14 +546,14 @@
     // TODO: Is there a more efficient way to do this?
     for (int i = 0; i < peekLength; i++)
     {
-      builder.append(streamReader.readByte());
+      builder.append(buffer.get());
     }
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 OCTETSTRING(type=0x%x, length=%d)", peekType,
-          peekLength));
+      StaticUtils.DEBUG_LOG
+          .finest(String.format("READ ASN.1 OCTETSTRING(type=0x%x, length=%d)",
+              peekType, peekLength));
     }
 
     state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -586,9 +577,9 @@
     }
 
     byte[] readBuffer;
-    if (peekLength <= buffer.length)
+    if (peekLength <= stringBuffer.length)
     {
-      readBuffer = buffer;
+      readBuffer = stringBuffer;
     }
     else
     {
@@ -596,7 +587,7 @@
     }
 
     readLimiter.checkLimit(peekLength);
-    streamReader.readByteArray(readBuffer, 0, peekLength);
+    buffer.get(readBuffer, 0, peekLength);
 
     state = ELEMENT_READ_STATE_NEED_TYPE;
 
@@ -605,7 +596,7 @@
     {
       str = new String(readBuffer, 0, peekLength, "UTF-8");
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
       {
@@ -614,14 +605,14 @@
                 + e.toString());
       }
 
-      str = new String(buffer, 0, peekLength);
+      str = new String(stringBuffer, 0, peekLength);
     }
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 OCTETSTRING(type=0x%x, length=%d, value=%s)",
-          peekType, peekLength, str));
+          "READ ASN.1 OCTETSTRING(type=0x%x, length=%d, value=%s)", peekType,
+          peekLength, str));
     }
 
     return str;
@@ -664,24 +655,6 @@
 
 
 
-  public void release()
-  {
-    streamReader = null;
-    peekLength = -1;
-    peekType = 0;
-    readLimiter = rootLimiter;
-    state = ELEMENT_READ_STATE_NEED_TYPE;
-  }
-
-
-
-  public void setStreamReader(StreamReader streamReader)
-  {
-    this.streamReader = streamReader;
-  }
-
-
-
   /**
    * {@inheritDoc}
    */
@@ -693,7 +666,7 @@
     readLimiter.checkLimit(peekLength);
     for (int i = 0; i < peekLength; i++)
     {
-      streamReader.readByte();
+      buffer.get();
     }
     state = ELEMENT_READ_STATE_NEED_TYPE;
     return this;
@@ -701,18 +674,31 @@
 
 
 
+  void appendBytesRead(final Buffer buffer)
+  {
+    this.buffer.append(buffer);
+  }
+
+
+
+  void disposeBytesRead()
+  {
+    this.buffer.disposeUnused();
+  }
+
+
+
   /**
-   * Internal helper method reading the additional ASN.1 length bytes
-   * and transition to the next state if successful.
+   * Internal helper method reading the additional ASN.1 length bytes and
+   * transition to the next state if successful.
    *
    * @param ensureRead
    *          <code>true</code> to check for availability first.
-   * @return <code>true</code> if the length bytes was successfully
-   *         read.
+   * @return <code>true</code> if the length bytes was successfully read.
    * @throws IOException
    *           If an error occurs while reading from the stream.
    */
-  private boolean needAdditionalLengthBytesState(boolean ensureRead)
+  private boolean needAdditionalLengthBytesState(final boolean ensureRead)
       throws IOException
   {
     if (ensureRead && (readLimiter.remaining() < lengthBytesNeeded))
@@ -724,7 +710,7 @@
     readLimiter.checkLimit(lengthBytesNeeded);
     while (lengthBytesNeeded > 0)
     {
-      readByte = streamReader.readByte();
+      readByte = buffer.get();
       peekLength = (peekLength << 8) | (readByte & 0xFF);
       lengthBytesNeeded--;
     }
@@ -733,8 +719,8 @@
     // message size.
     if ((maxElementSize > 0) && (peekLength > maxElementSize))
     {
-      LocalizableMessage m = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED.get(
-          peekLength, maxElementSize);
+      final LocalizableMessage m = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
+          .get(peekLength, maxElementSize);
       throw DecodeException.fatalError(m);
     }
     state = ELEMENT_READ_STATE_NEED_VALUE_BYTES;
@@ -744,17 +730,16 @@
 
 
   /**
-   * Internal helper method reading the first length bytes and
-   * transition to the next state if successful.
+   * Internal helper method reading the first length bytes and transition to the
+   * next state if successful.
    *
    * @param ensureRead
    *          <code>true</code> to check for availability first.
    * @return <code>true</code> if the length bytes was successfully read
    * @throws IOException
-   *           If an error occurs while trying to decode an ASN1
-   *           element.
+   *           If an error occurs while trying to decode an ASN1 element.
    */
-  private boolean needFirstLengthByteState(boolean ensureRead)
+  private boolean needFirstLengthByteState(final boolean ensureRead)
       throws IOException
   {
     if (ensureRead && (readLimiter.remaining() <= 0))
@@ -763,14 +748,14 @@
     }
 
     readLimiter.checkLimit(1);
-    byte readByte = streamReader.readByte();
+    byte readByte = buffer.get();
     peekLength = (readByte & 0x7F);
     if (peekLength != readByte)
     {
       lengthBytesNeeded = peekLength;
       if (lengthBytesNeeded > 4)
       {
-        LocalizableMessage message = ERR_ASN1_INVALID_NUM_LENGTH_BYTES
+        final LocalizableMessage message = ERR_ASN1_INVALID_NUM_LENGTH_BYTES
             .get(lengthBytesNeeded);
         throw DecodeException.fatalError(message);
       }
@@ -785,7 +770,7 @@
       readLimiter.checkLimit(lengthBytesNeeded);
       while (lengthBytesNeeded > 0)
       {
-        readByte = streamReader.readByte();
+        readByte = buffer.get();
         peekLength = (peekLength << 8) | (readByte & 0xFF);
         lengthBytesNeeded--;
       }
@@ -795,8 +780,8 @@
     // message size.
     if ((maxElementSize > 0) && (peekLength > maxElementSize))
     {
-      LocalizableMessage m = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED.get(
-          peekLength, maxElementSize);
+      final LocalizableMessage m = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
+          .get(peekLength, maxElementSize);
       throw DecodeException.fatalError(m);
     }
     state = ELEMENT_READ_STATE_NEED_VALUE_BYTES;
@@ -806,17 +791,16 @@
 
 
   /**
-   * Internal helper method reading the ASN.1 type byte and transition
-   * to the next state if successful.
+   * Internal helper method reading the ASN.1 type byte and transition to the
+   * next state if successful.
    *
    * @param ensureRead
    *          <code>true</code> to check for availability first.
    * @return <code>true</code> if the type byte was successfully read
    * @throws IOException
-   *           If an error occurs while trying to decode an ASN1
-   *           element.
+   *           If an error occurs while trying to decode an ASN1 element.
    */
-  private boolean needTypeState(boolean ensureRead) throws IOException
+  private boolean needTypeState(final boolean ensureRead) throws IOException
   {
     // Read just the type.
     if (ensureRead && (readLimiter.remaining() <= 0))
@@ -825,7 +809,7 @@
     }
 
     readLimiter.checkLimit(1);
-    peekType = streamReader.readByte();
+    peekType = buffer.get();
     state = ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
     return true;
   }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/ASN1StreamWriter.java b/sdk/src/com/sun/opends/sdk/ldap/ASN1BufferWriter.java
similarity index 75%
rename from sdk/src/com/sun/opends/sdk/ldap/ASN1StreamWriter.java
rename to sdk/src/com/sun/opends/sdk/ldap/ASN1BufferWriter.java
index d9925bd..fcb4096 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/ASN1StreamWriter.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/ASN1BufferWriter.java
@@ -22,16 +22,18 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 package com.sun.opends.sdk.ldap;
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.asn1.ASN1Constants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED;
+import static org.opends.sdk.asn1.ASN1Constants.BOOLEAN_VALUE_FALSE;
+import static org.opends.sdk.asn1.ASN1Constants.BOOLEAN_VALUE_TRUE;
 
 import java.io.IOException;
+import java.nio.ByteBuffer;
 import java.util.logging.Level;
 
 import org.opends.sdk.ByteSequence;
@@ -40,8 +42,10 @@
 import org.opends.sdk.asn1.ASN1Writer;
 import org.opends.sdk.asn1.AbstractASN1Writer;
 
-import com.sun.grizzly.streams.StreamWriter;
-import com.sun.grizzly.utils.PoolableObject;
+import com.sun.grizzly.Buffer;
+import com.sun.grizzly.Cacheable;
+import com.sun.grizzly.ThreadCache;
+import com.sun.grizzly.memory.ByteBufferWrapper;
 import com.sun.opends.sdk.util.StaticUtils;
 
 
@@ -49,8 +53,8 @@
 /**
  * Grizzly ASN1 writer implementation.
  */
-public final class ASN1StreamWriter extends AbstractASN1Writer implements
-    ASN1Writer, PoolableObject
+final class ASN1BufferWriter extends AbstractASN1Writer implements ASN1Writer,
+    Cacheable
 {
   private class ChildSequenceBuffer implements SequenceBuffer
   {
@@ -59,15 +63,14 @@
     private ChildSequenceBuffer child;
 
     private final ByteStringBuilder buffer = new ByteStringBuilder(
-        SUB_SEQUENCE_BUFFER_INIT_SIZE);
+        BUFFER_INIT_SIZE);
 
 
 
     public SequenceBuffer endSequence() throws IOException
     {
       writeLength(parent, buffer.length());
-      parent.writeByteArray(buffer.getBackingArray(), 0, buffer
-          .length());
+      parent.writeByteArray(buffer.getBackingArray(), 0, buffer.length());
 
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
@@ -80,7 +83,7 @@
 
 
 
-    public SequenceBuffer startSequence(byte type) throws IOException
+    public SequenceBuffer startSequence(final byte type) throws IOException
     {
       if (child == null)
       {
@@ -96,15 +99,15 @@
 
 
 
-    public void writeByte(byte b) throws IOException
+    public void writeByte(final byte b) throws IOException
     {
       buffer.append(b);
     }
 
 
 
-    public void writeByteArray(byte[] bs, int offset, int length)
-        throws IOException
+    public void writeByteArray(final byte[] bs, final int offset,
+        final int length) throws IOException
     {
       buffer.append(bs, offset, length);
     }
@@ -112,6 +115,59 @@
 
 
 
+  private static final class RecyclableBuffer extends ByteBufferWrapper
+  {
+    private volatile boolean usable = true;
+
+
+
+    private RecyclableBuffer()
+    {
+      visible = ByteBuffer.allocate(BUFFER_INIT_SIZE);
+      allowBufferDispose = true;
+    }
+
+
+
+    @Override
+    public void dispose()
+    {
+      usable = true;
+    }
+
+
+
+    /**
+     * Ensures that the specified number of additional bytes will fit in the
+     * buffer and resizes it if necessary.
+     *
+     * @param size
+     *          The number of additional bytes.
+     */
+    public void ensureAdditionalCapacity(final int size)
+    {
+      final int newCount = visible.position() + size;
+      if (newCount > visible.capacity())
+      {
+        final ByteBuffer newByteBuffer = ByteBuffer.allocate(Math.max(visible
+            .capacity() << 1, newCount));
+        visible.flip();
+        visible = newByteBuffer.put(visible);
+      }
+    }
+
+
+
+    @Override
+    public ByteBufferWrapper flip()
+    {
+      usable = false;
+      return super.flip();
+    }
+  }
+
+
+
   private class RootSequenceBuffer implements SequenceBuffer
   {
     private ChildSequenceBuffer child;
@@ -120,13 +176,14 @@
 
     public SequenceBuffer endSequence() throws IOException
     {
-      LocalizableMessage message = ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED.get();
+      final LocalizableMessage message = ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED
+          .get();
       throw new IllegalStateException(message.toString());
     }
 
 
 
-    public SequenceBuffer startSequence(byte type) throws IOException
+    public SequenceBuffer startSequence(final byte type) throws IOException
     {
       if (child == null)
       {
@@ -134,7 +191,8 @@
         child.parent = this;
       }
 
-      streamWriter.writeByte(type);
+      outBuffer.ensureAdditionalCapacity(1);
+      outBuffer.put(type);
       child.buffer.clear();
 
       return child;
@@ -142,17 +200,19 @@
 
 
 
-    public void writeByte(byte b) throws IOException
+    public void writeByte(final byte b) throws IOException
     {
-      streamWriter.writeByte(b);
+      outBuffer.ensureAdditionalCapacity(1);
+      outBuffer.put(b);
     }
 
 
 
-    public void writeByteArray(byte[] bs, int offset, int length)
-        throws IOException
+    public void writeByteArray(final byte[] bs, final int offset,
+        final int length) throws IOException
     {
-      streamWriter.writeByteArray(bs, offset, length);
+      outBuffer.ensureAdditionalCapacity(length);
+      outBuffer.put(bs, offset, length);
     }
   }
 
@@ -178,11 +238,33 @@
 
 
 
-  private static final int SUB_SEQUENCE_BUFFER_INIT_SIZE = 1024;
+  private static final int BUFFER_INIT_SIZE = 1024;
+  private final static ThreadCache.CachedTypeIndex<ASN1BufferWriter> WRITER_INDEX = ThreadCache
+      .obtainIndex(ASN1BufferWriter.class, 1);
 
-  private StreamWriter streamWriter;
+
+
+  static ASN1BufferWriter getWriter()
+  {
+    ASN1BufferWriter asn1Writer = ThreadCache.takeFromCache(WRITER_INDEX);
+    if (asn1Writer == null)
+    {
+      asn1Writer = new ASN1BufferWriter();
+    }
+
+    if (!asn1Writer.outBuffer.usable)
+    {
+      // If the output buffer is unusable, create a new one.
+      asn1Writer.outBuffer = new RecyclableBuffer();
+    }
+    asn1Writer.outBuffer.clear();
+    return asn1Writer;
+  }
+
+
 
   private SequenceBuffer sequenceBuffer;
+  private RecyclableBuffer outBuffer;
 
   private final RootSequenceBuffer rootBuffer;
 
@@ -191,23 +273,24 @@
   /**
    * Creates a new ASN.1 writer that writes to a StreamWriter.
    */
-  public ASN1StreamWriter()
+  private ASN1BufferWriter()
   {
     this.sequenceBuffer = this.rootBuffer = new RootSequenceBuffer();
+    this.outBuffer = new RecyclableBuffer();
   }
 
 
 
   /**
-   * Closes this ASN.1 writer and the underlying outputstream. Any
-   * unfinished sequences will be ended.
+   * Closes this ASN.1 writer and the underlying outputstream. Any unfinished
+   * sequences will be ended.
    *
    * @throws IOException
    *           if an error occurs while closing the stream.
    */
   public void close() throws IOException
   {
-    streamWriter.close();
+    outBuffer = null;
   }
 
 
@@ -220,29 +303,16 @@
    */
   public void flush() throws IOException
   {
-    streamWriter.flush();
+    // Do nothing
   }
 
 
 
-  public void prepare()
+  public void recycle()
   {
-    // nothing to do
-  }
-
-
-
-  public void release()
-  {
-    streamWriter = null;
     sequenceBuffer = rootBuffer;
-  }
-
-
-
-  public void setStreamWriter(StreamWriter streamWriter)
-  {
-    this.streamWriter = streamWriter;
+    outBuffer.clear();
+    ThreadCache.putToCache(WRITER_INDEX, this);
   }
 
 
@@ -250,7 +320,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeBoolean(byte type, boolean booleanValue)
+  public ASN1Writer writeBoolean(final byte type, final boolean booleanValue)
       throws IOException
   {
     sequenceBuffer.writeByte(type);
@@ -261,8 +331,8 @@
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
-          "WRITE ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)", type,
-          1, String.valueOf(booleanValue)));
+          "WRITE ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)", type, 1,
+          String.valueOf(booleanValue)));
     }
     return this;
   }
@@ -295,7 +365,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeEnumerated(byte type, int intValue)
+  public ASN1Writer writeEnumerated(final byte type, final int intValue)
       throws IOException
   {
     return writeInteger(type, intValue);
@@ -306,7 +376,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeInteger(byte type, int intValue)
+  public ASN1Writer writeInteger(final byte type, final int intValue)
       throws IOException
   {
     sequenceBuffer.writeByte(type);
@@ -318,8 +388,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 1, intValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 1,
+            intValue));
       }
     }
     else if (((intValue < 0) && ((intValue & 0xFFFF8000) == 0xFFFF8000))
@@ -331,8 +401,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 2, intValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 2,
+            intValue));
       }
     }
     else if (((intValue < 0) && ((intValue & 0xFF800000) == 0xFF800000))
@@ -345,8 +415,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 3, intValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 3,
+            intValue));
       }
     }
     else
@@ -359,8 +429,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 4, intValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 4,
+            intValue));
       }
     }
     return this;
@@ -371,7 +441,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeInteger(byte type, long longValue)
+  public ASN1Writer writeInteger(final byte type, final long longValue)
       throws IOException
   {
     sequenceBuffer.writeByte(type);
@@ -383,8 +453,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 1, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 1,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFFFFFFFFFFFF8000L) == 0xFFFFFFFFFFFF8000L))
@@ -396,8 +466,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 2, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 2,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFFFFFFFFFF800000L) == 0xFFFFFFFFFF800000L))
@@ -410,8 +480,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 3, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 3,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFFFFFFFF80000000L) == 0xFFFFFFFF80000000L))
@@ -425,8 +495,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 4, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 4,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFFFFFF8000000000L) == 0xFFFFFF8000000000L))
@@ -441,8 +511,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 5, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 5,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFFFF800000000000L) == 0xFFFF800000000000L))
@@ -458,8 +528,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 6, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 6,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFF80000000000000L) == 0xFF80000000000000L))
@@ -476,8 +546,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 7, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 7,
+            longValue));
       }
     }
     else
@@ -494,8 +564,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 8, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 8,
+            longValue));
       }
     }
     return this;
@@ -506,7 +576,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeNull(byte type) throws IOException
+  public ASN1Writer writeNull(final byte type) throws IOException
   {
     sequenceBuffer.writeByte(type);
     writeLength(sequenceBuffer, 0);
@@ -524,8 +594,8 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeOctetString(byte type, byte[] value,
-      int offset, int length) throws IOException
+  public ASN1Writer writeOctetString(final byte type, final byte[] value,
+      final int offset, final int length) throws IOException
   {
     sequenceBuffer.writeByte(type);
     writeLength(sequenceBuffer, length);
@@ -533,9 +603,8 @@
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String
-          .format("WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)",
-              type, length));
+      StaticUtils.DEBUG_LOG.finest(String.format(
+          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)", type, length));
     }
     return this;
   }
@@ -545,7 +614,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeOctetString(byte type, ByteSequence value)
+  public ASN1Writer writeOctetString(final byte type, final ByteSequence value)
       throws IOException
   {
     sequenceBuffer.writeByte(type);
@@ -558,8 +627,8 @@
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)", type, value
+      StaticUtils.DEBUG_LOG.finest(String
+          .format("WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)", type, value
               .length()));
     }
     return this;
@@ -570,7 +639,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeOctetString(byte type, String value)
+  public ASN1Writer writeOctetString(final byte type, final String value)
       throws IOException
   {
     sequenceBuffer.writeByte(type);
@@ -581,15 +650,15 @@
       return this;
     }
 
-    byte[] bytes = StaticUtils.getBytes(value);
+    final byte[] bytes = StaticUtils.getBytes(value);
     writeLength(sequenceBuffer, bytes.length);
     sequenceBuffer.writeByteArray(bytes, 0, bytes.length);
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
-          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d, "
-              + "value=%s)", type, bytes.length, value));
+          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d, " + "value=%s)", type,
+          bytes.length, value));
     }
     return this;
   }
@@ -599,7 +668,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeStartSequence(byte type) throws IOException
+  public ASN1Writer writeStartSequence(final byte type) throws IOException
   {
     // Get a child sequence buffer
     sequenceBuffer = sequenceBuffer.startSequence(type);
@@ -617,7 +686,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeStartSet(byte type) throws IOException
+  public ASN1Writer writeStartSet(final byte type) throws IOException
   {
     // From an implementation point of view, a set is equivalent to a
     // sequence.
@@ -626,9 +695,15 @@
 
 
 
+  Buffer getBuffer()
+  {
+    return outBuffer.flip();
+  }
+
+
+
   /**
-   * Writes the provided value for use as the length of an ASN.1
-   * element.
+   * Writes the provided value for use as the length of an ASN.1 element.
    *
    * @param buffer
    *          The sequence buffer to write to.
@@ -637,7 +712,7 @@
    * @throws IOException
    *           if an error occurs while writing.
    */
-  private void writeLength(SequenceBuffer buffer, int length)
+  private void writeLength(final SequenceBuffer buffer, final int length)
       throws IOException
   {
     if (length < 128)
diff --git a/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPFutureResultImpl.java b/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPFutureResultImpl.java
index 8560e57..0cc8329 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPFutureResultImpl.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPFutureResultImpl.java
@@ -29,11 +29,9 @@
 
 
 
-import org.opends.sdk.ErrorResultException;
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.FutureResult;
-import org.opends.sdk.ResultHandler;
+import org.opends.sdk.*;
 import org.opends.sdk.requests.Requests;
+import org.opends.sdk.responses.IntermediateResponse;
 import org.opends.sdk.responses.Result;
 
 import com.sun.opends.sdk.util.AbstractFutureResult;
@@ -47,42 +45,29 @@
  *          The type of result returned by this future.
  */
 abstract class AbstractLDAPFutureResultImpl<S extends Result> extends
-    AbstractFutureResult<S> implements FutureResult<S>
+    AbstractFutureResult<S> implements FutureResult<S>,
+    IntermediateResponseHandler
 {
-  private final LDAPConnection connection;
+  private final AsynchronousConnection connection;
 
   private final int messageID;
 
+  private IntermediateResponseHandler intermediateResponseHandler;
+
+  private volatile long timestamp;
 
 
-  /**
-   * Creates a new LDAP result future.
-   *
-   * @param messageID
-   *          The request message ID.
-   * @param handler
-   *          The result handler, maybe {@code null}.
-   * @param connection
-   *          The client connection.
-   */
-  AbstractLDAPFutureResultImpl(int messageID,
-      ResultHandler<? super S> handler, LDAPConnection connection)
+
+  AbstractLDAPFutureResultImpl(final int messageID,
+      final ResultHandler<? super S> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler,
+      final AsynchronousConnection connection)
   {
-    super(handler);
+    super(resultHandler);
     this.messageID = messageID;
     this.connection = connection;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  protected final ErrorResultException handleCancelRequest(
-      boolean mayInterruptIfRunning)
-  {
-    connection.abandon(Requests.newAbandonRequest(messageID));
-    return null;
+    this.intermediateResponseHandler = intermediateResponseHandler;
+    this.timestamp = System.currentTimeMillis();
   }
 
 
@@ -97,16 +82,76 @@
 
 
 
-  final void adaptErrorResult(Result result)
+  public final boolean handleIntermediateResponse(
+      final IntermediateResponse response)
   {
-    S errorResult = newErrorResult(result.getResultCode(), result
+    // FIXME: there's a potential race condition here - the future could
+    // get cancelled between the isDone() call and the handler
+    // invocation. We'd need to add support for intermediate handlers in
+    // the synchronizer.
+    if (!isDone())
+    {
+      updateTimestamp();
+      if (intermediateResponseHandler != null)
+      {
+        if (!intermediateResponseHandler.handleIntermediateResponse(response))
+        {
+          intermediateResponseHandler = null;
+        }
+      }
+    }
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected final ErrorResultException handleCancelRequest(
+      final boolean mayInterruptIfRunning)
+  {
+    connection.abandon(Requests.newAbandonRequest(messageID));
+    return null;
+  }
+
+
+
+  @Override
+  protected void toString(final StringBuilder sb)
+  {
+    sb.append(" messageID = ");
+    sb.append(messageID);
+    sb.append(" timestamp = ");
+    sb.append(timestamp);
+    super.toString(sb);
+  }
+
+
+
+  final void adaptErrorResult(final Result result)
+  {
+    final S errorResult = newErrorResult(result.getResultCode(), result
         .getDiagnosticMessage(), result.getCause());
     setResultOrError(errorResult);
   }
 
 
 
-  final void setResultOrError(S result)
+  final long getTimestamp()
+  {
+    return timestamp;
+  }
+
+
+
+  abstract S newErrorResult(ResultCode resultCode, String diagnosticMessage,
+      Throwable cause);
+
+
+
+  final void setResultOrError(final S result)
   {
     if (result.getResultCode().isExceptional())
     {
@@ -120,7 +165,9 @@
 
 
 
-  abstract S newErrorResult(ResultCode resultCode,
-      String diagnosticMessage, Throwable cause);
+  final void updateTimestamp()
+  {
+    timestamp = System.currentTimeMillis();
+  }
 
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPMessageHandler.java b/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPMessageHandler.java
index fabf582..7112404 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPMessageHandler.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPMessageHandler.java
@@ -29,230 +29,208 @@
 
 
 
+import java.io.IOException;
+
 import org.opends.sdk.ByteString;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.controls.Control;
-import org.opends.sdk.controls.GenericControl;
 import org.opends.sdk.requests.*;
 import org.opends.sdk.responses.*;
-import org.opends.sdk.sasl.SASLBindRequest;
-import org.opends.sdk.schema.Schema;
 
 
 
 /**
  * Abstract LDAP message handler.
+ *
+ * @param <P>
+ *          A user provided handler parameter.
  */
-public abstract class AbstractLDAPMessageHandler implements LDAPMessageHandler
+abstract class AbstractLDAPMessageHandler<P> implements LDAPMessageHandler<P>
 {
-  public void handleUnrecognizedMessage(int messageID, byte messageTag,
-      ByteString messageBytes) throws UnsupportedMessageException
-  {
-    throw new UnsupportedMessageException(messageID, messageTag,
-        messageBytes);
-  }
-
-
-
-  public void handleAbandonRequest(int messageID, AbandonRequest request)
-      throws UnexpectedRequestException
+  public void abandonRequest(final P param, final int messageID,
+      final AbandonRequest request) throws UnexpectedRequestException,
+      IOException
   {
     throw new UnexpectedRequestException(messageID, request);
   }
 
 
 
-  public void handleAddRequest(int messageID, AddRequest request)
-      throws UnexpectedRequestException
+  public void addRequest(final P param, final int messageID,
+      final AddRequest request) throws UnexpectedRequestException, IOException
   {
     throw new UnexpectedRequestException(messageID, request);
   }
 
 
 
-  public void handleCompareRequest(int messageID, CompareRequest request)
-      throws UnexpectedRequestException
-  {
-    throw new UnexpectedRequestException(messageID, request);
-  }
-
-
-
-  public void handleDeleteRequest(int messageID, DeleteRequest request)
-      throws UnexpectedRequestException
-  {
-    throw new UnexpectedRequestException(messageID, request);
-  }
-
-
-
-  public void handleExtendedRequest(int messageID,
-      GenericExtendedRequest request) throws UnexpectedRequestException
-  {
-    throw new UnexpectedRequestException(messageID, request);
-  }
-
-
-
-  public void handleBindRequest(int messageID, int version,
-      GenericBindRequest request) throws UnexpectedRequestException
-  {
-    throw new UnexpectedRequestException(messageID, request);
-  }
-
-
-
-  public void handleBindRequest(int messageID, int version,
-      SASLBindRequest<?> request) throws UnexpectedRequestException
-  {
-    throw new UnexpectedRequestException(messageID, request);
-  }
-
-
-
-  public void handleBindRequest(int messageID, int version,
-      SimpleBindRequest request) throws UnexpectedRequestException
-  {
-    throw new UnexpectedRequestException(messageID, request);
-  }
-
-
-
-  public void handleModifyDNRequest(int messageID,
-      ModifyDNRequest request) throws UnexpectedRequestException
-  {
-    throw new UnexpectedRequestException(messageID, request);
-  }
-
-
-
-  public void handleModifyRequest(int messageID, ModifyRequest request)
-      throws UnexpectedRequestException
-  {
-    throw new UnexpectedRequestException(messageID, request);
-  }
-
-
-
-  public void handleSearchRequest(int messageID, SearchRequest request)
-      throws UnexpectedRequestException
-  {
-    throw new UnexpectedRequestException(messageID, request);
-  }
-
-
-
-  public void handleUnbindRequest(int messageID, UnbindRequest request)
-      throws UnexpectedRequestException
-  {
-    throw new UnexpectedRequestException(messageID, request);
-  }
-
-
-
-  public void handleAddResult(int messageID, Result result)
-      throws UnexpectedResponseException
+  public void addResult(final P param, final int messageID, final Result result)
+      throws UnexpectedResponseException, IOException
   {
     throw new UnexpectedResponseException(messageID, result);
   }
 
 
 
-  public void handleBindResult(int messageID, BindResult result)
-      throws UnexpectedResponseException
+  public void bindRequest(final P param, final int messageID,
+      final int version, final GenericBindRequest request)
+      throws UnexpectedRequestException, IOException
+  {
+    throw new UnexpectedRequestException(messageID, request);
+  }
+
+
+
+  public void bindResult(final P param, final int messageID,
+      final BindResult result) throws UnexpectedResponseException, IOException
   {
     throw new UnexpectedResponseException(messageID, result);
   }
 
 
 
-  public void handleCompareResult(int messageID, CompareResult result)
-      throws UnexpectedResponseException
+  public void compareRequest(final P param, final int messageID,
+      final CompareRequest request) throws UnexpectedRequestException,
+      IOException
+  {
+    throw new UnexpectedRequestException(messageID, request);
+  }
+
+
+
+  public void compareResult(final P param, final int messageID,
+      final CompareResult result) throws UnexpectedResponseException,
+      IOException
   {
     throw new UnexpectedResponseException(messageID, result);
   }
 
 
 
-  public void handleDeleteResult(int messageID, Result result)
-      throws UnexpectedResponseException
+  public void deleteRequest(final P param, final int messageID,
+      final DeleteRequest request) throws UnexpectedRequestException,
+      IOException
+  {
+    throw new UnexpectedRequestException(messageID, request);
+  }
+
+
+
+  public void deleteResult(final P param, final int messageID,
+      final Result result) throws UnexpectedResponseException, IOException
   {
     throw new UnexpectedResponseException(messageID, result);
   }
 
 
 
-  public void handleExtendedResult(int messageID,
-      GenericExtendedResult result) throws UnexpectedResponseException
+  public <R extends ExtendedResult> void extendedRequest(final P param,
+      final int messageID, final ExtendedRequest<R> request)
+      throws UnexpectedRequestException, IOException
+  {
+    throw new UnexpectedRequestException(messageID, request);
+  }
+
+
+
+  public void extendedResult(final P param, final int messageID,
+      final ExtendedResult result) throws UnexpectedResponseException,
+      IOException
   {
     throw new UnexpectedResponseException(messageID, result);
   }
 
 
 
-  public void handleIntermediateResponse(int messageID,
-      GenericIntermediateResponse response)
-      throws UnexpectedResponseException
+  public void intermediateResponse(final P param, final int messageID,
+      final IntermediateResponse response) throws UnexpectedResponseException,
+      IOException
   {
     throw new UnexpectedResponseException(messageID, response);
   }
 
 
 
-  public void handleModifyDNResult(int messageID, Result result)
-      throws UnexpectedResponseException
+  public void modifyDNRequest(final P param, final int messageID,
+      final ModifyDNRequest request) throws UnexpectedRequestException,
+      IOException
+  {
+    throw new UnexpectedRequestException(messageID, request);
+  }
+
+
+
+  public void modifyDNResult(final P param, final int messageID,
+      final Result result) throws UnexpectedResponseException, IOException
   {
     throw new UnexpectedResponseException(messageID, result);
   }
 
 
 
-  public void handleModifyResult(int messageID, Result result)
-      throws UnexpectedResponseException
+  public void modifyRequest(final P param, final int messageID,
+      final ModifyRequest request) throws UnexpectedRequestException,
+      IOException
+  {
+    throw new UnexpectedRequestException(messageID, request);
+  }
+
+
+
+  public void modifyResult(final P param, final int messageID,
+      final Result result) throws UnexpectedResponseException, IOException
   {
     throw new UnexpectedResponseException(messageID, result);
   }
 
 
 
-  public void handleSearchResult(int messageID, Result result)
-      throws UnexpectedResponseException
+  public void searchRequest(final P param, final int messageID,
+      final SearchRequest request) throws UnexpectedRequestException,
+      IOException
+  {
+    throw new UnexpectedRequestException(messageID, request);
+  }
+
+
+
+  public void searchResult(final P param, final int messageID,
+      final Result result) throws UnexpectedResponseException, IOException
   {
     throw new UnexpectedResponseException(messageID, result);
   }
 
 
 
-  public void handleSearchResultEntry(int messageID,
-      SearchResultEntry entry) throws UnexpectedResponseException
+  public void searchResultEntry(final P param, final int messageID,
+      final SearchResultEntry entry) throws UnexpectedResponseException,
+      IOException
   {
     throw new UnexpectedResponseException(messageID, entry);
   }
 
 
 
-  public void handleSearchResultReference(int messageID,
-      SearchResultReference reference)
-      throws UnexpectedResponseException
+  public void searchResultReference(final P param, final int messageID,
+      final SearchResultReference reference)
+      throws UnexpectedResponseException, IOException
   {
     throw new UnexpectedResponseException(messageID, reference);
   }
 
 
 
-  public Control decodeResponseControl(int messageID, String oid,
-      boolean isCritical, ByteString value, Schema schema)
-      throws DecodeException
+  public void unbindRequest(final P param, final int messageID,
+      final UnbindRequest request) throws UnexpectedRequestException,
+      IOException
   {
-    return new GenericControl(oid, isCritical, value);
+    throw new UnexpectedRequestException(messageID, request);
   }
 
 
 
-  public Control decodeRequestControl(int messageID, String oid,
-      boolean isCritical, ByteString value, Schema schema)
-      throws DecodeException
+  public void unrecognizedMessage(final P param, final int messageID,
+      final byte messageTag, final ByteString messageBytes)
+      throws UnsupportedMessageException, IOException
   {
-    return new GenericControl(oid, isCritical, value);
+    throw new UnsupportedMessageException(messageID, messageTag, messageBytes);
   }
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPTransport.java b/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPTransport.java
deleted file mode 100644
index 7816982..0000000
--- a/sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPTransport.java
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package com.sun.opends.sdk.ldap;
-
-
-
-import java.io.IOException;
-
-import com.sun.grizzly.Connection;
-import com.sun.grizzly.filterchain.*;
-import com.sun.grizzly.streams.StreamReader;
-import com.sun.grizzly.streams.StreamWriter;
-import com.sun.grizzly.utils.ConcurrentQueuePool;
-import org.opends.sdk.ldap.LDAPDecoder;
-
-
-/**
- * Abstract LDAP transport.
- */
-public abstract class AbstractLDAPTransport
-{
-  private class ASN1ReaderPool extends
-      ConcurrentQueuePool<ASN1StreamReader>
-  {
-    @Override
-    public ASN1StreamReader newInstance()
-    {
-      return new ASN1StreamReader(maxASN1ElementSize);
-    }
-  }
-
-
-
-  private class ASN1WriterPool extends
-      ConcurrentQueuePool<ASN1StreamWriter>
-  {
-    @Override
-    public ASN1StreamWriter newInstance()
-    {
-      return new ASN1StreamWriter();
-    }
-  }
-
-
-
-  private class DefaultFilterChainFactory implements
-      PatternFilterChainFactory
-  {
-    private FilterChain defaultFilterChain;
-
-
-
-    private DefaultFilterChainFactory()
-    {
-      this.defaultFilterChain = new DefaultFilterChain(this);
-      this.defaultFilterChain.add(new MonitorFilter());
-      this.defaultFilterChain.add(new TransportFilter());
-      this.defaultFilterChain.add(new LDAPFilter());
-    }
-
-
-
-    public FilterChain create()
-    {
-      FilterChain filterChain = new DefaultFilterChain(this);
-      filterChain.addAll(defaultFilterChain);
-      return filterChain;
-    }
-
-
-
-    public FilterChain getFilterChainPattern()
-    {
-      return defaultFilterChain;
-    }
-
-
-
-    public void release(FilterChain chain)
-    {
-      // TODO: Nothing yet.
-    }
-
-
-
-    public void setFilterChainPattern(FilterChain chain)
-    {
-      defaultFilterChain = chain;
-    }
-  }
-
-
-
-  private class LDAPFilter extends FilterAdapter
-  {
-    @Override
-    public NextAction handleRead(FilterChainContext ctx,
-        NextAction nextAction) throws IOException
-    {
-      Connection<?> connection = ctx.getConnection();
-      StreamReader streamReader = ctx.getStreamReader();
-      LDAPMessageHandler handler = getMessageHandler(connection);
-      ASN1StreamReader asn1Reader = getASN1Reader(streamReader);
-
-      try
-      {
-        do
-        {
-          LDAPDecoder.decode(asn1Reader, handler);
-        }
-        while (asn1Reader.hasNextElement());
-      }
-      finally
-      {
-        releaseASN1Reader(asn1Reader);
-      }
-
-      return nextAction;
-    }
-  }
-
-
-
-  private class MonitorFilter extends FilterAdapter
-  {
-    @Override
-    public void exceptionOccurred(FilterChainContext ctx,
-        Throwable error)
-    {
-      Connection<?> connection = ctx.getConnection();
-      if (!connection.isOpen())
-      {
-        // Grizzly doens't not deregister the read interest from the
-        // selector so closing the connection results in an
-        // EOFException.
-        // Just ignore errors on closed connections.
-        return;
-      }
-      LDAPMessageHandler handler = getMessageHandler(connection);
-      handler.handleException(error);
-    }
-
-
-
-    @Override
-    public NextAction handleClose(FilterChainContext ctx,
-        NextAction nextAction) throws IOException
-    {
-      Connection<?> connection = ctx.getConnection();
-      removeMessageHandler(connection);
-      return nextAction;
-    }
-  }
-
-  private final PatternFilterChainFactory defaultFilterChainFactory;
-
-  private final int maxASN1ElementSize = 0;
-
-  private final ASN1ReaderPool asn1ReaderPool;
-
-  private final ASN1WriterPool asn1WriterPool;
-
-
-
-  protected AbstractLDAPTransport()
-  {
-    this.defaultFilterChainFactory = new DefaultFilterChainFactory();
-
-    this.asn1ReaderPool = new ASN1ReaderPool();
-    this.asn1WriterPool = new ASN1WriterPool();
-  }
-
-
-
-  public ASN1StreamWriter getASN1Writer(StreamWriter streamWriter)
-  {
-    ASN1StreamWriter asn1Writer = asn1WriterPool.poll();
-    asn1Writer.setStreamWriter(streamWriter);
-    return asn1Writer;
-  }
-
-
-
-  public PatternFilterChainFactory getDefaultFilterChainFactory()
-  {
-    return defaultFilterChainFactory;
-  }
-
-
-
-  public void releaseASN1Writer(ASN1StreamWriter asn1Writer)
-  {
-    asn1WriterPool.offer(asn1Writer);
-  }
-
-
-
-  protected abstract LDAPMessageHandler getMessageHandler(
-      Connection<?> connection);
-
-
-
-  protected abstract void removeMessageHandler(Connection<?> connection);
-
-
-
-  private ASN1StreamReader getASN1Reader(StreamReader streamReader)
-  {
-    ASN1StreamReader asn1Reader = asn1ReaderPool.poll();
-    asn1Reader.setStreamReader(streamReader);
-    return asn1Reader;
-  }
-
-
-
-  private void releaseASN1Reader(ASN1StreamReader asn1Reader)
-  {
-    asn1ReaderPool.offer(asn1Reader);
-  }
-}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/GlobalTransportFactory.java b/sdk/src/com/sun/opends/sdk/ldap/GlobalTransportFactory.java
new file mode 100644
index 0000000..b3e1279
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/GlobalTransportFactory.java
@@ -0,0 +1,183 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import java.io.IOException;
+
+import com.sun.grizzly.TransportFactory;
+import com.sun.grizzly.nio.NIOTransportFactory;
+import com.sun.grizzly.nio.transport.TCPNIOTransport;
+import com.sun.grizzly.nio.transport.UDPNIOTransport;
+import com.sun.grizzly.threadpool.ThreadPoolConfig;
+import com.sun.opends.sdk.util.StaticUtils;
+
+
+
+/**
+ * A static Grizzly transport that can be used by default globally in the SDK.
+ */
+public final class GlobalTransportFactory extends NIOTransportFactory
+{
+  private static final GlobalTransportFactory INSTANCE = new GlobalTransportFactory();
+
+
+
+  /**
+   * Returns the global Grizzly transport factory.
+   *
+   * @return The global Grizzly transport factory.
+   */
+  public static TransportFactory getInstance()
+  {
+    return INSTANCE;
+  }
+
+
+
+  /**
+   * Sets the global Grizzly transport factory.
+   *
+   * @param factory
+   *          The global Grizzly transport factory.
+   */
+  public static void setInstance(final TransportFactory factory)
+  {
+    throw new UnsupportedOperationException("not yet implemented");
+  }
+
+
+
+  private int selectors;
+
+  private TCPNIOTransport globalTCPNIOTransport = null;
+
+
+
+  private GlobalTransportFactory()
+  {
+    // Prevent instantiation.
+  }
+
+
+
+  /**
+   * Close the {@link com.sun.grizzly.TransportFactory} and release all
+   * resources.
+   */
+  @Override
+  public synchronized void close()
+  {
+    if (globalTCPNIOTransport != null)
+    {
+      try
+      {
+        globalTCPNIOTransport.stop();
+      }
+      catch (final IOException e)
+      {
+        StaticUtils.DEBUG_LOG
+            .warning("Error shutting down Grizzly TCP NIO transport: " + e);
+      }
+    }
+    super.close();
+  }
+
+
+
+  /**
+   * Create instance of TCP {@link com.sun.grizzly.Transport}.
+   *
+   * @return instance of TCP {@link com.sun.grizzly.Transport}.
+   */
+  @Override
+  public TCPNIOTransport createTCPTransport()
+  {
+    if (globalTCPNIOTransport == null)
+    {
+      globalTCPNIOTransport = setupTransport(new TCPNIOTransport());
+      globalTCPNIOTransport.setSelectorRunnersCount(selectors);
+
+      try
+      {
+        globalTCPNIOTransport.start();
+      }
+      catch (final IOException e)
+      {
+        throw new RuntimeException(
+            "Unable to create default connection factory provider", e);
+      }
+    }
+    return globalTCPNIOTransport;
+  }
+
+
+
+  /**
+   * Creating an UDP transport is unsupported with this factory. A {@code
+   * UnsupportedOperationException} will be thrown when this method is called.
+   *
+   * @return This method will always throw {@code UnsupportedOperationException}
+   *         .
+   */
+  @Override
+  public UDPNIOTransport createUDPTransport()
+  {
+    throw new UnsupportedOperationException();
+  }
+
+
+
+  @Override
+  public void initialize()
+  {
+    final int cpus = Runtime.getRuntime().availableProcessors();
+    int threads = Math.max(5, (cpus / 2) - 1);
+    selectors = Math.max(2, cpus / 8);
+
+    final String threadsStr = System
+        .getProperty("org.opends.sdk.ldap.transport.threads");
+    if (threadsStr != null)
+    {
+      threads = Integer.parseInt(threadsStr);
+    }
+    final String selectorsStr = System
+        .getProperty("org.opends.sdk.ldap.transport.selectors");
+    if (threadsStr != null)
+    {
+      selectors = Integer.parseInt(selectorsStr);
+    }
+
+    ThreadPoolConfig.DEFAULT.setCorePoolSize(threads);
+    ThreadPoolConfig.DEFAULT.setMaxPoolSize(threads);
+    ThreadPoolConfig.DEFAULT.setPoolName("OpenDS SDK Worker(Grizzly)");
+
+    super.initialize();
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPListenerOptions.java b/sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPListenerOptions.java
new file mode 100644
index 0000000..ec3e223
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPListenerOptions.java
@@ -0,0 +1,116 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import org.opends.sdk.LDAPListenerOptions;
+
+import com.sun.grizzly.nio.transport.TCPNIOTransport;
+
+
+
+/**
+ * Common options for LDAP listeners, including the Grizzly TCP transport.
+ */
+public final class GrizzlyLDAPListenerOptions extends LDAPListenerOptions
+{
+  private TCPNIOTransport transport = null;
+
+
+
+  /**
+   * Creates a new set of listener options with default settings. SSL will not
+   * be enabled, a default set of decode options will be used, and the
+   * {@link GlobalTransportFactory} should be used to obtain a TCP transport.
+   */
+  public GrizzlyLDAPListenerOptions()
+  {
+    // Nothing to do.
+  }
+
+
+
+  /**
+   * Creates a new set of listener options having the same initial set of
+   * options as the provided set of connection options.
+   *
+   * @param options
+   *          The set of connection options to be copied.
+   */
+  public GrizzlyLDAPListenerOptions(final LDAPListenerOptions options)
+  {
+    super(options);
+    if (options instanceof GrizzlyLDAPListenerOptions)
+    {
+      this.transport = ((GrizzlyLDAPListenerOptions) options)
+          .getTCPNIOTransport();
+    }
+  }
+
+
+
+  /**
+   * Returns the Grizzly TCP transport which will be used when initiating
+   * connections with the Directory Server. By default this method will return
+   * {@code null} indicating that the {@link GlobalTransportFactory} should be
+   * used to obtain a TCP transport.
+   *
+   * @return The Grizzly TCP transport which will be used when initiating
+   *         connections with the Directory Server, or {@code null} if the
+   *         {@link GlobalTransportFactory} should be used to obtain a TCP
+   *         transport.
+   */
+  public final TCPNIOTransport getTCPNIOTransport()
+  {
+    return transport;
+  }
+
+
+
+  /**
+   * Sets the Grizzly TCP transport which will be used when initiating
+   * connections with the Directory Server. By default this method will return
+   * {@code null} indicating that the {@link GlobalTransportFactory} should be
+   * used to obtain a TCP transport.
+   *
+   * @param transport
+   *          The Grizzly TCP transport which will be used when initiating
+   *          connections with the Directory Server, or {@code null} if the
+   *          {@link GlobalTransportFactory} should be used to obtain a TCP
+   *          transport.
+   * @return A reference to this connection options.
+   */
+  public final GrizzlyLDAPListenerOptions setTCPNIOTransport(
+      final TCPNIOTransport transport)
+  {
+    this.transport = transport;
+    return this;
+  }
+
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPOptions.java b/sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPOptions.java
new file mode 100644
index 0000000..f75e634
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPOptions.java
@@ -0,0 +1,116 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import org.opends.sdk.LDAPOptions;
+
+import com.sun.grizzly.nio.transport.TCPNIOTransport;
+
+
+
+/**
+ * Common options for LDAP client connections, including the Grizzly TCP
+ * transport.
+ */
+public final class GrizzlyLDAPOptions extends LDAPOptions
+{
+  private TCPNIOTransport transport = null;
+
+
+
+  /**
+   * Creates a new set of connection options with default settings. SSL will not
+   * be enabled, a default set of decode options will be used, and the
+   * {@link GlobalTransportFactory} should be used to obtain a TCP transport.
+   */
+  public GrizzlyLDAPOptions()
+  {
+    // Nothing to do.
+  }
+
+
+
+  /**
+   * Creates a new set of connection options having the same initial set of
+   * options as the provided set of connection options.
+   *
+   * @param options
+   *          The set of connection options to be copied.
+   */
+  public GrizzlyLDAPOptions(final LDAPOptions options)
+  {
+    super(options);
+    if (options instanceof GrizzlyLDAPOptions)
+    {
+      this.transport = ((GrizzlyLDAPOptions) options).getTCPNIOTransport();
+    }
+  }
+
+
+
+  /**
+   * Returns the Grizzly TCP transport which will be used when initiating
+   * connections with the Directory Server. By default this method will return
+   * {@code null} indicating that the {@link GlobalTransportFactory} should be
+   * used to obtain a TCP transport.
+   *
+   * @return The Grizzly TCP transport which will be used when initiating
+   *         connections with the Directory Server, or {@code null} if the
+   *         {@link GlobalTransportFactory} should be used to obtain a TCP
+   *         transport.
+   */
+  public final TCPNIOTransport getTCPNIOTransport()
+  {
+    return transport;
+  }
+
+
+
+  /**
+   * Sets the Grizzly TCP transport which will be used when initiating
+   * connections with the Directory Server. By default this method will return
+   * {@code null} indicating that the {@link GlobalTransportFactory} should be
+   * used to obtain a TCP transport.
+   *
+   * @param transport
+   *          The Grizzly TCP transport which will be used when initiating
+   *          connections with the Directory Server, or {@code null} if the
+   *          {@link GlobalTransportFactory} should be used to obtain a TCP
+   *          transport.
+   * @return A reference to this connection options.
+   */
+  public final GrizzlyLDAPOptions setTCPNIOTransport(
+      final TCPNIOTransport transport)
+  {
+    this.transport = transport;
+    return this;
+  }
+
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/InternalConnection.java b/sdk/src/com/sun/opends/sdk/ldap/InternalConnection.java
new file mode 100644
index 0000000..aa897ee
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/InternalConnection.java
@@ -0,0 +1,335 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.opends.sdk.*;
+import org.opends.sdk.requests.*;
+import org.opends.sdk.responses.*;
+
+import com.sun.opends.sdk.util.CompletedFutureResult;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * This class defines a pseudo-connection object that can be used for performing
+ * internal operations directly against a {@code ServerConnection}
+ * implementation.
+ */
+public final class InternalConnection extends AbstractAsynchronousConnection
+{
+  private final class InternalBindFutureResultImpl extends
+      AbstractLDAPFutureResultImpl<BindResult> implements
+      FutureResult<BindResult>
+  {
+    private final BindRequest bindRequest;
+
+
+
+    InternalBindFutureResultImpl(final int messageID,
+        final BindRequest bindRequest,
+        final ResultHandler<? super BindResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler,
+        final AsynchronousConnection connection)
+    {
+      super(messageID, resultHandler, intermediateResponseHandler, connection);
+      this.bindRequest = bindRequest;
+    }
+
+
+
+    @Override
+    public String toString()
+    {
+      final StringBuilder sb = new StringBuilder();
+      sb.append("InternalBindFutureResultImpl(");
+      sb.append("bindRequest = ");
+      sb.append(bindRequest);
+      super.toString(sb);
+      sb.append(")");
+      return sb.toString();
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    BindResult newErrorResult(final ResultCode resultCode,
+        final String diagnosticMessage, final Throwable cause)
+    {
+      return Responses.newBindResult(resultCode).setDiagnosticMessage(
+          diagnosticMessage).setCause(cause);
+    }
+  }
+
+
+
+  private final ServerConnection<Integer> serverConnection;
+  private final List<ConnectionEventListener> listeners =
+    new CopyOnWriteArrayList<ConnectionEventListener>();
+  private final AtomicInteger messageID = new AtomicInteger();
+
+
+
+  /**
+   * Sets the server connection associated with this internal connection.
+   *
+   * @param serverConnection
+   *          The server connection.
+   */
+  public InternalConnection(final ServerConnection<Integer> serverConnection)
+  {
+    this.serverConnection = serverConnection;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Void> abandon(final AbandonRequest request)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final int i = messageID.getAndIncrement();
+    serverConnection.abandon(i, request);
+    return new CompletedFutureResult<Void>((Void) null, i);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Result> add(final AddRequest request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final int i = messageID.getAndIncrement();
+    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(i, request,
+        resultHandler, intermediateResponseHandler, this);
+    serverConnection.add(i, request, future, future);
+    return future;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void addConnectionEventListener(final ConnectionEventListener listener)
+      throws IllegalStateException, NullPointerException
+  {
+    Validator.ensureNotNull(listener);
+    listeners.add(listener);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<BindResult> bind(final BindRequest request,
+      final ResultHandler<? super BindResult> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final int i = messageID.getAndIncrement();
+    final InternalBindFutureResultImpl future = new InternalBindFutureResultImpl(
+        i, request, resultHandler, intermediateResponseHandler, this);
+    serverConnection.bind(i, 3, request, future, future);
+    return future;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void close(final UnbindRequest request, final String reason)
+  {
+    final int i = messageID.getAndIncrement();
+    serverConnection.closed(i, request);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<CompareResult> compare(final CompareRequest request,
+      final ResultHandler<? super CompareResult> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final int i = messageID.getAndIncrement();
+    final LDAPCompareFutureResultImpl future = new LDAPCompareFutureResultImpl(
+        i, request, resultHandler, intermediateResponseHandler, this);
+    serverConnection.compare(i, request, future, future);
+    return future;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Result> delete(final DeleteRequest request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final int i = messageID.getAndIncrement();
+    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(i, request,
+        resultHandler, intermediateResponseHandler, this);
+    serverConnection.delete(i, request, future, future);
+    return future;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+      final ExtendedRequest<R> request,
+      final ResultHandler<? super R> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final int i = messageID.getAndIncrement();
+    final LDAPExtendedFutureResultImpl<R> future = new LDAPExtendedFutureResultImpl<R>(
+        i, request, resultHandler, intermediateResponseHandler, this);
+    serverConnection.extendedRequest(i, request, future, future);
+    return future;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isClosed()
+  {
+    // FIXME: this should be true after close has been called.
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isValid()
+  {
+    // FIXME: this should be false if this connection is disconnected.
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Result> modify(final ModifyRequest request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final int i = messageID.getAndIncrement();
+    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(i, request,
+        resultHandler, intermediateResponseHandler, this);
+    serverConnection.modify(i, request, future, future);
+    return future;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final int i = messageID.getAndIncrement();
+    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(i, request,
+        resultHandler, intermediateResponseHandler, this);
+    serverConnection.modifyDN(i, request, future, future);
+    return future;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void removeConnectionEventListener(
+      final ConnectionEventListener listener) throws NullPointerException
+  {
+    Validator.ensureNotNull(listener);
+    listeners.remove(listener);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Result> search(final SearchRequest request,
+      final ResultHandler<Result> resultHandler,
+      final SearchResultHandler searchResulthandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final int i = messageID.getAndIncrement();
+    final LDAPSearchFutureResultImpl future = new LDAPSearchFutureResultImpl(i,
+        request, resultHandler, searchResulthandler,
+        intermediateResponseHandler, this);
+    serverConnection.search(i, request, future, future, future);
+    return future;
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPBindFutureResultImpl.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPBindFutureResultImpl.java
index 028d85b..4fda984 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/LDAPBindFutureResultImpl.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPBindFutureResultImpl.java
@@ -29,13 +29,10 @@
 
 
 
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.FutureResult;
-import org.opends.sdk.ResultHandler;
-import org.opends.sdk.requests.BindRequest;
+import org.opends.sdk.*;
+import org.opends.sdk.requests.BindClient;
 import org.opends.sdk.responses.BindResult;
 import org.opends.sdk.responses.Responses;
-import org.opends.sdk.sasl.SASLContext;
 
 
 
@@ -46,18 +43,38 @@
     AbstractLDAPFutureResultImpl<BindResult> implements
     FutureResult<BindResult>
 {
-  private final BindRequest request;
-
-  private SASLContext saslContext;
+  private final BindClient bindClient;
 
 
 
-  LDAPBindFutureResultImpl(int messageID, BindRequest request,
-      ResultHandler<? super BindResult> handler,
-      LDAPConnection connection)
+  LDAPBindFutureResultImpl(final int messageID, final BindClient bindClient,
+      final ResultHandler<? super BindResult> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler,
+      final AsynchronousConnection connection)
   {
-    super(messageID, handler, connection);
-    this.request = request;
+    super(messageID, resultHandler, intermediateResponseHandler, connection);
+    this.bindClient = bindClient;
+  }
+
+
+
+  @Override
+  public String toString()
+  {
+    final StringBuilder sb = new StringBuilder();
+    sb.append("LDAPBindFutureResultImpl(");
+    sb.append("bindClient = ");
+    sb.append(bindClient);
+    super.toString(sb);
+    sb.append(")");
+    return sb.toString();
+  }
+
+
+
+  BindClient getBindClient()
+  {
+    return bindClient;
   }
 
 
@@ -66,31 +83,10 @@
    * {@inheritDoc}
    */
   @Override
-  BindResult newErrorResult(ResultCode resultCode,
-      String diagnosticMessage, Throwable cause)
+  BindResult newErrorResult(final ResultCode resultCode,
+      final String diagnosticMessage, final Throwable cause)
   {
     return Responses.newBindResult(resultCode).setDiagnosticMessage(
         diagnosticMessage).setCause(cause);
   }
-
-
-
-  BindRequest getRequest()
-  {
-    return request;
-  }
-
-
-
-  void setSASLContext(SASLContext saslContext)
-  {
-    this.saslContext = saslContext;
-  }
-
-
-
-  SASLContext getSASLContext()
-  {
-    return saslContext;
-  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPClientFilter.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPClientFilter.java
new file mode 100644
index 0000000..a1e1618
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPClientFilter.java
@@ -0,0 +1,587 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import static com.sun.opends.sdk.ldap.LDAPConstants.OID_NOTICE_OF_DISCONNECTION;
+
+import java.io.EOFException;
+import java.io.IOException;
+
+import javax.net.ssl.SSLEngine;
+
+import org.opends.sdk.ConnectionSecurityLayer;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.ErrorResultException;
+import org.opends.sdk.ResultCode;
+import org.opends.sdk.requests.*;
+import org.opends.sdk.responses.*;
+
+import com.sun.grizzly.Buffer;
+import com.sun.grizzly.Connection;
+import com.sun.grizzly.EmptyCompletionHandler;
+import com.sun.grizzly.Grizzly;
+import com.sun.grizzly.attributes.Attribute;
+import com.sun.grizzly.filterchain.BaseFilter;
+import com.sun.grizzly.filterchain.FilterChainContext;
+import com.sun.grizzly.filterchain.NextAction;
+
+
+
+/**
+ * Grizzly filter implementation for decoding LDAP responses and handling client
+ * side logic for SSL and SASL operations over LDAP.
+ */
+final class LDAPClientFilter extends BaseFilter
+{
+  private static final Attribute<LDAPConnection> LDAP_CONNECTION_ATTR =
+    Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("LDAPClientConnection");
+  private static final Attribute<ASN1BufferReader> LDAP_ASN1_READER_ATTR =
+    Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("LDAPASN1Reader");
+
+  private final int maxASN1ElementSize;
+  private final LDAPReader ldapReader;
+
+  private static final AbstractLDAPMessageHandler<FilterChainContext>
+    CLIENT_RESPONSE_HANDLER = new AbstractLDAPMessageHandler<FilterChainContext>()
+  {
+    @Override
+    public void addResult(final FilterChainContext ctx, final int messageID,
+        final Result result) throws UnexpectedResponseException, IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .removePendingRequest(messageID);
+
+      if (pendingRequest != null)
+      {
+        if (pendingRequest instanceof LDAPFutureResultImpl)
+        {
+          final LDAPFutureResultImpl future = (LDAPFutureResultImpl) pendingRequest;
+          if (future.getRequest() instanceof AddRequest)
+          {
+            future.setResultOrError(result);
+            return;
+          }
+        }
+        throw new UnexpectedResponseException(messageID, result);
+      }
+    }
+
+
+
+    @Override
+    public void bindResult(final FilterChainContext ctx, final int messageID,
+        final BindResult result) throws UnexpectedResponseException,
+        IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .removePendingRequest(messageID);
+
+      if (pendingRequest != null)
+      {
+        if (pendingRequest instanceof LDAPBindFutureResultImpl)
+        {
+          final LDAPBindFutureResultImpl future = ((LDAPBindFutureResultImpl) pendingRequest);
+          final BindClient bindClient = future.getBindClient();
+
+          try
+          {
+            if (!bindClient.evaluateResult(result))
+            {
+              // The server is expecting a multi stage bind response.
+              final int msgID = ldapConnection
+                  .addPendingRequest(pendingRequest);
+
+              final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+              try
+              {
+                final GenericBindRequest nextRequest = bindClient
+                    .nextBindRequest();
+                new LDAPWriter().bindRequest(asn1Writer, msgID, 3, nextRequest);
+                ctx.write(asn1Writer.getBuffer(), null);
+              }
+              finally
+              {
+                asn1Writer.close();
+              }
+              return;
+            }
+          }
+          catch (final ErrorResultException e)
+          {
+            future.adaptErrorResult(e.getResult());
+            return;
+          }
+          catch (final IOException e)
+          {
+            // FIXME: I18N need to have a better error message.
+            // FIXME: Is this the best result code?
+            final Result errorResult = Responses.newResult(
+                ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+                "An error occurred during multi-stage authentication")
+                .setCause(e);
+            future.adaptErrorResult(errorResult);
+            return;
+          }
+
+          if (result.getResultCode() == ResultCode.SUCCESS)
+          {
+            final ConnectionSecurityLayer l = bindClient
+                .getConnectionSecurityLayer();
+            if (l != null)
+            {
+              // The connection needs to be secured by the SASL
+              // mechanism.
+              ldapConnection.installFilter(new SASLFilter(l));
+            }
+          }
+
+          ldapConnection.setBindOrStartTLSInProgress(false);
+          future.setResultOrError(result);
+          return;
+        }
+        throw new UnexpectedResponseException(messageID, result);
+      }
+    }
+
+
+
+    @Override
+    public void compareResult(final FilterChainContext ctx,
+        final int messageID, final CompareResult result)
+        throws UnexpectedResponseException, IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .removePendingRequest(messageID);
+
+      if (pendingRequest != null)
+      {
+        if (pendingRequest instanceof LDAPCompareFutureResultImpl)
+        {
+          final LDAPCompareFutureResultImpl future = (LDAPCompareFutureResultImpl) pendingRequest;
+          future.setResultOrError(result);
+          return;
+        }
+        throw new UnexpectedResponseException(messageID, result);
+      }
+    }
+
+
+
+    @Override
+    public void deleteResult(final FilterChainContext ctx, final int messageID,
+        final Result result) throws UnexpectedResponseException, IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .removePendingRequest(messageID);
+
+      if (pendingRequest != null)
+      {
+        if (pendingRequest instanceof LDAPFutureResultImpl)
+        {
+          final LDAPFutureResultImpl future = (LDAPFutureResultImpl) pendingRequest;
+          if (future.getRequest() instanceof DeleteRequest)
+          {
+            future.setResultOrError(result);
+            return;
+          }
+        }
+        throw new UnexpectedResponseException(messageID, result);
+      }
+    }
+
+
+
+    @Override
+    public void extendedResult(final FilterChainContext ctx,
+        final int messageID, final ExtendedResult result)
+        throws UnexpectedResponseException, IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      if (messageID == 0)
+      {
+        if ((result.getOID() != null)
+            && result.getOID().equals(OID_NOTICE_OF_DISCONNECTION))
+        {
+
+          final Result errorResult = Responses
+              .newResult(result.getResultCode()).setDiagnosticMessage(
+                  result.getDiagnosticMessage());
+          ldapConnection.close(null, true, errorResult);
+          return;
+        }
+        else
+        {
+          // Unsolicited notification received.
+          ldapConnection.handleUnsolicitedNotification(result);
+        }
+      }
+
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .removePendingRequest(messageID);
+
+      if (pendingRequest instanceof LDAPExtendedFutureResultImpl<?>)
+      {
+        final LDAPExtendedFutureResultImpl<?> extendedFuture =
+          ((LDAPExtendedFutureResultImpl<?>) pendingRequest);
+        try
+        {
+          handleExtendedResult0(ldapConnection, extendedFuture, result);
+        }
+        catch (final DecodeException de)
+        {
+          // FIXME: should the connection be closed as well?
+          final Result errorResult = Responses.newResult(
+              ResultCode.CLIENT_SIDE_DECODING_ERROR).setDiagnosticMessage(
+              de.getLocalizedMessage()).setCause(de);
+          extendedFuture.adaptErrorResult(errorResult);
+        }
+      }
+      else
+      {
+        throw new UnexpectedResponseException(messageID, result);
+      }
+    }
+
+
+
+    @Override
+    public void intermediateResponse(final FilterChainContext ctx,
+        final int messageID, final IntermediateResponse response)
+        throws UnexpectedResponseException, IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .getPendingRequest(messageID);
+
+      if (pendingRequest != null)
+      {
+        pendingRequest.handleIntermediateResponse(response);
+      }
+    }
+
+
+
+    @Override
+    public void modifyDNResult(final FilterChainContext ctx,
+        final int messageID, final Result result)
+        throws UnexpectedResponseException, IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .removePendingRequest(messageID);
+
+      if (pendingRequest != null)
+      {
+        if (pendingRequest instanceof LDAPFutureResultImpl)
+        {
+          final LDAPFutureResultImpl future = (LDAPFutureResultImpl) pendingRequest;
+          if (future.getRequest() instanceof ModifyDNRequest)
+          {
+            future.setResultOrError(result);
+            return;
+          }
+        }
+        throw new UnexpectedResponseException(messageID, result);
+      }
+    }
+
+
+
+    @Override
+    public void modifyResult(final FilterChainContext ctx, final int messageID,
+        final Result result) throws UnexpectedResponseException, IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .removePendingRequest(messageID);
+
+      if (pendingRequest != null)
+      {
+        if (pendingRequest instanceof LDAPFutureResultImpl)
+        {
+          final LDAPFutureResultImpl future = (LDAPFutureResultImpl) pendingRequest;
+          if (future.getRequest() instanceof ModifyRequest)
+          {
+            future.setResultOrError(result);
+            return;
+          }
+        }
+        throw new UnexpectedResponseException(messageID, result);
+      }
+    }
+
+
+
+    @Override
+    public void searchResult(final FilterChainContext ctx, final int messageID,
+        final Result result) throws UnexpectedResponseException, IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .removePendingRequest(messageID);
+
+      if (pendingRequest != null)
+      {
+        if (pendingRequest instanceof LDAPSearchFutureResultImpl)
+        {
+          ((LDAPSearchFutureResultImpl) pendingRequest)
+              .setResultOrError(result);
+        }
+        else
+        {
+          throw new UnexpectedResponseException(messageID, result);
+        }
+      }
+    }
+
+
+
+    @Override
+    public void searchResultEntry(final FilterChainContext ctx,
+        final int messageID, final SearchResultEntry entry)
+        throws UnexpectedResponseException, IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .getPendingRequest(messageID);
+
+      if (pendingRequest != null)
+      {
+        if (pendingRequest instanceof LDAPSearchFutureResultImpl)
+        {
+          ((LDAPSearchFutureResultImpl) pendingRequest).handleEntry(entry);
+        }
+        else
+        {
+          throw new UnexpectedResponseException(messageID, entry);
+        }
+      }
+    }
+
+
+
+    @Override
+    public void searchResultReference(final FilterChainContext ctx,
+        final int messageID, final SearchResultReference reference)
+        throws UnexpectedResponseException, IOException
+    {
+      final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AbstractLDAPFutureResultImpl<?> pendingRequest = ldapConnection
+          .getPendingRequest(messageID);
+
+      if (pendingRequest != null)
+      {
+        if (pendingRequest instanceof LDAPSearchFutureResultImpl)
+        {
+          ((LDAPSearchFutureResultImpl) pendingRequest)
+              .handleReference(reference);
+        }
+        else
+        {
+          throw new UnexpectedResponseException(messageID, reference);
+        }
+      }
+    }
+
+
+
+    // Needed in order to expose type information.
+    private <R extends ExtendedResult> void handleExtendedResult0(
+        final LDAPConnection conn,
+        final LDAPExtendedFutureResultImpl<R> future,
+        final ExtendedResult result) throws DecodeException
+    {
+      final R decodedResponse = future.decodeResult(result, conn
+          .getLDAPOptions().getDecodeOptions());
+
+      if (future.getRequest() instanceof StartTLSExtendedRequest)
+      {
+        if (result.getResultCode() == ResultCode.SUCCESS)
+        {
+          try
+          {
+            final StartTLSExtendedRequest request = (StartTLSExtendedRequest) future
+                .getRequest();
+            conn.startTLS(request.getSSLContext(),
+                new EmptyCompletionHandler<SSLEngine>()
+                {
+                  @Override
+                  public void completed(final SSLEngine result)
+                  {
+                    conn.setBindOrStartTLSInProgress(false);
+                    future.setResultOrError(decodedResponse);
+                  }
+
+
+
+                  @Override
+                  public void failed(final Throwable throwable)
+                  {
+                    final Result errorResult = Responses.newResult(
+                        ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(throwable)
+                        .setDiagnosticMessage("SSL handshake failed");
+                    conn.setBindOrStartTLSInProgress(false);
+                    conn.close(null, false, errorResult);
+                    future.adaptErrorResult(errorResult);
+                  }
+                });
+            return;
+          }
+          catch (final IOException e)
+          {
+            final Result errorResult = Responses.newResult(
+                ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e)
+                .setDiagnosticMessage(e.getMessage());
+            future.adaptErrorResult(errorResult);
+            conn.close(null, false, errorResult);
+            return;
+          }
+        }
+      }
+
+      future.setResultOrError(decodedResponse);
+    }
+  };
+
+
+
+  LDAPClientFilter(final LDAPReader ldapReader, final int maxASN1ElementSize)
+  {
+    this.ldapReader = ldapReader;
+    this.maxASN1ElementSize = maxASN1ElementSize;
+  }
+
+
+
+  @Override
+  public void exceptionOccurred(final FilterChainContext ctx,
+      final Throwable error)
+  {
+    final Connection<?> connection = ctx.getConnection();
+    if (!connection.isOpen())
+    {
+      // Grizzly doens't not deregister the read interest from the
+      // selector so closing the connection results in an
+      // EOFException.
+      // Just ignore errors on closed connections.
+      return;
+    }
+    final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR.get(connection);
+
+    Result errorResult;
+    if (error instanceof EOFException)
+    {
+      // FIXME: Is this the best result code?
+      errorResult = Responses.newResult(ResultCode.CLIENT_SIDE_SERVER_DOWN)
+          .setCause(error);
+    }
+    else
+    {
+      // FIXME: what other sort of IOExceptions can be thrown?
+      // FIXME: Is this the best result code?
+      errorResult = Responses.newResult(ResultCode.CLIENT_SIDE_DECODING_ERROR)
+          .setCause(error);
+    }
+    ldapConnection.close(null, false, errorResult);
+  }
+
+
+
+  @Override
+  public NextAction handleClose(final FilterChainContext ctx)
+      throws IOException
+  {
+    final Connection<?> connection = ctx.getConnection();
+    final LDAPConnection ldapConnection = LDAP_CONNECTION_ATTR
+        .remove(connection);
+    if (ldapConnection != null)
+    {
+      TimeoutChecker.INSTANCE.removeConnection(ldapConnection);
+      final Result errorResult = Responses
+          .newResult(ResultCode.CLIENT_SIDE_SERVER_DOWN);
+      ldapConnection.close(null, false, errorResult);
+    }
+    return ctx.getInvokeAction();
+  }
+
+
+
+  @Override
+  public NextAction handleRead(final FilterChainContext ctx) throws IOException
+  {
+    final Buffer buffer = (Buffer) ctx.getMessage();
+    ASN1BufferReader asn1Reader = LDAP_ASN1_READER_ATTR
+        .get(ctx.getConnection());
+    if (asn1Reader == null)
+    {
+      asn1Reader = new ASN1BufferReader(maxASN1ElementSize);
+      LDAP_ASN1_READER_ATTR.set(ctx.getConnection(), asn1Reader);
+    }
+    asn1Reader.appendBytesRead(buffer);
+
+    try
+    {
+      while (asn1Reader.elementAvailable())
+      {
+        ldapReader.decode(asn1Reader, CLIENT_RESPONSE_HANDLER, ctx);
+      }
+    }
+    finally
+    {
+      asn1Reader.disposeBytesRead();
+    }
+
+    return ctx.getStopAction();
+  }
+
+
+
+  void registerConnection(final Connection<?> connection,
+      final LDAPConnection ldapConnection)
+  {
+    TimeoutChecker.INSTANCE.addConnection(ldapConnection);
+    LDAP_CONNECTION_ATTR.set(connection, ldapConnection);
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPCompareFutureResultImpl.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPCompareFutureResultImpl.java
index 6e28919..df491a0 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/LDAPCompareFutureResultImpl.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPCompareFutureResultImpl.java
@@ -29,9 +29,7 @@
 
 
 
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.FutureResult;
-import org.opends.sdk.ResultHandler;
+import org.opends.sdk.*;
 import org.opends.sdk.requests.CompareRequest;
 import org.opends.sdk.responses.CompareResult;
 import org.opends.sdk.responses.Responses;
@@ -49,24 +47,28 @@
 
 
 
-  LDAPCompareFutureResultImpl(int messageID, CompareRequest request,
-      ResultHandler<? super CompareResult> handler,
-      LDAPConnection connection)
+  LDAPCompareFutureResultImpl(final int messageID,
+      final CompareRequest request,
+      final ResultHandler<? super CompareResult> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler,
+      final AsynchronousConnection connection)
   {
-    super(messageID, handler, connection);
+    super(messageID, resultHandler, intermediateResponseHandler, connection);
     this.request = request;
   }
 
 
 
-  /**
-   * {@inheritDoc}
-   */
-  CompareResult newErrorResult(ResultCode resultCode,
-      String diagnosticMessage, Throwable cause)
+  @Override
+  public String toString()
   {
-    return Responses.newCompareResult(resultCode).setDiagnosticMessage(
-        diagnosticMessage).setCause(cause);
+    final StringBuilder sb = new StringBuilder();
+    sb.append("LDAPCompareFutureResultImpl(");
+    sb.append("request = ");
+    sb.append(request);
+    super.toString(sb);
+    sb.append(")");
+    return sb.toString();
   }
 
 
@@ -75,4 +77,17 @@
   {
     return request;
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  CompareResult newErrorResult(final ResultCode resultCode,
+      final String diagnosticMessage, final Throwable cause)
+  {
+    return Responses.newCompareResult(resultCode).setDiagnosticMessage(
+        diagnosticMessage).setCause(cause);
+  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPConnection.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPConnection.java
index 4f6c80e..d3bed34 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/LDAPConnection.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPConnection.java
@@ -29,37 +29,29 @@
 
 
 
-import static com.sun.opends.sdk.ldap.LDAPConstants.*;
-import org.opends.sdk.ldap.LDAPEncoder;
-import org.opends.sdk.ldap.ResolvedSchema;
-
-import java.io.EOFException;
 import java.io.IOException;
-import java.net.InetSocketAddress;
+import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.net.ssl.SSLContext;
-import javax.security.sasl.SaslException;
+import javax.net.ssl.SSLEngine;
 
 import org.opends.sdk.*;
-import org.opends.sdk.controls.Control;
-import org.opends.sdk.controls.ControlDecoder;
-import org.opends.sdk.extensions.StartTLSRequest;
 import org.opends.sdk.requests.*;
 import org.opends.sdk.responses.*;
-import org.opends.sdk.sasl.SASLBindRequest;
-import org.opends.sdk.sasl.SASLContext;
-import org.opends.sdk.schema.Schema;
 
+import com.sun.grizzly.CompletionHandler;
+import com.sun.grizzly.filterchain.DefaultFilterChain;
 import com.sun.grizzly.filterchain.Filter;
 import com.sun.grizzly.filterchain.FilterChain;
-import com.sun.grizzly.filterchain.StreamTransformerFilter;
-import com.sun.grizzly.ssl.*;
-import com.sun.grizzly.streams.StreamWriter;
+import com.sun.grizzly.ssl.SSLEngineConfigurator;
+import com.sun.grizzly.ssl.SSLFilter;
+import com.sun.opends.sdk.util.CompletedFutureResult;
+import com.sun.opends.sdk.util.StaticUtils;
 import com.sun.opends.sdk.util.Validator;
 
 
@@ -69,625 +61,48 @@
  * <p>
  * TODO: handle illegal state exceptions.
  */
-public final class LDAPConnection extends
-    AbstractAsynchronousConnection implements AsynchronousConnection
+final class LDAPConnection extends AbstractAsynchronousConnection implements
+    AsynchronousConnection
 {
-
-  private final class LDAPMessageHandlerImpl extends
-      AbstractLDAPMessageHandler
-  {
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleAddResult(int messageID, Result result)
-    {
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .remove(messageID);
-      if (pendingRequest != null)
-      {
-        if (pendingRequest instanceof LDAPFutureResultImpl)
-        {
-          LDAPFutureResultImpl future = (LDAPFutureResultImpl) pendingRequest;
-          if (future.getRequest() instanceof AddRequest)
-          {
-            future.setResultOrError(result);
-            return;
-          }
-        }
-        handleIncorrectResponse(pendingRequest);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleBindResult(int messageID, BindResult result)
-    {
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .remove(messageID);
-      if (pendingRequest != null)
-      {
-        if (pendingRequest instanceof LDAPBindFutureResultImpl)
-        {
-          LDAPBindFutureResultImpl future = ((LDAPBindFutureResultImpl) pendingRequest);
-          BindRequest request = future.getRequest();
-
-          if (request instanceof SASLBindRequest<?>)
-          {
-            SASLBindRequest<?> saslBind = (SASLBindRequest<?>) request;
-            SASLContext saslContext = future.getSASLContext();
-
-            if ((result.getResultCode() == ResultCode.SUCCESS || result
-                .getResultCode() == ResultCode.SASL_BIND_IN_PROGRESS)
-                && !saslContext.isComplete())
-            {
-              try
-              {
-                saslContext.evaluateCredentials(result
-                    .getServerSASLCredentials());
-              }
-              catch (SaslException e)
-              {
-                pendingBindOrStartTLS = -1;
-
-                // FIXME: I18N need to have a better error message.
-                // FIXME: Is this the best result code?
-                Result errorResult = Responses.newResult(
-                    ResultCode.CLIENT_SIDE_LOCAL_ERROR)
-                    .setDiagnosticMessage(
-                        "An error occurred during SASL authentication")
-                    .setCause(e);
-                future.adaptErrorResult(errorResult);
-                return;
-              }
-            }
-
-            if (result.getResultCode() == ResultCode.SASL_BIND_IN_PROGRESS)
-            {
-              // The server is expecting a multi stage bind response.
-              messageID = nextMsgID.getAndIncrement();
-              ASN1StreamWriter asn1Writer = connFactory
-                  .getASN1Writer(streamWriter);
-
-              try
-              {
-                synchronized (writeLock)
-                {
-                  pendingRequests.put(messageID, future);
-                  try
-                  {
-                    LDAPEncoder.encodeBindRequest(asn1Writer,
-                        messageID, 3, saslBind, saslContext
-                            .getSASLCredentials());
-                    asn1Writer.flush();
-                  }
-                  catch (IOException e)
-                  {
-                    pendingRequests.remove(messageID);
-
-                    // FIXME: what other sort of IOExceptions can be
-                    // thrown?
-                    // FIXME: Is this the best result code?
-                    Result errorResult = Responses.newResult(
-                        ResultCode.CLIENT_SIDE_ENCODING_ERROR)
-                        .setCause(e);
-                    connectionErrorOccurred(errorResult);
-                    future.adaptErrorResult(errorResult);
-                  }
-                }
-              }
-              finally
-              {
-                connFactory.releaseASN1Writer(asn1Writer);
-              }
-              return;
-            }
-
-            if ((result.getResultCode() == ResultCode.SUCCESS)
-                && saslContext.isSecure())
-            {
-              // The connection needs to be secured by the SASL
-              // mechanism.
-              installFilter(SASLFilter.getInstance(saslContext,
-                  connection));
-            }
-          }
-          pendingBindOrStartTLS = -1;
-          future.setResultOrError(result);
-        }
-        else
-        {
-          handleIncorrectResponse(pendingRequest);
-        }
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleCompareResult(int messageID, CompareResult result)
-    {
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .remove(messageID);
-      if (pendingRequest != null)
-      {
-        if (pendingRequest instanceof LDAPCompareFutureResultImpl)
-        {
-          LDAPCompareFutureResultImpl future = (LDAPCompareFutureResultImpl) pendingRequest;
-          future.setResultOrError(result);
-        }
-        else
-        {
-          handleIncorrectResponse(pendingRequest);
-        }
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleDeleteResult(int messageID, Result result)
-    {
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .remove(messageID);
-      if (pendingRequest != null)
-      {
-        if (pendingRequest instanceof LDAPFutureResultImpl)
-        {
-          LDAPFutureResultImpl future = (LDAPFutureResultImpl) pendingRequest;
-          if (future.getRequest() instanceof DeleteRequest)
-          {
-            future.setResultOrError(result);
-            return;
-          }
-        }
-        handleIncorrectResponse(pendingRequest);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void handleException(Throwable throwable)
-    {
-      Result errorResult;
-      if (throwable instanceof EOFException)
-      {
-        // FIXME: Is this the best result code?
-        errorResult = Responses.newResult(
-            ResultCode.CLIENT_SIDE_SERVER_DOWN).setCause(throwable);
-      }
-      else
-      {
-        // FIXME: what other sort of IOExceptions can be thrown?
-        // FIXME: Is this the best result code?
-        errorResult = Responses.newResult(
-            ResultCode.CLIENT_SIDE_DECODING_ERROR).setCause(throwable);
-      }
-      connectionErrorOccurred(errorResult);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleExtendedResult(int messageID,
-        GenericExtendedResult result)
-    {
-      if (messageID == 0)
-      {
-        if ((result.getResponseName() != null)
-            && result.getResponseName().equals(
-                OID_NOTICE_OF_DISCONNECTION))
-        {
-
-          Result errorResult = Responses.newResult(
-              result.getResultCode()).setDiagnosticMessage(
-              result.getDiagnosticMessage());
-          close(null, true, errorResult);
-          return;
-        }
-        else
-        {
-          // Unsolicited notification received.
-          synchronized (writeLock)
-          {
-            if (isClosed)
-            {
-              // Don't notify after connection is closed.
-              return;
-            }
-
-            for (ConnectionEventListener listener : listeners)
-            {
-              listener
-                  .connectionReceivedUnsolicitedNotification(result);
-            }
-          }
-        }
-      }
-
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .remove(messageID);
-
-      if (pendingRequest instanceof LDAPExtendedFutureResultImpl<?>)
-      {
-        LDAPExtendedFutureResultImpl<?> extendedFuture = ((LDAPExtendedFutureResultImpl<?>) pendingRequest);
-        try
-        {
-          handleExtendedResult0(extendedFuture, result);
-        }
-        catch (DecodeException de)
-        {
-          // FIXME: should the connection be closed as well?
-          Result errorResult = Responses.newResult(
-              ResultCode.CLIENT_SIDE_DECODING_ERROR)
-              .setDiagnosticMessage(de.getLocalizedMessage()).setCause(
-                  de);
-          extendedFuture.adaptErrorResult(errorResult);
-        }
-      }
-      else
-      {
-        handleIncorrectResponse(pendingRequest);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleIntermediateResponse(int messageID,
-        GenericIntermediateResponse response)
-    {
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .remove(messageID);
-      if (pendingRequest != null)
-      {
-        handleIncorrectResponse(pendingRequest);
-
-        // FIXME: intermediate responses can occur for all operations.
-
-        // if (pendingRequest instanceof LDAPExtendedFutureResultImpl)
-        // {
-        // LDAPExtendedFutureResultImpl extendedFuture =
-        // ((LDAPExtendedFutureResultImpl) pendingRequest);
-        // ExtendedRequest request = extendedFuture.getRequest();
-        //
-        // try
-        // {
-        // IntermediateResponse decodedResponse =
-        // request.getExtendedOperation()
-        // .decodeIntermediateResponse(
-        // response.getResponseName(),
-        // response.getResponseValue());
-        // extendedFuture.handleIntermediateResponse(decodedResponse);
-        // }
-        // catch (DecodeException de)
-        // {
-        // pendingRequest.failure(de);
-        // }
-        // }
-        // else
-        // {
-        // handleIncorrectResponse(pendingRequest);
-        // }
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleModifyDNResult(int messageID, Result result)
-    {
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .remove(messageID);
-      if (pendingRequest != null)
-      {
-        if (pendingRequest instanceof LDAPFutureResultImpl)
-        {
-          LDAPFutureResultImpl future = (LDAPFutureResultImpl) pendingRequest;
-          if (future.getRequest() instanceof ModifyDNRequest)
-          {
-            future.setResultOrError(result);
-            return;
-          }
-        }
-        handleIncorrectResponse(pendingRequest);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleModifyResult(int messageID, Result result)
-    {
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .remove(messageID);
-      if (pendingRequest != null)
-      {
-        if (pendingRequest instanceof LDAPFutureResultImpl)
-        {
-          LDAPFutureResultImpl future = (LDAPFutureResultImpl) pendingRequest;
-          if (future.getRequest() instanceof ModifyRequest)
-          {
-            future.setResultOrError(result);
-            return;
-          }
-        }
-        handleIncorrectResponse(pendingRequest);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleSearchResult(int messageID, Result result)
-    {
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .remove(messageID);
-      if (pendingRequest != null)
-      {
-        if (pendingRequest instanceof LDAPSearchFutureResultImpl)
-        {
-          ((LDAPSearchFutureResultImpl) pendingRequest)
-              .setResultOrError(result);
-        }
-        else
-        {
-          handleIncorrectResponse(pendingRequest);
-        }
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleSearchResultEntry(int messageID,
-        SearchResultEntry entry)
-    {
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .get(messageID);
-      if (pendingRequest != null)
-      {
-        if (pendingRequest instanceof LDAPSearchFutureResultImpl)
-        {
-          ((LDAPSearchFutureResultImpl) pendingRequest)
-              .handleSearchResultEntry(entry);
-        }
-        else
-        {
-          handleIncorrectResponse(pendingRequest);
-        }
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void handleSearchResultReference(int messageID,
-        SearchResultReference reference)
-    {
-      AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
-          .get(messageID);
-      if (pendingRequest != null)
-      {
-        if (pendingRequest instanceof LDAPSearchFutureResultImpl)
-        {
-          ((LDAPSearchFutureResultImpl) pendingRequest)
-              .handleSearchResultReference(reference);
-        }
-        else
-        {
-          handleIncorrectResponse(pendingRequest);
-        }
-      }
-    }
-
-
-
-    @Override
-    public Control decodeResponseControl(int messageID, String oid,
-        boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      ControlDecoder<?> decoder = connFactory.getControlDecoder(oid);
-      if (decoder != null)
-      {
-        return decoder.decode(isCritical, value, schema);
-      }
-      return super.decodeResponseControl(messageID, oid, isCritical,
-          value, schema);
-    }
-
-
-
-    public ResolvedSchema resolveSchema(String dn)
-        throws DecodeException
-    {
-      DN initialDN;
-
-      try
-      {
-        initialDN = DN.valueOf(dn, schema);
-      }
-      catch (LocalizedIllegalArgumentException e)
-      {
-        throw DecodeException.error(e.getMessageObject());
-      }
-
-      return new ResolvedSchemaImpl(schema, initialDN);
-    }
-
-
-
-    public Schema getDefaultSchema()
-    {
-      return schema;
-    }
-  }
-
-
-
-  private static final class ResolvedSchemaImpl implements
-      ResolvedSchema
-  {
-    private final DN initialDN;
-
-    private final Schema schema;
-
-
-
-    private ResolvedSchemaImpl(Schema schema, DN initialDN)
-    {
-      this.schema = schema;
-      this.initialDN = initialDN;
-    }
-
-
-
-    public AttributeDescription decodeAttributeDescription(
-        String attributeDescription) throws DecodeException
-    {
-      try
-      {
-        return AttributeDescription.valueOf(attributeDescription,
-            schema);
-      }
-      catch (LocalizedIllegalArgumentException e)
-      {
-        throw DecodeException.error(e.getMessageObject());
-      }
-    }
-
-
-
-    public DN decodeDN(String dn) throws DecodeException
-    {
-      try
-      {
-        return DN.valueOf(dn, schema);
-      }
-      catch (LocalizedIllegalArgumentException e)
-      {
-        throw DecodeException.error(e.getMessageObject());
-      }
-    }
-
-
-
-    public RDN decodeRDN(String rdn) throws DecodeException
-    {
-      try
-      {
-        return RDN.valueOf(rdn, schema);
-      }
-      catch (LocalizedIllegalArgumentException e)
-      {
-        throw DecodeException.error(e.getMessageObject());
-      }
-    }
-
-
-
-    public DN getInitialDN()
-    {
-      return initialDN;
-    }
-
-
-
-    public Schema getSchema()
-    {
-      return schema;
-    }
-
-  }
-
-
-
-  private final Schema schema;
-
   private final com.sun.grizzly.Connection<?> connection;
 
   private Result connectionInvalidReason;
 
-  private final LDAPConnectionFactoryImpl connFactory;
-
   private FilterChain customFilterChain;
 
-  private final LDAPMessageHandler handler = new LDAPMessageHandlerImpl();
-
   private boolean isClosed = false;
 
-  private final List<ConnectionEventListener> listeners = new CopyOnWriteArrayList<ConnectionEventListener>();
+  private final List<ConnectionEventListener> listeners =
+    new CopyOnWriteArrayList<ConnectionEventListener>();
 
   private final AtomicInteger nextMsgID = new AtomicInteger(1);
 
-  private volatile int pendingBindOrStartTLS = -1;
+  private boolean bindOrStartTLSInProgress = false;
 
-  private final ConcurrentHashMap<Integer, AbstractLDAPFutureResultImpl<?>> pendingRequests = new ConcurrentHashMap<Integer, AbstractLDAPFutureResultImpl<?>>();
+  private final HashMap<Integer, AbstractLDAPFutureResultImpl<?>>
+    pendingRequests = new HashMap<Integer, AbstractLDAPFutureResultImpl<?>>();
 
-  private final InetSocketAddress serverAddress;
+  private final Object stateLock = new Object();
 
-  private StreamWriter streamWriter;
+  private final LDAPWriter ldapWriter = new LDAPWriter();
 
-  private final Object writeLock = new Object();
+  private final LDAPOptions options;
+
+
 
   /**
    * Creates a new LDAP connection.
    *
    * @param connection
    *          The Grizzly connection.
-   * @param serverAddress
-   *          The address of the server.
-   * @param schema
-   *          The schema which will be used to decode responses from the
-   *          server.
-   * @param connFactory
-   *          The associated connection factory.
+   * @param options
+   *          The LDAP client options.
    */
-  LDAPConnection(com.sun.grizzly.Connection<?> connection,
-      InetSocketAddress serverAddress, Schema schema,
-      LDAPConnectionFactoryImpl connFactory)
+  LDAPConnection(final com.sun.grizzly.Connection<?> connection,
+      final LDAPOptions options)
   {
     this.connection = connection;
-    this.serverAddress = serverAddress;
-    this.schema = schema;
-    this.connFactory = connFactory;
-    this.streamWriter = getFilterChainStreamWriter();
+    this.options = options;
   }
 
 
@@ -695,105 +110,121 @@
   /**
    * {@inheritDoc}
    */
-  public void abandon(AbandonRequest request)
+  public FutureResult<Void> abandon(final AbandonRequest request)
   {
-    AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
+    // First remove the future associated with the request to be abandoned.
+    final AbstractLDAPFutureResultImpl<?> pendingRequest = pendingRequests
         .remove(request.getMessageID());
-    if (pendingRequest != null)
-    {
-      pendingRequest.cancel(false);
-      int messageID = nextMsgID.getAndIncrement();
-      ASN1StreamWriter asn1Writer = connFactory
-          .getASN1Writer(streamWriter);
 
-      try
+    if (pendingRequest == null)
+    {
+      // There has never been a request with the specified message ID or the
+      // response has already been received and handled. We can ignore this
+      // abandon request.
+
+      // Message ID will be -1 since no request was sent.
+      return new CompletedFutureResult<Void>((Void) null);
+    }
+
+    pendingRequest.cancel(false);
+    final int messageID = nextMsgID.getAndIncrement();
+
+    synchronized (stateLock)
+    {
+      if (connectionInvalidReason != null)
       {
-        synchronized (writeLock)
-        {
-          if (connectionInvalidReason != null)
-          {
-            return;
-          }
-          if (pendingBindOrStartTLS > 0)
-          {
-            // This is not allowed. We will just ignore this
-            // abandon request.
-          }
-          try
-          {
-            LDAPEncoder.encodeAbandonRequest(asn1Writer, messageID,
-                request);
-            asn1Writer.flush();
-          }
-          catch (IOException e)
-          {
-            // FIXME: what other sort of IOExceptions can be thrown?
-            // FIXME: Is this the best result code?
-            Result errorResult = Responses.newResult(
-                ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
-            connectionErrorOccurred(errorResult);
-          }
-        }
+        return new CompletedFutureResult<Void>(ErrorResultException
+            .wrap(connectionInvalidReason), messageID);
       }
-      finally
+      if (bindOrStartTLSInProgress)
       {
-        connFactory.releaseASN1Writer(asn1Writer);
+        final Result errorResult = Responses.newResult(
+            ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
+            "Bind or Start TLS operation in progress");
+        return new CompletedFutureResult<Void>(ErrorResultException
+            .wrap(errorResult), messageID);
       }
     }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public FutureResult<Result> add(AddRequest request,
-      ResultHandler<Result> handler)
-  {
-    int messageID = nextMsgID.getAndIncrement();
-    LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID, request,
-        handler, this);
-    ASN1StreamWriter asn1Writer = connFactory
-        .getASN1Writer(streamWriter);
 
     try
     {
-      synchronized (writeLock)
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
       {
-        if (connectionInvalidReason != null)
-        {
-          future.adaptErrorResult(connectionInvalidReason);
-          return future;
-        }
-        if (pendingBindOrStartTLS > 0)
-        {
-          future.setResultOrError(Responses.newResult(
-              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
-              "Bind or Start TLS operation in progress"));
-          return future;
-        }
-        pendingRequests.put(messageID, future);
-        try
-        {
-          LDAPEncoder.encodeAddRequest(asn1Writer, messageID, request);
-          asn1Writer.flush();
-        }
-        catch (IOException e)
-        {
-          pendingRequests.remove(messageID);
-
-          // FIXME: what other sort of IOExceptions can be thrown?
-          // FIXME: Is this the best result code?
-          Result errorResult = Responses.newResult(
-              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
-          connectionErrorOccurred(errorResult);
-          future.adaptErrorResult(errorResult);
-        }
+        ldapWriter.abandonRequest(asn1Writer, messageID, request);
+        connection.write(asn1Writer.getBuffer(), null);
+        return new CompletedFutureResult<Void>((Void) null, messageID);
+      }
+      finally
+      {
+        asn1Writer.recycle();
       }
     }
-    finally
+    catch (final IOException e)
     {
-      connFactory.releaseASN1Writer(asn1Writer);
+      // FIXME: what other sort of IOExceptions can be thrown?
+      // FIXME: Is this the best result code?
+      final Result errorResult = Responses.newResult(
+          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
+      connectionErrorOccurred(errorResult);
+      return new CompletedFutureResult<Void>(ErrorResultException
+          .wrap(errorResult), messageID);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Result> add(final AddRequest request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+  {
+    final int messageID = nextMsgID.getAndIncrement();
+    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID,
+        request, resultHandler, intermediateResponseHandler, this);
+
+    synchronized (stateLock)
+    {
+      if (connectionInvalidReason != null)
+      {
+        future.adaptErrorResult(connectionInvalidReason);
+        return future;
+      }
+      if (bindOrStartTLSInProgress)
+      {
+        future.setResultOrError(Responses
+            .newResult(ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
+                "Bind or Start TLS operation in progress"));
+        return future;
+      }
+      pendingRequests.put(messageID, future);
+    }
+
+    try
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        ldapWriter.addRequest(asn1Writer, messageID, request);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+    }
+    catch (final IOException e)
+    {
+      pendingRequests.remove(messageID);
+
+      // FIXME: what other sort of IOExceptions can be thrown?
+      // FIXME: Is this the best result code?
+      final Result errorResult = Responses.newResult(
+          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
+      connectionErrorOccurred(errorResult);
+      future.adaptErrorResult(errorResult);
     }
 
     return future;
@@ -804,9 +235,8 @@
   /**
    * {@inheritDoc}
    */
-  public void addConnectionEventListener(
-      ConnectionEventListener listener) throws IllegalStateException,
-      NullPointerException
+  public void addConnectionEventListener(final ConnectionEventListener listener)
+      throws IllegalStateException, NullPointerException
   {
     Validator.ensureNotNull(listener);
     listeners.add(listener);
@@ -817,98 +247,88 @@
   /**
    * {@inheritDoc}
    */
-  public FutureResult<BindResult> bind(BindRequest request,
-      ResultHandler<? super BindResult> handler)
+  public FutureResult<BindResult> bind(final BindRequest request,
+      final ResultHandler<? super BindResult> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
   {
-    int messageID = nextMsgID.getAndIncrement();
-    LDAPBindFutureResultImpl future = new LDAPBindFutureResultImpl(messageID,
-        request, handler, this);
-    ASN1StreamWriter asn1Writer = connFactory
-        .getASN1Writer(streamWriter);
+    final int messageID = nextMsgID.getAndIncrement();
+
+    BindClient context;
+    try
+    {
+      context = request
+          .createBindClient(connection.getPeerAddress().toString());
+    }
+    catch (final Exception e)
+    {
+      // FIXME: I18N need to have a better error message.
+      // FIXME: Is this the best result code?
+      final Result errorResult = Responses.newResult(
+          ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+          "An error occurred while creating a bind context").setCause(e);
+      final ErrorResultException error = ErrorResultException.wrap(errorResult);
+      if (resultHandler != null)
+      {
+        resultHandler.handleErrorResult(error);
+      }
+      return new CompletedFutureResult<BindResult>(error, messageID);
+    }
+
+    final LDAPBindFutureResultImpl future = new LDAPBindFutureResultImpl(
+        messageID, context, resultHandler, intermediateResponseHandler, this);
+
+    synchronized (stateLock)
+    {
+      if (connectionInvalidReason != null)
+      {
+        future.adaptErrorResult(connectionInvalidReason);
+        return future;
+      }
+      if (bindOrStartTLSInProgress)
+      {
+        future.setResultOrError(Responses.newBindResult(
+            ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
+            "Bind or Start TLS operation in progress"));
+        return future;
+      }
+      if (!pendingRequests.isEmpty())
+      {
+        future.setResultOrError(Responses.newBindResult(
+            ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
+            "There are other operations pending on this connection"));
+        return future;
+      }
+
+      pendingRequests.put(messageID, future);
+      bindOrStartTLSInProgress = true;
+    }
 
     try
     {
-      synchronized (writeLock)
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
       {
-        if (connectionInvalidReason != null)
-        {
-          future.adaptErrorResult(connectionInvalidReason);
-          return future;
-        }
-        if (pendingBindOrStartTLS > 0)
-        {
-          future.setResultOrError(Responses.newBindResult(
-              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
-              "Bind or Start TLS operation in progress"));
-          return future;
-        }
-        if (!pendingRequests.isEmpty())
-        {
-          future.setResultOrError(Responses.newBindResult(
-              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
-              "There are other operations pending on this connection"));
-          return future;
-        }
-
-        pendingRequests.put(messageID, future);
-        pendingBindOrStartTLS = messageID;
-
-        try
-        {
-          if (request instanceof SASLBindRequest<?>)
-          {
-            try
-            {
-              SASLBindRequest<?> saslBind = (SASLBindRequest<?>) request;
-              SASLContext saslContext = saslBind
-                  .getClientContext(serverAddress.getHostName());
-              future.setSASLContext(saslContext);
-              LDAPEncoder.encodeBindRequest(asn1Writer, messageID, 3,
-                  saslBind, saslContext.getSASLCredentials());
-            }
-            catch (SaslException e)
-            {
-              // FIXME: I18N need to have a better error message.
-              // FIXME: Is this the best result code?
-              Result errorResult = Responses.newResult(
-                  ResultCode.CLIENT_SIDE_LOCAL_ERROR)
-                  .setDiagnosticMessage(
-                      "An error occurred during SASL authentication")
-                  .setCause(e);
-              future.adaptErrorResult(errorResult);
-              return future;
-            }
-          }
-          else if (request instanceof SimpleBindRequest)
-          {
-            LDAPEncoder.encodeBindRequest(asn1Writer, messageID, 3,
-                (SimpleBindRequest) request);
-          }
-          else
-          {
-            pendingRequests.remove(messageID);
-            future.setResultOrError(Responses.newBindResult(
-                ResultCode.CLIENT_SIDE_AUTH_UNKNOWN)
-                .setDiagnosticMessage("Auth type not supported"));
-          }
-          asn1Writer.flush();
-        }
-        catch (IOException e)
-        {
-          pendingRequests.remove(messageID);
-
-          // FIXME: what other sort of IOExceptions can be thrown?
-          // FIXME: Is this the best result code?
-          Result errorResult = Responses.newResult(
-              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
-          connectionErrorOccurred(errorResult);
-          future.adaptErrorResult(errorResult);
-        }
+        // Use the bind client to get the initial request instead of using the
+        // bind request passed to this method.
+        final GenericBindRequest initialRequest = context.nextBindRequest();
+        ldapWriter.bindRequest(asn1Writer, messageID, 3, initialRequest);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      finally
+      {
+        asn1Writer.recycle();
       }
     }
-    finally
+    catch (final IOException e)
     {
-      connFactory.releaseASN1Writer(asn1Writer);
+      pendingRequests.remove(messageID);
+
+      // FIXME: what other sort of IOExceptions can be thrown?
+      // FIXME: Is this the best result code?
+      final Result errorResult = Responses.newResult(
+          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
+      connectionErrorOccurred(errorResult);
+      future.adaptErrorResult(errorResult);
     }
 
     return future;
@@ -919,7 +339,7 @@
   /**
    * {@inheritDoc}
    */
-  public void close(UnbindRequest request, String reason)
+  public void close(final UnbindRequest request, final String reason)
       throws NullPointerException
   {
     // FIXME: I18N need to internationalize this message.
@@ -927,8 +347,7 @@
 
     close(request, false, Responses.newResult(
         ResultCode.CLIENT_SIDE_USER_CANCELLED).setDiagnosticMessage(
-        "Connection closed by client"
-            + (reason != null ? ": " + reason : "")));
+        "Connection closed by client" + (reason != null ? ": " + reason : "")));
   }
 
 
@@ -936,54 +355,54 @@
   /**
    * {@inheritDoc}
    */
-  public FutureResult<CompareResult> compare(CompareRequest request,
-      ResultHandler<? super CompareResult> handler)
+  public FutureResult<CompareResult> compare(final CompareRequest request,
+      final ResultHandler<? super CompareResult> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
   {
-    int messageID = nextMsgID.getAndIncrement();
-    LDAPCompareFutureResultImpl future = new LDAPCompareFutureResultImpl(
-        messageID, request, handler, this);
-    ASN1StreamWriter asn1Writer = connFactory
-        .getASN1Writer(streamWriter);
+    final int messageID = nextMsgID.getAndIncrement();
+    final LDAPCompareFutureResultImpl future = new LDAPCompareFutureResultImpl(
+        messageID, request, resultHandler, intermediateResponseHandler, this);
+
+    synchronized (stateLock)
+    {
+      if (connectionInvalidReason != null)
+      {
+        future.adaptErrorResult(connectionInvalidReason);
+        return future;
+      }
+      if (bindOrStartTLSInProgress)
+      {
+        future.setResultOrError(Responses.newCompareResult(
+            ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
+            "Bind or Start TLS operation in progress"));
+        return future;
+      }
+      pendingRequests.put(messageID, future);
+    }
 
     try
     {
-      synchronized (writeLock)
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
       {
-        if (connectionInvalidReason != null)
-        {
-          future.adaptErrorResult(connectionInvalidReason);
-          return future;
-        }
-        if (pendingBindOrStartTLS > 0)
-        {
-          future.setResultOrError(Responses.newCompareResult(
-              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
-              "Bind or Start TLS operation in progress"));
-          return future;
-        }
-        pendingRequests.put(messageID, future);
-        try
-        {
-          LDAPEncoder.encodeCompareRequest(asn1Writer, messageID,
-              request);
-          asn1Writer.flush();
-        }
-        catch (IOException e)
-        {
-          pendingRequests.remove(messageID);
-
-          // FIXME: what other sort of IOExceptions can be thrown?
-          // FIXME: Is this the best result code?
-          Result errorResult = Responses.newResult(
-              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
-          connectionErrorOccurred(errorResult);
-          future.adaptErrorResult(errorResult);
-        }
+        ldapWriter.compareRequest(asn1Writer, messageID, request);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      finally
+      {
+        asn1Writer.recycle();
       }
     }
-    finally
+    catch (final IOException e)
     {
-      connFactory.releaseASN1Writer(asn1Writer);
+      pendingRequests.remove(messageID);
+
+      // FIXME: what other sort of IOExceptions can be thrown?
+      // FIXME: Is this the best result code?
+      final Result errorResult = Responses.newResult(
+          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
+      connectionErrorOccurred(errorResult);
+      future.adaptErrorResult(errorResult);
     }
 
     return future;
@@ -994,54 +413,54 @@
   /**
    * {@inheritDoc}
    */
-  public FutureResult<Result> delete(DeleteRequest request,
-      ResultHandler<Result> handler)
+  public FutureResult<Result> delete(final DeleteRequest request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
   {
-    int messageID = nextMsgID.getAndIncrement();
-    LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID, request,
-        handler, this);
-    ASN1StreamWriter asn1Writer = connFactory
-        .getASN1Writer(streamWriter);
+    final int messageID = nextMsgID.getAndIncrement();
+    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID,
+        request, resultHandler, intermediateResponseHandler, this);
+
+    synchronized (stateLock)
+    {
+      if (connectionInvalidReason != null)
+      {
+        future.adaptErrorResult(connectionInvalidReason);
+        return future;
+      }
+      if (bindOrStartTLSInProgress)
+      {
+        future.setResultOrError(Responses
+            .newResult(ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
+                "Bind or Start TLS operation in progress"));
+        return future;
+      }
+      pendingRequests.put(messageID, future);
+    }
 
     try
     {
-      synchronized (writeLock)
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
       {
-        if (connectionInvalidReason != null)
-        {
-          future.adaptErrorResult(connectionInvalidReason);
-          return future;
-        }
-        if (pendingBindOrStartTLS > 0)
-        {
-          future.setResultOrError(Responses.newResult(
-              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
-              "Bind or Start TLS operation in progress"));
-          return future;
-        }
-        pendingRequests.put(messageID, future);
-        try
-        {
-          LDAPEncoder.encodeDeleteRequest(asn1Writer, messageID,
-              request);
-          asn1Writer.flush();
-        }
-        catch (IOException e)
-        {
-          pendingRequests.remove(messageID);
-
-          // FIXME: what other sort of IOExceptions can be thrown?
-          // FIXME: Is this the best result code?
-          Result errorResult = Responses.newResult(
-              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
-          connectionErrorOccurred(errorResult);
-          future.adaptErrorResult(errorResult);
-        }
+        ldapWriter.deleteRequest(asn1Writer, messageID, request);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      finally
+      {
+        asn1Writer.recycle();
       }
     }
-    finally
+    catch (final IOException e)
     {
-      connFactory.releaseASN1Writer(asn1Writer);
+      pendingRequests.remove(messageID);
+
+      // FIXME: what other sort of IOExceptions can be thrown?
+      // FIXME: Is this the best result code?
+      final Result errorResult = Responses.newResult(
+          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
+      connectionErrorOccurred(errorResult);
+      future.adaptErrorResult(errorResult);
     }
 
     return future;
@@ -1052,73 +471,72 @@
   /**
    * {@inheritDoc}
    */
-  public <R extends Result> FutureResult<R> extendedRequest(
-      ExtendedRequest<R> request, ResultHandler<? super R> handler)
+  public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+      final ExtendedRequest<R> request,
+      final ResultHandler<? super R> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
   {
-    int messageID = nextMsgID.getAndIncrement();
-    LDAPExtendedFutureResultImpl<R> future = new LDAPExtendedFutureResultImpl<R>(
-        messageID, request, handler, this);
-    ASN1StreamWriter asn1Writer = connFactory
-        .getASN1Writer(streamWriter);
+    final int messageID = nextMsgID.getAndIncrement();
+    final LDAPExtendedFutureResultImpl<R> future = new LDAPExtendedFutureResultImpl<R>(
+        messageID, request, resultHandler, intermediateResponseHandler, this);
+
+    synchronized (stateLock)
+    {
+      if (connectionInvalidReason != null)
+      {
+        future.adaptErrorResult(connectionInvalidReason);
+        return future;
+      }
+      if (bindOrStartTLSInProgress)
+      {
+        future.setResultOrError(request.getResultDecoder()
+            .adaptExtendedErrorResult(ResultCode.OPERATIONS_ERROR, "",
+                "Bind or Start TLS operation in progress"));
+        return future;
+      }
+      if (request.getOID().equals(StartTLSExtendedRequest.OID))
+      {
+        if (!pendingRequests.isEmpty())
+        {
+          future.setResultOrError(request.getResultDecoder()
+              .adaptExtendedErrorResult(ResultCode.OPERATIONS_ERROR, "",
+                  "There are pending operations on this connection"));
+          return future;
+        }
+        if (isTLSEnabled())
+        {
+          future.setResultOrError(request.getResultDecoder()
+              .adaptExtendedErrorResult(ResultCode.OPERATIONS_ERROR, "",
+                  "This connection is already TLS enabled"));
+        }
+        bindOrStartTLSInProgress = true;
+      }
+      pendingRequests.put(messageID, future);
+    }
 
     try
     {
-      synchronized (writeLock)
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
       {
-        if (connectionInvalidReason != null)
-        {
-          future.adaptErrorResult(connectionInvalidReason);
-          return future;
-        }
-        if (pendingBindOrStartTLS > 0)
-        {
-          future.setResultOrError(request.getExtendedOperation()
-              .decodeResponse(ResultCode.OPERATIONS_ERROR, "",
-                  "Bind or Start TLS operation in progress"));
-          return future;
-        }
-        if (request.getRequestName().equals(
-            StartTLSRequest.OID_START_TLS_REQUEST))
-        {
-          if (!pendingRequests.isEmpty())
-          {
-            future.setResultOrError(request.getExtendedOperation()
-                .decodeResponse(ResultCode.OPERATIONS_ERROR, "",
-                    "There are pending operations on this connection"));
-            return future;
-          }
-          if (isTLSEnabled())
-          {
-            future.setResultOrError(request.getExtendedOperation()
-                .decodeResponse(ResultCode.OPERATIONS_ERROR, "",
-                    "This connection is already TLS enabled"));
-          }
-          pendingBindOrStartTLS = messageID;
-        }
-        pendingRequests.put(messageID, future);
-
-        try
-        {
-          LDAPEncoder.encodeExtendedRequest(asn1Writer, messageID,
-              request);
-          asn1Writer.flush();
-        }
-        catch (IOException e)
-        {
-          pendingRequests.remove(messageID);
-
-          // FIXME: what other sort of IOExceptions can be thrown?
-          // FIXME: Is this the best result code?
-          Result errorResult = Responses.newResult(
-              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
-          connectionErrorOccurred(errorResult);
-          future.adaptErrorResult(errorResult);
-        }
+        ldapWriter.extendedRequest(asn1Writer, messageID, request);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      finally
+      {
+        asn1Writer.recycle();
       }
     }
-    finally
+    catch (final IOException e)
     {
-      connFactory.releaseASN1Writer(asn1Writer);
+      pendingRequests.remove(messageID);
+
+      // FIXME: what other sort of IOExceptions can be thrown?
+      // FIXME: Is this the best result code?
+      final Result errorResult = Responses.newResult(
+          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
+      connectionErrorOccurred(errorResult);
+      future.adaptErrorResult(errorResult);
     }
 
     return future;
@@ -1129,54 +547,74 @@
   /**
    * {@inheritDoc}
    */
-  public FutureResult<Result> modify(ModifyRequest request,
-      ResultHandler<Result> handler)
+  public boolean isClosed()
   {
-    int messageID = nextMsgID.getAndIncrement();
-    LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID, request,
-        handler, this);
-    ASN1StreamWriter asn1Writer = connFactory
-        .getASN1Writer(streamWriter);
+    return isClosed;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isValid()
+  {
+    return connectionInvalidReason == null && !isClosed;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Result> modify(final ModifyRequest request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+  {
+    final int messageID = nextMsgID.getAndIncrement();
+    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID,
+        request, resultHandler, intermediateResponseHandler, this);
+
+    synchronized (stateLock)
+    {
+      if (connectionInvalidReason != null)
+      {
+        future.adaptErrorResult(connectionInvalidReason);
+        return future;
+      }
+      if (bindOrStartTLSInProgress)
+      {
+        future.setResultOrError(Responses
+            .newResult(ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
+                "Bind or Start TLS operation in progress"));
+        return future;
+      }
+      pendingRequests.put(messageID, future);
+    }
 
     try
     {
-      synchronized (writeLock)
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
       {
-        if (connectionInvalidReason != null)
-        {
-          future.adaptErrorResult(connectionInvalidReason);
-          return future;
-        }
-        if (pendingBindOrStartTLS > 0)
-        {
-          future.setResultOrError(Responses.newResult(
-              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
-              "Bind or Start TLS operation in progress"));
-          return future;
-        }
-        pendingRequests.put(messageID, future);
-        try
-        {
-          LDAPEncoder.encodeModifyRequest(asn1Writer, messageID,
-              request);
-          asn1Writer.flush();
-        }
-        catch (IOException e)
-        {
-          pendingRequests.remove(messageID);
-
-          // FIXME: what other sort of IOExceptions can be thrown?
-          // FIXME: Is this the best result code?
-          Result errorResult = Responses.newResult(
-              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
-          connectionErrorOccurred(errorResult);
-          future.adaptErrorResult(errorResult);
-        }
+        ldapWriter.modifyRequest(asn1Writer, messageID, request);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      finally
+      {
+        asn1Writer.recycle();
       }
     }
-    finally
+    catch (final IOException e)
     {
-      connFactory.releaseASN1Writer(asn1Writer);
+      pendingRequests.remove(messageID);
+
+      // FIXME: what other sort of IOExceptions can be thrown?
+      // FIXME: Is this the best result code?
+      final Result errorResult = Responses.newResult(
+          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
+      connectionErrorOccurred(errorResult);
+      future.adaptErrorResult(errorResult);
     }
 
     return future;
@@ -1187,54 +625,54 @@
   /**
    * {@inheritDoc}
    */
-  public FutureResult<Result> modifyDN(ModifyDNRequest request,
-      ResultHandler<Result> handler)
+  public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
   {
-    int messageID = nextMsgID.getAndIncrement();
-    LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID, request,
-        handler, this);
-    ASN1StreamWriter asn1Writer = connFactory
-        .getASN1Writer(streamWriter);
+    final int messageID = nextMsgID.getAndIncrement();
+    final LDAPFutureResultImpl future = new LDAPFutureResultImpl(messageID,
+        request, resultHandler, intermediateResponseHandler, this);
+
+    synchronized (stateLock)
+    {
+      if (connectionInvalidReason != null)
+      {
+        future.adaptErrorResult(connectionInvalidReason);
+        return future;
+      }
+      if (bindOrStartTLSInProgress)
+      {
+        future.setResultOrError(Responses
+            .newResult(ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
+                "Bind or Start TLS operation in progress"));
+        return future;
+      }
+      pendingRequests.put(messageID, future);
+    }
 
     try
     {
-      synchronized (writeLock)
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
       {
-        if (connectionInvalidReason != null)
-        {
-          future.adaptErrorResult(connectionInvalidReason);
-          return future;
-        }
-        if (pendingBindOrStartTLS > 0)
-        {
-          future.setResultOrError(Responses.newResult(
-              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
-              "Bind or Start TLS operation in progress"));
-          return future;
-        }
-        pendingRequests.put(messageID, future);
-        try
-        {
-          LDAPEncoder.encodeModifyDNRequest(asn1Writer, messageID,
-              request);
-          asn1Writer.flush();
-        }
-        catch (IOException e)
-        {
-          pendingRequests.remove(messageID);
-
-          // FIXME: what other sort of IOExceptions can be thrown?
-          // FIXME: Is this the best result code?
-          Result errorResult = Responses.newResult(
-              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
-          connectionErrorOccurred(errorResult);
-          future.adaptErrorResult(errorResult);
-        }
+        ldapWriter.modifyDNRequest(asn1Writer, messageID, request);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      finally
+      {
+        asn1Writer.recycle();
       }
     }
-    finally
+    catch (final IOException e)
     {
-      connFactory.releaseASN1Writer(asn1Writer);
+      pendingRequests.remove(messageID);
+
+      // FIXME: what other sort of IOExceptions can be thrown?
+      // FIXME: Is this the best result code?
+      final Result errorResult = Responses.newResult(
+          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
+      connectionErrorOccurred(errorResult);
+      future.adaptErrorResult(errorResult);
     }
 
     return future;
@@ -1246,7 +684,7 @@
    * {@inheritDoc}
    */
   public void removeConnectionEventListener(
-      ConnectionEventListener listener) throws NullPointerException
+      final ConnectionEventListener listener) throws NullPointerException
   {
     Validator.ensureNotNull(listener);
     listeners.remove(listener);
@@ -1257,55 +695,56 @@
   /**
    * {@inheritDoc}
    */
-  public FutureResult<Result> search(SearchRequest request,
-      ResultHandler<Result> resultHandler,
-      SearchResultHandler searchResulthandler)
+  public FutureResult<Result> search(final SearchRequest request,
+      final ResultHandler<Result> resultHandler,
+      final SearchResultHandler searchResultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
   {
-    int messageID = nextMsgID.getAndIncrement();
-    LDAPSearchFutureResultImpl future = new LDAPSearchFutureResultImpl(
-        messageID, request, resultHandler, searchResulthandler, this);
-    ASN1StreamWriter asn1Writer = connFactory
-        .getASN1Writer(streamWriter);
+    final int messageID = nextMsgID.getAndIncrement();
+    final LDAPSearchFutureResultImpl future = new LDAPSearchFutureResultImpl(
+        messageID, request, resultHandler, searchResultHandler,
+        intermediateResponseHandler, this);
+
+    synchronized (stateLock)
+    {
+      if (connectionInvalidReason != null)
+      {
+        future.adaptErrorResult(connectionInvalidReason);
+        return future;
+      }
+      if (bindOrStartTLSInProgress)
+      {
+        future.setResultOrError(Responses
+            .newResult(ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
+                "Bind or Start TLS operation in progress"));
+        return future;
+      }
+      pendingRequests.put(messageID, future);
+    }
 
     try
     {
-      synchronized (writeLock)
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
       {
-        if (connectionInvalidReason != null)
-        {
-          future.adaptErrorResult(connectionInvalidReason);
-          return future;
-        }
-        if (pendingBindOrStartTLS > 0)
-        {
-          future.setResultOrError(Responses.newResult(
-              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
-              "Bind or Start TLS operation in progress"));
-          return future;
-        }
-        pendingRequests.put(messageID, future);
-        try
-        {
-          LDAPEncoder.encodeSearchRequest(asn1Writer, messageID,
-              request);
-          asn1Writer.flush();
-        }
-        catch (IOException e)
-        {
-          pendingRequests.remove(messageID);
-
-          // FIXME: what other sort of IOExceptions can be thrown?
-          // FIXME: Is this the best result code?
-          Result errorResult = Responses.newResult(
-              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
-          connectionErrorOccurred(errorResult);
-          future.adaptErrorResult(errorResult);
-        }
+        ldapWriter.searchRequest(asn1Writer, messageID, request);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      finally
+      {
+        asn1Writer.recycle();
       }
     }
-    finally
+    catch (final IOException e)
     {
-      connFactory.releaseASN1Writer(asn1Writer);
+      pendingRequests.remove(messageID);
+
+      // FIXME: what other sort of IOExceptions can be thrown?
+      // FIXME: Is this the best result code?
+      final Result errorResult = Responses.newResult(
+          ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
+      connectionErrorOccurred(errorResult);
+      future.adaptErrorResult(errorResult);
     }
 
     return future;
@@ -1313,40 +752,58 @@
 
 
 
-  /**
-   * Returns the LDAP message handler associated with this connection.
-   *
-   * @return The LDAP message handler associated with this connection.
-   */
-  LDAPMessageHandler getLDAPMessageHandler()
+  int addPendingRequest(final AbstractLDAPFutureResultImpl<?> request)
   {
-    return handler;
+    final int newMsgID = nextMsgID.getAndIncrement();
+    pendingRequests.put(newMsgID, request);
+    return newMsgID;
   }
 
 
 
-  /**
-   * Indicates whether or not TLS is enabled on this connection.
-   *
-   * @return {@code true} if TLS is enabled on this connection,
-   *         otherwise {@code false}.
-   */
-  boolean isTLSEnabled()
+  long cancelExpiredRequests(final long currentTime)
   {
-    FilterChain currentFilterChain = (FilterChain) connection
-        .getProcessor();
-    return currentFilterChain.get(2) instanceof SSLFilter;
+    final long timeout = options.getTimeout(TimeUnit.MILLISECONDS);
+    long delay = timeout;
+    if (timeout > 0)
+    {
+      synchronized (stateLock)
+      {
+        for (final Iterator<AbstractLDAPFutureResultImpl<?>> i = pendingRequests
+            .values().iterator(); i.hasNext();)
+        {
+          final AbstractLDAPFutureResultImpl<?> future = i.next();
+          final long diff = (future.getTimestamp() + timeout) - currentTime;
+          if (diff <= 0)
+          {
+            StaticUtils.DEBUG_LOG.fine("Cancelling expired future result: "
+                + future);
+            final Result result = Responses
+                .newResult(ResultCode.CLIENT_SIDE_TIMEOUT);
+            future.adaptErrorResult(result);
+            i.remove();
+
+            abandon(Requests.newAbandonRequest(future.getRequestID()));
+          }
+          else
+          {
+            delay = Math.min(delay, diff);
+          }
+        }
+      }
+    }
+    return delay;
   }
 
 
 
-  private void close(UnbindRequest unbindRequest,
-      boolean isDisconnectNotification, Result reason)
+  void close(final UnbindRequest unbindRequest,
+      final boolean isDisconnectNotification, final Result reason)
   {
     boolean notifyClose = false;
     boolean notifyErrorOccurred = false;
 
-    synchronized (writeLock)
+    synchronized (stateLock)
     {
       if (isClosed)
       {
@@ -1376,30 +833,31 @@
     }
 
     // First abort all outstanding requests.
-    for (AbstractLDAPFutureResultImpl<?> future : pendingRequests
+    for (final AbstractLDAPFutureResultImpl<?> future : pendingRequests
         .values())
     {
-      if (pendingBindOrStartTLS <= 0)
+      if (!bindOrStartTLSInProgress)
       {
-        ASN1StreamWriter asn1Writer = connFactory
-            .getASN1Writer(streamWriter);
-        int messageID = nextMsgID.getAndIncrement();
-        AbandonRequest abandon = Requests.newAbandonRequest(future
+        final int messageID = nextMsgID.getAndIncrement();
+        final AbandonRequest abandon = Requests.newAbandonRequest(future
             .getRequestID());
         try
         {
-          LDAPEncoder.encodeAbandonRequest(asn1Writer, messageID,
-                                           abandon);
-          asn1Writer.flush();
+          final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+          try
+          {
+            ldapWriter.abandonRequest(asn1Writer, messageID, abandon);
+            connection.write(asn1Writer.getBuffer(), null);
+          }
+          finally
+          {
+            asn1Writer.recycle();
+          }
         }
-        catch (IOException e)
+        catch (final IOException e)
         {
           // Underlying channel probably blown up. Just ignore.
         }
-        finally
-        {
-          connFactory.releaseASN1Writer(asn1Writer);
-        }
       }
 
       future.adaptErrorResult(reason);
@@ -1407,45 +865,34 @@
     pendingRequests.clear();
 
     // Now try cleanly closing the connection if possible.
-    try
+    // Only send unbind if specified.
+    if (unbindRequest != null)
     {
-      ASN1StreamWriter asn1Writer = connFactory
-          .getASN1Writer(streamWriter);
-      if (unbindRequest == null)
-      {
-        unbindRequest = Requests.newUnbindRequest();
-      }
-
       try
       {
-        LDAPEncoder.encodeUnbindRequest(asn1Writer, nextMsgID
-            .getAndIncrement(), unbindRequest);
-        asn1Writer.flush();
+        final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+        try
+        {
+          ldapWriter.unbindRequest(asn1Writer, nextMsgID.getAndIncrement(),
+              unbindRequest);
+          connection.write(asn1Writer.getBuffer(), null);
+        }
+        finally
+        {
+          asn1Writer.recycle();
+        }
       }
-      finally
+      catch (final IOException e)
       {
-        connFactory.releaseASN1Writer(asn1Writer);
+        // Underlying channel prob blown up. Just ignore.
       }
     }
-    catch (IOException e)
-    {
-      // Underlying channel prob blown up. Just ignore.
-    }
-
-    try
-    {
-      streamWriter.close();
-    }
-    catch (IOException e)
-    {
-      // Ignore.
-    }
 
     try
     {
       connection.close();
     }
-    catch (IOException e)
+    catch (final IOException e)
     {
       // Ignore.
     }
@@ -1453,205 +900,120 @@
     // Notify listeners.
     if (notifyClose)
     {
-      // TODO: uncomment if close notification is required.
-      // for (ConnectionEventListener listener : listeners)
-      // {
-      // listener.connectionClosed(this);
-      // }
+      for (final ConnectionEventListener listener : listeners)
+      {
+        listener.connectionClosed();
+      }
     }
 
     if (notifyErrorOccurred)
     {
-      for (ConnectionEventListener listener : listeners)
+      for (final ConnectionEventListener listener : listeners)
       {
         listener.connectionErrorOccurred(isDisconnectNotification,
-                                         ErrorResultException.wrap(reason));
+            ErrorResultException.wrap(reason));
       }
     }
   }
 
 
 
-  private void connectionErrorOccurred(Result reason)
+  LDAPOptions getLDAPOptions()
   {
-    close(null, false, reason);
+    return options;
   }
 
 
 
-  // TODO uncomment if we decide these methods are useful.
-  /**
-   * {@inheritDoc}
-   */
-  public boolean isClosed()
+  AbstractLDAPFutureResultImpl<?> getPendingRequest(final Integer messageID)
   {
-    return isClosed;
+    return pendingRequests.get(messageID);
   }
 
 
 
-  /**
-   * {@inheritDoc}
-   */
-  public boolean isValid()
+  synchronized void handleUnsolicitedNotification(final ExtendedResult result)
   {
-    return connectionInvalidReason == null && !isClosed;
-  }
-  //
-  //
-  //
-  // /**
-  // * {@inheritDoc}
-  // */
-  // public boolean isValid(long timeout, TimeUnit unit)
-  // throws InterruptedException, TimeoutException
-  // {
-  // // FIXME: no support for timeout.
-  // return isValid();
-  // }
-
-  private StreamWriter getFilterChainStreamWriter()
-  {
-    StreamWriter writer = connection.getStreamWriter();
-    FilterChain currentFilterChain = (FilterChain) connection
-        .getProcessor();
-    for (Filter filter : currentFilterChain)
+    if (isClosed)
     {
-      if (filter instanceof StreamTransformerFilter)
-      {
-        writer = ((StreamTransformerFilter) filter)
-            .getStreamWriter(writer);
-      }
+      // Don't notify after connection is closed.
+      return;
     }
 
-    return writer;
-  }
-
-
-
-  // Needed in order to expose type information.
-  private <R extends Result> void handleExtendedResult0(
-      LDAPExtendedFutureResultImpl<R> future, GenericExtendedResult result)
-      throws DecodeException
-  {
-    R decodedResponse = future.decodeResponse(result.getResultCode(),
-        result.getMatchedDN(), result.getDiagnosticMessage(), result
-            .getResponseName(), result.getResponseValue());
-
-    if (future.getRequest() instanceof StartTLSRequest)
+    for (final ConnectionEventListener listener : listeners)
     {
-      if (result.getResultCode() == ResultCode.SUCCESS)
-      {
-        StartTLSRequest request = (StartTLSRequest) future.getRequest();
-        try
-        {
-          startTLS(request.getSSLContext());
-        }
-        catch (ErrorResultException e)
-        {
-          future.adaptErrorResult(e.getResult());
-          return;
-        }
-      }
-      pendingBindOrStartTLS = -1;
-    }
-
-    future.setResultOrError(decodedResponse);
-  }
-
-
-
-  private void handleIncorrectResponse(
-      AbstractLDAPFutureResultImpl<?> pendingRequest)
-  {
-    // FIXME: I18N need to have a better error message.
-    Result errorResult = Responses.newResult(
-        ResultCode.CLIENT_SIDE_DECODING_ERROR).setDiagnosticMessage(
-        "LDAP response message did not match request");
-
-    pendingRequest.adaptErrorResult(errorResult);
-    connectionErrorOccurred(errorResult);
-  }
-
-
-
-  private void startTLS(SSLContext sslContext)
-      throws ErrorResultException
-  {
-    SSLHandshaker sslHandshaker = connFactory.getSslHandshaker();
-    SSLFilter sslFilter;
-    SSLEngineConfigurator sslEngineConfigurator;
-    if (sslContext == connFactory.getSSLContext())
-    {
-      // Use factory SSL objects since it is the same SSLContext
-      sslFilter = connFactory.getSSlFilter();
-      sslEngineConfigurator = connFactory.getSSlEngineConfigurator();
-    }
-    else
-    {
-      sslEngineConfigurator = new SSLEngineConfigurator(sslContext,
-          true, false, false);
-      sslFilter = new SSLFilter(sslEngineConfigurator, sslHandshaker);
-    }
-    installFilter(sslFilter);
-
-    performSSLHandshake(sslHandshaker, sslEngineConfigurator);
-  }
-
-
-
-  void performSSLHandshake(SSLHandshaker sslHandshaker,
-      SSLEngineConfigurator sslEngineConfigurator)
-      throws ErrorResultException
-  {
-    SSLStreamReader reader = new SSLStreamReader(connection
-        .getStreamReader());
-    SSLStreamWriter writer = new SSLStreamWriter(connection
-        .getStreamWriter());
-
-    try
-    {
-      sslHandshaker.handshake(reader, writer, sslEngineConfigurator)
-          .get();
-    }
-    catch (ExecutionException ee)
-    {
-      // FIXME: what other sort of IOExceptions can be thrown?
-      // FIXME: Is this the best result code?
-      Result errorResult = Responses.newResult(
-          ResultCode.CLIENT_SIDE_CONNECT_ERROR).setCause(ee.getCause());
-      connectionErrorOccurred(errorResult);
-      throw ErrorResultException.wrap(errorResult);
-    }
-    catch (Exception e)
-    {
-      // FIXME: what other sort of IOExceptions can be thrown?
-      // FIXME: Is this the best result code?
-      Result errorResult = Responses.newResult(
-          ResultCode.CLIENT_SIDE_CONNECT_ERROR).setCause(e);
-      connectionErrorOccurred(errorResult);
-      throw ErrorResultException.wrap(errorResult);
+      listener.connectionReceivedUnsolicitedNotification(result);
     }
   }
 
 
 
-  synchronized void installFilter(Filter filter)
+  void installFilter(final Filter filter)
   {
     if (customFilterChain == null)
     {
-      customFilterChain = connFactory.getDefaultFilterChainFactory()
-          .create();
+      customFilterChain = new DefaultFilterChain((FilterChain) connection
+          .getProcessor());
       connection.setProcessor(customFilterChain);
     }
 
     // Install the SSLFilter in the custom filter chain
-    Filter oldFilter = customFilterChain.remove(customFilterChain
-        .size() - 1);
-    customFilterChain.add(filter);
-    customFilterChain.add(oldFilter);
+    customFilterChain.add(customFilterChain.size() - 1, filter);
+  }
 
-    // Update stream writer
-    streamWriter = getFilterChainStreamWriter();
+
+
+  /**
+   * Indicates whether or not TLS is enabled on this connection.
+   *
+   * @return {@code true} if TLS is enabled on this connection, otherwise
+   *         {@code false}.
+   */
+  boolean isTLSEnabled()
+  {
+    final FilterChain currentFilterChain = (FilterChain) connection
+        .getProcessor();
+    return currentFilterChain.get(currentFilterChain.size() - 2) instanceof SSLFilter;
+  }
+
+
+
+  AbstractLDAPFutureResultImpl<?> removePendingRequest(final Integer messageID)
+  {
+    return pendingRequests.remove(messageID);
+  }
+
+
+
+  void setBindOrStartTLSInProgress(final boolean state)
+  {
+    bindOrStartTLSInProgress = state;
+  }
+
+
+
+  synchronized void startTLS(final SSLContext sslContext,
+      final CompletionHandler<SSLEngine> completionHandler) throws IOException
+  {
+    if (isTLSEnabled())
+    {
+      return;
+    }
+
+    SSLFilter sslFilter;
+    SSLEngineConfigurator sslEngineConfigurator;
+
+    sslEngineConfigurator = new SSLEngineConfigurator(sslContext, true, false,
+        false);
+    sslFilter = new SSLFilter(null, sslEngineConfigurator);
+    installFilter(sslFilter);
+    sslFilter.handshake(connection, completionHandler);
+  }
+
+
+
+  private void connectionErrorOccurred(final Result reason)
+  {
+    close(null, false, reason);
   }
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPConnectionFactoryImpl.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPConnectionFactoryImpl.java
index 71f0d08..ce244bb 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/LDAPConnectionFactoryImpl.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPConnectionFactoryImpl.java
@@ -30,94 +30,66 @@
 
 
 import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.util.HashMap;
-import java.util.Map;
+import java.net.SocketAddress;
 import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
 
-import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
 
 import org.opends.sdk.*;
-import org.opends.sdk.controls.*;
-import org.opends.sdk.extensions.StartTLSRequest;
-import org.opends.sdk.ldap.LDAPConnectionOptions;
+import org.opends.sdk.requests.Requests;
+import org.opends.sdk.requests.StartTLSExtendedRequest;
+import org.opends.sdk.responses.ExtendedResult;
 import org.opends.sdk.responses.Responses;
 import org.opends.sdk.responses.Result;
 
 import com.sun.grizzly.CompletionHandler;
 import com.sun.grizzly.Connection;
-import com.sun.grizzly.TransportFactory;
-import com.sun.grizzly.attributes.Attribute;
-import com.sun.grizzly.filterchain.PatternFilterChainFactory;
+import com.sun.grizzly.EmptyCompletionHandler;
+import com.sun.grizzly.filterchain.DefaultFilterChain;
+import com.sun.grizzly.filterchain.FilterChain;
+import com.sun.grizzly.filterchain.TransportFilter;
 import com.sun.grizzly.nio.transport.TCPNIOTransport;
-import com.sun.grizzly.ssl.BlockingSSLHandshaker;
-import com.sun.grizzly.ssl.SSLEngineConfigurator;
-import com.sun.grizzly.ssl.SSLFilter;
-import com.sun.grizzly.ssl.SSLHandshaker;
-import com.sun.grizzly.streams.StreamWriter;
 import com.sun.opends.sdk.util.CompletedFutureResult;
 import com.sun.opends.sdk.util.FutureResultTransformer;
 import com.sun.opends.sdk.util.RecursiveFutureResult;
-import com.sun.opends.sdk.util.Validator;
 
 
 
 /**
  * LDAP connection factory implementation.
  */
-public final class LDAPConnectionFactoryImpl extends
-    AbstractConnectionFactory implements ConnectionFactory
+public final class LDAPConnectionFactoryImpl extends AbstractConnectionFactory
+    implements ConnectionFactory
 {
-  private final class LDAPTransport extends AbstractLDAPTransport
-  {
 
-    @Override
-    protected LDAPMessageHandler getMessageHandler(
-        Connection<?> connection)
-    {
-      return ldapConnectionAttr.get(connection).getLDAPMessageHandler();
-    }
-
-
-
-    @Override
-    protected void removeMessageHandler(Connection<?> connection)
-    {
-      ldapConnectionAttr.remove(connection);
-    }
-
-  }
-
-
-
-  private final class FutureResultImpl implements
-      CompletionHandler<Connection>
+  @SuppressWarnings("unchecked")
+  private final class FutureResultImpl implements CompletionHandler<Connection>
   {
     private final FutureResultTransformer<Result, AsynchronousConnection> futureStartTLSResult;
 
-    private final RecursiveFutureResult<LDAPConnection, Result> futureConnectionResult;
+    private final RecursiveFutureResult<LDAPConnection, ExtendedResult> futureConnectionResult;
 
     private LDAPConnection connection;
 
 
 
     private FutureResultImpl(
-        ResultHandler<? super AsynchronousConnection> handler)
+        final ResultHandler<? super AsynchronousConnection> handler)
     {
       this.futureStartTLSResult = new FutureResultTransformer<Result, AsynchronousConnection>(
           handler)
       {
 
+        @Override
         protected ErrorResultException transformErrorResult(
-            ErrorResultException errorResult)
+            final ErrorResultException errorResult)
         {
           // Ensure that the connection is closed.
           try
           {
             connection.close();
           }
-          catch (Exception e)
+          catch (final Exception e)
           {
             // Ignore.
           }
@@ -126,7 +98,8 @@
 
 
 
-        protected LDAPConnection transformResult(Result result)
+        @Override
+        protected LDAPConnection transformResult(final Result result)
             throws ErrorResultException
         {
           return connection;
@@ -134,21 +107,22 @@
 
       };
 
-      this.futureConnectionResult = new RecursiveFutureResult<LDAPConnection, Result>(
+      this.futureConnectionResult = new RecursiveFutureResult<LDAPConnection, ExtendedResult>(
           futureStartTLSResult)
       {
 
-        protected FutureResult<? extends Result> chainResult(
-            LDAPConnection innerResult,
-            ResultHandler<? super Result> handler)
+        @Override
+        protected FutureResult<? extends ExtendedResult> chainResult(
+            final LDAPConnection innerResult,
+            final ResultHandler<? super ExtendedResult> handler)
             throws ErrorResultException
         {
           connection = innerResult;
 
           if (options.getSSLContext() != null && options.useStartTLS())
           {
-            StartTLSRequest startTLS = new StartTLSRequest(options
-                .getSSLContext());
+            final StartTLSExtendedRequest startTLS = Requests
+                .newStartTLSExtendedRequest(options.getSSLContext());
             return connection.extendedRequest(startTLS, handler);
           }
 
@@ -156,26 +130,41 @@
           {
             try
             {
-              connection.installFilter(sslFilter);
-              connection.performSSLHandshake(sslHandshaker,
-                  sslEngineConfigurator);
+              connection.startTLS(options.getSSLContext(),
+                  new EmptyCompletionHandler<SSLEngine>()
+                  {
+                    @Override
+                    public void completed(final SSLEngine result)
+                    {
+                      handler.handleResult(null);
+                    }
+
+
+
+                    @Override
+                    public void failed(final Throwable throwable)
+                    {
+                      final Result errorResult = Responses.newResult(
+                          ResultCode.CLIENT_SIDE_CONNECT_ERROR).setCause(
+                          throwable).setDiagnosticMessage(
+                          throwable.getMessage());
+                      handler.handleErrorResult(ErrorResultException
+                          .wrap(errorResult));
+                    }
+                  });
+              return null;
             }
-            catch (ErrorResultException errorResult)
+            catch (final IOException ioe)
             {
-              try
-              {
-                connection.close();
-                connection = null;
-              }
-              catch (Exception ignored)
-              {
-              }
-              throw errorResult;
+              final Result errorResult = Responses.newResult(
+                  ResultCode.CLIENT_SIDE_CONNECT_ERROR).setCause(ioe)
+                  .setDiagnosticMessage(ioe.getMessage());
+              throw ErrorResultException.wrap(errorResult);
             }
           }
-
           handler.handleResult(null);
-          return new CompletedFutureResult<Result>((Result) null);
+          return new CompletedFutureResult<ExtendedResult>(
+              (ExtendedResult) null);
         }
 
       };
@@ -188,7 +177,7 @@
     /**
      * {@inheritDoc}
      */
-    public void cancelled(Connection connection)
+    public void cancelled()
     {
       // Ignore this.
     }
@@ -198,7 +187,7 @@
     /**
      * {@inheritDoc}
      */
-    public void completed(Connection connection, Connection result)
+    public void completed(final Connection connection)
     {
       futureConnectionResult.handleResult(adaptConnection(connection));
     }
@@ -208,7 +197,7 @@
     /**
      * {@inheritDoc}
      */
-    public void failed(Connection connection, Throwable throwable)
+    public void failed(final Throwable throwable)
     {
       futureConnectionResult
           .handleErrorResult(adaptConnectionException(throwable));
@@ -219,7 +208,7 @@
     /**
      * {@inheritDoc}
      */
-    public void updated(Connection connection, Connection result)
+    public void updated(final Connection connection)
     {
       // Ignore this.
     }
@@ -228,142 +217,49 @@
 
 
 
-  private static final String LDAP_CONNECTION_OBJECT_ATTR = "LDAPConnAtr";
-
-  private static TCPNIOTransport TCP_NIO_TRANSPORT = null;
-
-
-
-  // FIXME: Need to figure out how this can be configured without
-  // exposing internal implementation details to application.
-  private static synchronized TCPNIOTransport getTCPNIOTransport()
-  {
-    if (TCP_NIO_TRANSPORT == null)
-    {
-      // Create a default transport using the Grizzly framework.
-      TCP_NIO_TRANSPORT = TransportFactory.getInstance()
-          .createTCPTransport();
-      try
-      {
-        TCP_NIO_TRANSPORT.start();
-      }
-      catch (IOException e)
-      {
-        throw new RuntimeException(
-            "Unable to create default connection factory provider", e);
-      }
-
-      Runtime.getRuntime().addShutdownHook(new Thread()
-      {
-
-        @Override
-        public void run()
-        {
-          ShutdownTCPNIOTransport();
-        }
-
-      });
-    }
-    return TCP_NIO_TRANSPORT;
-  }
-
-
-
-  private synchronized static void ShutdownTCPNIOTransport()
-  {
-    if (TCP_NIO_TRANSPORT != null)
-    {
-      try
-      {
-        TCP_NIO_TRANSPORT.stop();
-      }
-      catch (Exception e)
-      {
-        // Ignore.
-      }
-
-      // try
-      // {
-      // TCP_NIO_TRANSPORT.getWorkerThreadPool().shutdown();
-      // }
-      // catch (Exception e)
-      // {
-      // // Ignore.
-      // }
-
-      TCP_NIO_TRANSPORT = null;
-    }
-  }
-
-
-
-  private final Attribute<LDAPConnection> ldapConnectionAttr;
-
-  private final InetSocketAddress socketAddress;
+  private final SocketAddress socketAddress;
 
   private final TCPNIOTransport transport;
 
-  private final SSLHandshaker sslHandshaker = new BlockingSSLHandshaker();
+  private final FilterChain defaultFilterChain;
 
-  private final SSLEngineConfigurator sslEngineConfigurator;
+  private final LDAPClientFilter clientFilter;
 
-  private final SSLFilter sslFilter;
-
-  private final Map<String, ControlDecoder<?>> knownControls;
-
-  private final LDAPTransport ldapTransport = new LDAPTransport();
-
-  private final LDAPConnectionOptions options;
+  private final LDAPOptions options;
 
 
 
   /**
-   * Creates a new LDAP connection factory implementation which can be
-   * used to create connections to the Directory Server at the provided
-   * host and port address using provided connection options.
+   * Creates a new LDAP connection factory implementation which can be used to
+   * create connections to the Directory Server at the provided host and port
+   * address using provided connection options.
    *
-   * @param host
-   *          The host name.
-   * @param port
-   *          The port number.
+   * @param address
+   *          The address of the Directory Server to connect to.
    * @param options
-   *          The LDAP connection options to use when creating
-   *          connections.
-   * @throws NullPointerException
-   *           If {@code host} or {@code options} was {@code null}.
+   *          The LDAP connection options to use when creating connections.
    */
-  public LDAPConnectionFactoryImpl(String host, int port,
-      LDAPConnectionOptions options) throws NullPointerException
+  public LDAPConnectionFactoryImpl(final SocketAddress address,
+      final LDAPOptions options)
   {
-    this(host, port, options, getTCPNIOTransport());
-  }
-
-
-
-  private LDAPConnectionFactoryImpl(String host, int port,
-      LDAPConnectionOptions options, TCPNIOTransport transport)
-  {
-    Validator.ensureNotNull(host, transport, options);
-
-    this.transport = transport;
-    this.ldapConnectionAttr = transport.getAttributeBuilder()
-        .createAttribute(LDAP_CONNECTION_OBJECT_ATTR);
-    this.socketAddress = new InetSocketAddress(host, port);
-    this.options = LDAPConnectionOptions.copyOf(options);
-    if (this.options.getSSLContext() == null)
+    TCPNIOTransport tmpTransport = null;
+    if (options instanceof GrizzlyLDAPOptions)
     {
-      this.sslEngineConfigurator = null;
-      this.sslFilter = null;
+      tmpTransport = ((GrizzlyLDAPOptions) options).getTCPNIOTransport();
     }
-    else
+    if (tmpTransport == null)
     {
-      this.sslEngineConfigurator = new SSLEngineConfigurator(
-          this.options.getSSLContext(), true, false, false);
-      this.sslFilter = new SSLFilter(sslEngineConfigurator,
-          sslHandshaker);
+      tmpTransport = GlobalTransportFactory.getInstance().createTCPTransport();
     }
-    this.knownControls = new HashMap<String, ControlDecoder<?>>();
-    initControls();
+    this.transport = tmpTransport;
+
+    this.socketAddress = address;
+    this.options = new LDAPOptions(options);
+    this.clientFilter = new LDAPClientFilter(new LDAPReader(this.options
+        .getDecodeOptions()), 0);
+    this.defaultFilterChain = new DefaultFilterChain();
+    this.defaultFilterChain.add(new TransportFilter());
+    this.defaultFilterChain.add(clientFilter);
   }
 
 
@@ -371,10 +267,11 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public FutureResult<AsynchronousConnection> getAsynchronousConnection(
-      ResultHandler<AsynchronousConnection> handler)
+      final ResultHandler<AsynchronousConnection> handler)
   {
-    FutureResultImpl future = new FutureResultImpl(handler);
+    final FutureResultImpl future = new FutureResultImpl(handler);
 
     try
     {
@@ -382,85 +279,25 @@
           socketAddress, future));
       return future.futureStartTLSResult;
     }
-    catch (IOException e)
+    catch (final IOException e)
     {
-      ErrorResultException result = adaptConnectionException(e);
+      final ErrorResultException result = adaptConnectionException(e);
       return new CompletedFutureResult<AsynchronousConnection>(result);
     }
   }
 
 
 
-  ExecutorService getHandlerInvokers()
-  {
-    // TODO: Threading strategies?
-    return null;
-  }
-
-
-
-  SSLHandshaker getSslHandshaker()
-  {
-    return sslHandshaker;
-  }
-
-
-
-  SSLFilter getSSlFilter()
-  {
-    return sslFilter;
-  }
-
-
-
-  SSLContext getSSLContext()
-  {
-    return options.getSSLContext();
-  }
-
-
-
-  SSLEngineConfigurator getSSlEngineConfigurator()
-  {
-    return sslEngineConfigurator;
-  }
-
-
-
-  ASN1StreamWriter getASN1Writer(StreamWriter streamWriter)
-  {
-    return ldapTransport.getASN1Writer(streamWriter);
-  }
-
-
-
-  void releaseASN1Writer(ASN1StreamWriter asn1Writer)
-  {
-    ldapTransport.releaseASN1Writer(asn1Writer);
-  }
-
-
-
-  PatternFilterChainFactory getDefaultFilterChainFactory()
-  {
-    return ldapTransport.getDefaultFilterChainFactory();
-  }
-
-
-
-  private LDAPConnection adaptConnection(Connection<?> connection)
+  private LDAPConnection adaptConnection(final Connection<?> connection)
   {
     // Test shows that its much faster with non block writes but risk
     // running out of memory if the server is slow.
     connection.configureBlocking(true);
-    connection.getStreamReader().setBlocking(true);
-    connection.getStreamWriter().setBlocking(true);
-    connection.setProcessor(ldapTransport
-        .getDefaultFilterChainFactory().getFilterChainPattern());
+    connection.setProcessor(defaultFilterChain);
 
-    LDAPConnection ldapConnection = new LDAPConnection(connection,
-        socketAddress, options.getSchema(), this);
-    ldapConnectionAttr.set(connection, ldapConnection);
+    final LDAPConnection ldapConnection = new LDAPConnection(connection,
+        options);
+    clientFilter.registerConnection(connection, ldapConnection);
     return ldapConnection;
   }
 
@@ -473,49 +310,9 @@
       t = t.getCause();
     }
 
-    Result result = Responses.newResult(
-        ResultCode.CLIENT_SIDE_CONNECT_ERROR).setCause(t)
-        .setDiagnosticMessage(t.getMessage());
+    final Result result = Responses.newResult(
+        ResultCode.CLIENT_SIDE_CONNECT_ERROR).setCause(t).setDiagnosticMessage(
+        t.getMessage());
     return ErrorResultException.wrap(result);
   }
-
-
-
-  ControlDecoder<?> getControlDecoder(String oid)
-  {
-    return knownControls.get(oid);
-  }
-
-
-
-  private void initControls()
-  {
-    knownControls.put(
-        AccountUsabilityControl.OID_ACCOUNT_USABLE_CONTROL,
-        AccountUsabilityControl.RESPONSE_DECODER);
-    knownControls.put(
-        AuthorizationIdentityControl.OID_AUTHZID_RESPONSE,
-        AuthorizationIdentityControl.RESPONSE_DECODER);
-    knownControls.put(
-        EntryChangeNotificationControl.OID_ENTRY_CHANGE_NOTIFICATION,
-        EntryChangeNotificationControl.DECODER);
-    knownControls.put(PagedResultsControl.OID_PAGED_RESULTS_CONTROL,
-        PagedResultsControl.DECODER);
-    knownControls.put(PasswordExpiredControl.OID_NS_PASSWORD_EXPIRED,
-        PasswordExpiredControl.DECODER);
-    knownControls.put(PasswordExpiringControl.OID_NS_PASSWORD_EXPIRING,
-        PasswordExpiringControl.DECODER);
-    knownControls.put(
-        PasswordPolicyControl.OID_PASSWORD_POLICY_CONTROL,
-        PasswordPolicyControl.RESPONSE_DECODER);
-    knownControls.put(PostReadControl.OID_LDAP_READENTRY_POSTREAD,
-        PostReadControl.RESPONSE_DECODER);
-    knownControls.put(PreReadControl.OID_LDAP_READENTRY_PREREAD,
-        PreReadControl.RESPONSE_DECODER);
-    knownControls.put(
-        ServerSideSortControl.OID_SERVER_SIDE_SORT_RESPONSE_CONTROL,
-        ServerSideSortControl.RESPONSE_DECODER);
-    knownControls.put(VLVControl.OID_VLV_RESPONSE_CONTROL,
-        VLVControl.RESPONSE_DECODER);
-  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPConstants.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPConstants.java
index 5b90762..a79b8fb 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/LDAPConstants.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPConstants.java
@@ -26,11 +26,14 @@
  */
 package com.sun.opends.sdk.ldap;
 
+
+
 /**
  * This class defines a number of constants used in the LDAP protocol.
  */
 public final class LDAPConstants
 {
+
   /**
    * The protocol op type for bind requests.
    */
@@ -137,32 +140,31 @@
   public static final byte OP_TYPE_INTERMEDIATE_RESPONSE = 0x79;
 
   /**
-   * The BER type to use for encoding the sequence of controls in an
-   * LDAP message.
+   * The BER type to use for encoding the sequence of controls in an LDAP
+   * message.
    */
   public static final byte TYPE_CONTROL_SEQUENCE = (byte) 0xA0;
 
   /**
-   * The BER type to use for encoding the sequence of referral URLs in
-   * an LDAPResult element.
+   * The BER type to use for encoding the sequence of referral URLs in an
+   * LDAPResult element.
    */
   public static final byte TYPE_REFERRAL_SEQUENCE = (byte) 0xA3;
 
   /**
-   * The BER type to use for the AuthenticationChoice element in a bind
-   * request when simple authentication is to be used.
+   * The BER type to use for the AuthenticationChoice element in a bind request
+   * when simple authentication is to be used.
    */
   public static final byte TYPE_AUTHENTICATION_SIMPLE = (byte) 0x80;
 
   /**
-   * The BER type to use for the AuthenticationChoice element in a bind
-   * request when SASL authentication is to be used.
+   * The BER type to use for the AuthenticationChoice element in a bind request
+   * when SASL authentication is to be used.
    */
   public static final byte TYPE_AUTHENTICATION_SASL = (byte) 0xA3;
 
   /**
-   * The BER type to use for the server SASL credentials in a bind
-   * response.
+   * The BER type to use for the server SASL credentials in a bind response.
    */
   public static final byte TYPE_SERVER_SASL_CREDENTIALS = (byte) 0x87;
 
@@ -217,38 +219,32 @@
   public static final byte TYPE_FILTER_EXTENSIBLE_MATCH = (byte) 0xA9;
 
   /**
-   * The BER type to use for the subInitial component of a substring
-   * filter.
+   * The BER type to use for the subInitial component of a substring filter.
    */
   public static final byte TYPE_SUBINITIAL = (byte) 0x80;
 
   /**
-   * The BER type to use for the subAny component(s) of a substring
-   * filter.
+   * The BER type to use for the subAny component(s) of a substring filter.
    */
   public static final byte TYPE_SUBANY = (byte) 0x81;
 
   /**
-   * The BER type to use for the subFinal components of a substring
-   * filter.
+   * The BER type to use for the subFinal components of a substring filter.
    */
   public static final byte TYPE_SUBFINAL = (byte) 0x82;
 
   /**
-   * The BER type to use for the matching rule OID in a matching rule
-   * assertion.
+   * The BER type to use for the matching rule OID in a matching rule assertion.
    */
   public static final byte TYPE_MATCHING_RULE_ID = (byte) 0x81;
 
   /**
-   * The BER type to use for the attribute type in a matching rule
-   * assertion.
+   * The BER type to use for the attribute type in a matching rule assertion.
    */
   public static final byte TYPE_MATCHING_RULE_TYPE = (byte) 0x82;
 
   /**
-   * The BER type to use for the assertion value in a matching rule
-   * assertion.
+   * The BER type to use for the assertion value in a matching rule assertion.
    */
   public static final byte TYPE_MATCHING_RULE_VALUE = (byte) 0x83;
 
@@ -259,8 +255,7 @@
   public static final byte TYPE_MATCHING_RULE_DN_ATTRIBUTES = (byte) 0x84;
 
   /**
-   * The BER type to use for the newSuperior component of a modify DN
-   * request.
+   * The BER type to use for the newSuperior component of a modify DN request.
    */
   public static final byte TYPE_MODIFY_DN_NEW_SUPERIOR = (byte) 0x80;
 
@@ -285,14 +280,12 @@
   public static final byte TYPE_EXTENDED_RESPONSE_VALUE = (byte) 0x8B;
 
   /**
-   * The BER type to use for the OID of an intermediate response
-   * message.
+   * The BER type to use for the OID of an intermediate response message.
    */
   public static final byte TYPE_INTERMEDIATE_RESPONSE_OID = (byte) 0x80;
 
   /**
-   * The BER type to use for the value of an intermediate response
-   * message.
+   * The BER type to use for the value of an intermediate response message.
    */
   public static final byte TYPE_INTERMEDIATE_RESPONSE_VALUE = (byte) 0x81;
 
@@ -304,30 +297,36 @@
   /**
    * The OID for the LDAP notice of disconnection extended operation.
    */
-  public static final String OID_NOTICE_OF_DISCONNECTION =
-      "1.3.6.1.4.1.1466.20036";
+  public static final String OID_NOTICE_OF_DISCONNECTION = "1.3.6.1.4.1.1466.20036";
 
   /**
-   * The ASN.1 element decoding state that indicates that the next byte
-   * read should be the BER type for a new element.
+   * The ASN.1 element decoding state that indicates that the next byte read
+   * should be the BER type for a new element.
    */
   public static final int ELEMENT_READ_STATE_NEED_TYPE = 0;
 
   /**
-   * The ASN.1 element decoding state that indicates that the next byte
-   * read should be the first byte for the element length.
+   * The ASN.1 element decoding state that indicates that the next byte read
+   * should be the first byte for the element length.
    */
   public static final int ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE = 1;
 
   /**
-   * The ASN.1 element decoding state that indicates that the next byte
-   * read should be additional bytes of a multi-byte length.
+   * The ASN.1 element decoding state that indicates that the next byte read
+   * should be additional bytes of a multi-byte length.
    */
   public static final int ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES = 2;
 
   /**
-   * The ASN.1 element decoding state that indicates that the next byte
-   * read should be applied to the value of the element.
+   * The ASN.1 element decoding state that indicates that the next byte read
+   * should be applied to the value of the element.
    */
   public static final int ELEMENT_READ_STATE_NEED_VALUE_BYTES = 3;
+
+
+
+  private LDAPConstants()
+  {
+    // Prevent instantiation.
+  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPExtendedFutureResultImpl.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPExtendedFutureResultImpl.java
index db0454b..50a786d 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/LDAPExtendedFutureResultImpl.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPExtendedFutureResultImpl.java
@@ -31,47 +31,53 @@
 
 import org.opends.sdk.*;
 import org.opends.sdk.requests.ExtendedRequest;
-import org.opends.sdk.responses.Result;
+import org.opends.sdk.responses.ExtendedResult;
 
 
 
 /**
  * Extended result future implementation.
+ *
+ * @param <R>
+ *          The type of result returned by this future.
  */
-final class LDAPExtendedFutureResultImpl<R extends Result> extends
+final class LDAPExtendedFutureResultImpl<R extends ExtendedResult> extends
     AbstractLDAPFutureResultImpl<R> implements FutureResult<R>
 {
   private final ExtendedRequest<R> request;
 
 
 
-  LDAPExtendedFutureResultImpl(int messageID, ExtendedRequest<R> request,
-      ResultHandler<? super R> handler, LDAPConnection connection)
+  LDAPExtendedFutureResultImpl(final int messageID,
+      final ExtendedRequest<R> request,
+      final ResultHandler<? super R> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler,
+      final AsynchronousConnection connection)
   {
-    super(messageID, handler, connection);
+    super(messageID, resultHandler, intermediateResponseHandler, connection);
     this.request = request;
   }
 
 
 
-  R decodeResponse(ResultCode resultCode, String matchedDN,
-      String diagnosticMessage, String responseName,
-      ByteString responseValue) throws DecodeException
+  @Override
+  public String toString()
   {
-    return request.getExtendedOperation().decodeResponse(resultCode,
-        matchedDN, diagnosticMessage, responseName, responseValue);
+    final StringBuilder sb = new StringBuilder();
+    sb.append("LDAPExtendedFutureResultImpl(");
+    sb.append("request = ");
+    sb.append(request);
+    super.toString(sb);
+    sb.append(")");
+    return sb.toString();
   }
 
 
 
-  /**
-   * {@inheritDoc}
-   */
-  R newErrorResult(ResultCode resultCode, String diagnosticMessage,
-      Throwable cause)
+  R decodeResult(final ExtendedResult result, final DecodeOptions options)
+      throws DecodeException
   {
-    return request.getExtendedOperation().decodeResponse(resultCode,
-        "", diagnosticMessage);
+    return request.getResultDecoder().decodeExtendedResult(result, options);
   }
 
 
@@ -80,4 +86,17 @@
   {
     return request;
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  R newErrorResult(final ResultCode resultCode, final String diagnosticMessage,
+      final Throwable cause)
+  {
+    return request.getResultDecoder().adaptExtendedErrorResult(resultCode, "",
+        diagnosticMessage);
+  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPFutureResultImpl.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPFutureResultImpl.java
index cfc6287..58a914e 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/LDAPFutureResultImpl.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPFutureResultImpl.java
@@ -29,9 +29,7 @@
 
 
 
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.FutureResult;
-import org.opends.sdk.ResultHandler;
+import org.opends.sdk.*;
 import org.opends.sdk.requests.Request;
 import org.opends.sdk.responses.Responses;
 import org.opends.sdk.responses.Result;
@@ -41,37 +39,53 @@
 /**
  * Result future implementation.
  */
-public final class LDAPFutureResultImpl extends
-    AbstractLDAPFutureResultImpl<Result> implements FutureResult<Result>
+final class LDAPFutureResultImpl extends AbstractLDAPFutureResultImpl<Result>
+    implements FutureResult<Result>
 {
   private final Request request;
 
 
 
-  LDAPFutureResultImpl(int messageID, Request request,
-      ResultHandler<Result> handler, LDAPConnection connection)
+  LDAPFutureResultImpl(final int messageID, final Request request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler,
+      final AsynchronousConnection connection)
   {
-    super(messageID, handler, connection);
+    super(messageID, resultHandler, intermediateResponseHandler, connection);
     this.request = request;
   }
 
 
 
+  @Override
+  public String toString()
+  {
+    final StringBuilder sb = new StringBuilder();
+    sb.append("LDAPFutureResultImpl(");
+    sb.append("request = ");
+    sb.append(request);
+    super.toString(sb);
+    sb.append(")");
+    return sb.toString();
+  }
+
+
+
+  Request getRequest()
+  {
+    return request;
+  }
+
+
+
   /**
    * {@inheritDoc}
    */
   @Override
-  Result newErrorResult(ResultCode resultCode,
-      String diagnosticMessage, Throwable cause)
+  Result newErrorResult(final ResultCode resultCode,
+      final String diagnosticMessage, final Throwable cause)
   {
     return Responses.newResult(resultCode).setDiagnosticMessage(
         diagnosticMessage).setCause(cause);
   }
-
-
-
-  Request getRequest()
-  {
-    return request;
-  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPListenerImpl.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPListenerImpl.java
new file mode 100644
index 0000000..f534f28
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPListenerImpl.java
@@ -0,0 +1,139 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.SocketAddress;
+
+import javax.net.ssl.SSLContext;
+
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LDAPClientContext;
+import org.opends.sdk.LDAPListenerOptions;
+import org.opends.sdk.ServerConnectionFactory;
+
+import com.sun.grizzly.filterchain.DefaultFilterChain;
+import com.sun.grizzly.filterchain.FilterChain;
+import com.sun.grizzly.filterchain.TransportFilter;
+import com.sun.grizzly.nio.transport.TCPNIOServerConnection;
+import com.sun.grizzly.nio.transport.TCPNIOTransport;
+import com.sun.grizzly.ssl.SSLEngineConfigurator;
+import com.sun.grizzly.ssl.SSLFilter;
+
+
+
+/**
+ * LDAP listener implementation.
+ */
+public final class LDAPListenerImpl implements Closeable
+{
+  private final TCPNIOTransport transport;
+  private final FilterChain defaultFilterChain;
+  private final ServerConnectionFactory<LDAPClientContext, Integer> connectionFactory;
+  private final TCPNIOServerConnection serverConnection;
+
+
+
+  /**
+   * Creates a new LDAP listener implementation which will listen for LDAP
+   * client connections using the provided address and connection options.
+   *
+   * @param address
+   *          The address to listen on.
+   * @param factory
+   *          The server connection factory which will be used to create server
+   *          connections.
+   * @param options
+   *          The LDAP listener options.
+   * @throws IOException
+   *           If an error occurred while trying to listen on the provided
+   *           address.
+   */
+  public LDAPListenerImpl(final SocketAddress address,
+      final ServerConnectionFactory<LDAPClientContext, Integer> factory,
+      final LDAPListenerOptions options) throws IOException
+  {
+    TCPNIOTransport tmpTransport = null;
+    if (options instanceof GrizzlyLDAPListenerOptions)
+    {
+      tmpTransport = ((GrizzlyLDAPListenerOptions) options)
+          .getTCPNIOTransport();
+    }
+    if (tmpTransport == null)
+    {
+      tmpTransport = GlobalTransportFactory.getInstance().createTCPTransport();
+    }
+    this.transport = tmpTransport;
+    this.connectionFactory = factory;
+    this.defaultFilterChain = new DefaultFilterChain();
+    this.defaultFilterChain.add(new TransportFilter());
+
+    if (options.getSSLContext() != null)
+    {
+      final SSLContext sslContext = options.getSSLContext();
+      SSLEngineConfigurator sslEngineConfigurator;
+
+      sslEngineConfigurator = new SSLEngineConfigurator(sslContext, false,
+          false, false);
+      this.defaultFilterChain.add(new SSLFilter(sslEngineConfigurator, null));
+    }
+
+    this.defaultFilterChain.add(new LDAPServerFilter(this, new LDAPReader(
+        new DecodeOptions(options.getDecodeOptions())), 0));
+
+    this.serverConnection = transport.bind(address, options.getBacklog());
+    this.serverConnection.setProcessor(defaultFilterChain);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void close() throws IOException
+  {
+    transport.unbind(serverConnection);
+  }
+
+
+
+  ServerConnectionFactory<LDAPClientContext, Integer> getConnectionFactory()
+  {
+    return connectionFactory;
+  }
+
+
+
+  FilterChain getDefaultFilterChain()
+  {
+    return defaultFilterChain;
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPMessageHandler.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPMessageHandler.java
index b94a994..44dcc29 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/LDAPMessageHandler.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPMessageHandler.java
@@ -29,163 +29,131 @@
 
 
 
+import java.io.IOException;
+
 import org.opends.sdk.ByteString;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.ldap.ResolvedSchema;
-import org.opends.sdk.controls.Control;
 import org.opends.sdk.requests.*;
 import org.opends.sdk.responses.*;
-import org.opends.sdk.sasl.SASLBindRequest;
-import org.opends.sdk.schema.Schema;
 
 
 
 /**
  * LDAP message handler interface.
+ *
+ * @param <P>
+ *          A user provided handler parameter.
  */
-public interface LDAPMessageHandler
+interface LDAPMessageHandler<P>
 {
-  ResolvedSchema resolveSchema(String dn) throws DecodeException;
+  void abandonRequest(P param, int messageID, AbandonRequest request)
+      throws UnexpectedRequestException, IOException;
 
 
 
-  Schema getDefaultSchema();
+  void addRequest(P param, int messageID, AddRequest request)
+      throws UnexpectedRequestException, IOException;
 
 
 
-  void handleException(Throwable throwable);
+  void addResult(P param, int messageID, Result result)
+      throws UnexpectedResponseException, IOException;
 
 
 
-  void handleUnrecognizedMessage(int messageID, byte messageTag,
-      ByteString messageBytes) throws UnsupportedMessageException;
+  void bindRequest(P param, int messageID, int version,
+      GenericBindRequest request) throws UnexpectedRequestException,
+      IOException;
 
 
 
-  void handleAbandonRequest(int messageID, AbandonRequest request)
-      throws UnexpectedRequestException;
+  void bindResult(P param, int messageID, BindResult result)
+      throws UnexpectedResponseException, IOException;
 
 
 
-  void handleAddRequest(int messageID, AddRequest request)
-      throws UnexpectedRequestException;
+  void compareRequest(P param, int messageID, CompareRequest request)
+      throws UnexpectedRequestException, IOException;
 
 
 
-  void handleCompareRequest(int messageID, CompareRequest request)
-      throws UnexpectedRequestException;
+  void compareResult(P param, int messageID, CompareResult result)
+      throws UnexpectedResponseException, IOException;
 
 
 
-  void handleDeleteRequest(int messageID, DeleteRequest request)
-      throws UnexpectedRequestException;
+  void deleteRequest(P param, int messageID, DeleteRequest request)
+      throws UnexpectedRequestException, IOException;
 
 
 
-  void handleExtendedRequest(int messageID,
-      GenericExtendedRequest request) throws UnexpectedRequestException;
+  void deleteResult(P param, int messageID, Result result)
+      throws UnexpectedResponseException, IOException;
 
 
 
-  void handleBindRequest(int messageID, int version,
-      GenericBindRequest request) throws UnexpectedRequestException;
+  <R extends ExtendedResult> void extendedRequest(P param, int messageID,
+      ExtendedRequest<R> request) throws UnexpectedRequestException,
+      IOException;
 
 
 
-  void handleBindRequest(int messageID, int version,
-      SASLBindRequest<?> request) throws UnexpectedRequestException;
+  void extendedResult(P param, int messageID, ExtendedResult result)
+      throws UnexpectedResponseException, IOException;
 
 
 
-  void handleBindRequest(int messageID, int version,
-      SimpleBindRequest request) throws UnexpectedRequestException;
+  void intermediateResponse(P param, int messageID,
+      IntermediateResponse response) throws UnexpectedResponseException,
+      IOException;
 
 
 
-  void handleModifyDNRequest(int messageID, ModifyDNRequest request)
-      throws UnexpectedRequestException;
+  void modifyDNRequest(P param, int messageID, ModifyDNRequest request)
+      throws UnexpectedRequestException, IOException;
 
 
 
-  void handleModifyRequest(int messageID, ModifyRequest request)
-      throws UnexpectedRequestException;
+  void modifyDNResult(P param, int messageID, Result result)
+      throws UnexpectedResponseException, IOException;
 
 
 
-  void handleSearchRequest(int messageID, SearchRequest request)
-      throws UnexpectedRequestException;
+  void modifyRequest(P param, int messageID, ModifyRequest request)
+      throws UnexpectedRequestException, IOException;
 
 
 
-  void handleUnbindRequest(int messageID, UnbindRequest request)
-      throws UnexpectedRequestException;
-
-
-
-  void handleAddResult(int messageID, Result result)
-      throws UnexpectedResponseException;
-
-
-
-  void handleBindResult(int messageID, BindResult result)
-      throws UnexpectedResponseException;
-
-
-
-  void handleCompareResult(int messageID, CompareResult result)
-      throws UnexpectedResponseException;
-
-
-
-  void handleDeleteResult(int messageID, Result result)
-      throws UnexpectedResponseException;
-
-
-
-  void handleExtendedResult(int messageID, GenericExtendedResult result)
-      throws UnexpectedResponseException;
-
-
-
-  void handleIntermediateResponse(int messageID,
-      GenericIntermediateResponse response)
-      throws UnexpectedResponseException;
-
-
-
-  void handleModifyDNResult(int messageID, Result result)
-      throws UnexpectedResponseException;
+  void modifyResult(P param, int messageID, Result result)
+      throws UnexpectedResponseException, IOException;
 
 
 
-  void handleModifyResult(int messageID, Result result)
-      throws UnexpectedResponseException;
+  void searchRequest(P param, int messageID, SearchRequest request)
+      throws UnexpectedRequestException, IOException;
 
 
 
-  void handleSearchResult(int messageID, Result result)
-      throws UnexpectedResponseException;
+  void searchResult(P param, int messageID, Result result)
+      throws UnexpectedResponseException, IOException;
 
 
 
-  void handleSearchResultEntry(int messageID, SearchResultEntry entry)
-      throws UnexpectedResponseException;
+  void searchResultEntry(P param, int messageID, SearchResultEntry entry)
+      throws UnexpectedResponseException, IOException;
 
 
 
-  void handleSearchResultReference(int messageID,
-      SearchResultReference reference)
-      throws UnexpectedResponseException;
+  void searchResultReference(P param, int messageID,
+      SearchResultReference reference) throws UnexpectedResponseException,
+      IOException;
 
 
 
-  Control decodeResponseControl(int messageID, String oid,
-      boolean isCritical, ByteString value, Schema schema)
-      throws DecodeException;
+  void unbindRequest(P param, int messageID, UnbindRequest request)
+      throws UnexpectedRequestException, IOException;
 
 
 
-  Control decodeRequestControl(int messageID, String oid,
-      boolean isCritical, ByteString value, Schema schema)
-      throws DecodeException;
+  void unrecognizedMessage(P param, int messageID, byte messageTag,
+      ByteString messageBytes) throws UnsupportedMessageException, IOException;
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPReader.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPReader.java
new file mode 100644
index 0000000..905ce7e
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPReader.java
@@ -0,0 +1,1817 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import static com.sun.opends.sdk.ldap.LDAPConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_LDAP_MODIFICATION_DECODE_INVALID_MOD_TYPE;
+import static com.sun.opends.sdk.messages.Messages.ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_DEREF;
+import static com.sun.opends.sdk.messages.Messages.ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_SCOPE;
+import static org.opends.sdk.asn1.ASN1Constants.UNIVERSAL_BOOLEAN_TYPE;
+import static org.opends.sdk.asn1.ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE;
+
+import java.io.IOException;
+import java.util.logging.Level;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.GenericControl;
+import org.opends.sdk.requests.*;
+import org.opends.sdk.responses.*;
+import org.opends.sdk.schema.Schema;
+
+import com.sun.opends.sdk.util.StaticUtils;
+
+
+
+/**
+ * Static methods for decoding LDAP messages.
+ */
+final class LDAPReader
+{
+  static SearchResultEntry decodeEntry(final ASN1Reader reader,
+      final DecodeOptions options) throws IOException
+  {
+    Entry entry;
+
+    reader.readStartSequence(OP_TYPE_SEARCH_RESULT_ENTRY);
+    try
+    {
+      final String dnString = reader.readOctetStringAsString();
+      final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
+      DN dn;
+      try
+      {
+        dn = DN.valueOf(dnString, schema);
+      }
+      catch (final LocalizedIllegalArgumentException e)
+      {
+        throw DecodeException.error(e.getMessageObject());
+      }
+
+      entry = options.getEntryFactory().newEntry(dn);
+      reader.readStartSequence();
+      try
+      {
+        while (reader.hasNextElement())
+        {
+          reader.readStartSequence();
+          try
+          {
+            final String ads = reader.readOctetStringAsString();
+            AttributeDescription ad;
+            try
+            {
+              ad = AttributeDescription.valueOf(ads, schema);
+            }
+            catch (final LocalizedIllegalArgumentException e)
+            {
+              throw DecodeException.error(e.getMessageObject());
+            }
+
+            final Attribute attribute = options.getAttributeFactory()
+                .newAttribute(ad);
+
+            reader.readStartSet();
+            try
+            {
+              while (reader.hasNextElement())
+              {
+                attribute.add(reader.readOctetString());
+              }
+              entry.addAttribute(attribute);
+            }
+            finally
+            {
+              reader.readEndSet();
+            }
+          }
+          finally
+          {
+            reader.readEndSequence();
+          }
+        }
+      }
+      finally
+      {
+        reader.readEndSequence();
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    return Responses.newSearchResultEntry(entry);
+  }
+
+
+
+  private final DecodeOptions options;
+
+
+
+  LDAPReader(final DecodeOptions options)
+  {
+    this.options = options;
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP message.
+   *
+   * @param <P>
+   *          The type of {@code param}.
+   * @param reader
+   *          The ASN.1 reader.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle a decoded
+   *          message.
+   * @param param
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  <P> void decode(final ASN1Reader reader, final LDAPMessageHandler<P> handler,
+      final P param) throws IOException
+  {
+    reader.readStartSequence();
+    try
+    {
+      final int messageID = (int) reader.readInteger();
+      decodeProtocolOp(reader, messageID, handler, param);
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 read as an LDAP abandon
+   * request protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeAbandonRequest(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    final int msgToAbandon = (int) reader.readInteger(OP_TYPE_ABANDON_REQUEST);
+    final AbandonRequest message = Requests.newAbandonRequest(msgToAbandon);
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP ABANDON REQUEST(messageID=%d, request=%s)", messageID,
+          message));
+    }
+
+    handler.abandonRequest(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP add request
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeAddRequest(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    Entry entry;
+
+    reader.readStartSequence(OP_TYPE_ADD_REQUEST);
+    try
+    {
+      final String dnString = reader.readOctetStringAsString();
+      final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
+      final DN dn = decodeDN(dnString, schema);
+      entry = options.getEntryFactory().newEntry(dn);
+
+      reader.readStartSequence();
+      try
+      {
+        while (reader.hasNextElement())
+        {
+          reader.readStartSequence();
+          try
+          {
+            final String ads = reader.readOctetStringAsString();
+            final AttributeDescription ad = decodeAttributeDescription(ads,
+                schema);
+            final Attribute attribute = options.getAttributeFactory()
+                .newAttribute(ad);
+
+            reader.readStartSet();
+            try
+            {
+              while (reader.hasNextElement())
+              {
+                attribute.add(reader.readOctetString());
+              }
+              entry.addAttribute(attribute);
+            }
+            finally
+            {
+              reader.readEndSet();
+            }
+          }
+          finally
+          {
+            reader.readEndSequence();
+          }
+        }
+      }
+      finally
+      {
+        reader.readEndSequence();
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    final AddRequest message = Requests.newAddRequest(entry);
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP ADD REQUEST(messageID=%d, request=%s)", messageID,
+          message));
+    }
+
+    handler.addRequest(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an add response
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeAddResult(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    Result message;
+
+    reader.readStartSequence(OP_TYPE_ADD_RESPONSE);
+    try
+    {
+      final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated());
+      final String matchedDN = reader.readOctetStringAsString();
+      final String diagnosticMessage = reader.readOctetStringAsString();
+      message = Responses.newResult(resultCode).setMatchedDN(matchedDN)
+          .setDiagnosticMessage(diagnosticMessage);
+      decodeResponseReferrals(reader, message);
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String
+          .format("DECODE LDAP ADD RESULT(messageID=%d, result=%s)", messageID,
+              message));
+    }
+
+    handler.addResult(p, messageID, message);
+  }
+
+
+
+  private AttributeDescription decodeAttributeDescription(
+      final String attributeDescription, final Schema schema)
+      throws DecodeException
+  {
+    try
+    {
+      return AttributeDescription.valueOf(attributeDescription, schema);
+    }
+    catch (final LocalizedIllegalArgumentException e)
+    {
+      throw DecodeException.error(e.getMessageObject());
+    }
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 read as an LDAP bind request
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeBindRequest(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    reader.readStartSequence(OP_TYPE_BIND_REQUEST);
+    try
+    {
+      final int protocolVersion = (int) reader.readInteger();
+      final String authName = reader.readOctetStringAsString();
+      final byte authType = reader.peekType();
+      final ByteString authBytes = reader.readOctetString(authType);
+
+      final GenericBindRequest request = Requests.newGenericBindRequest(
+          authName, authType, authBytes);
+
+      decodeControls(reader, request);
+
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+      {
+        StaticUtils.DEBUG_LOG.finer(String.format(
+            "DECODE LDAP BIND REQUEST(messageID=%d, auth=0x%x, request=%s)",
+            messageID, request.getAuthenticationType(), request));
+      }
+
+      handler.bindRequest(p, messageID, protocolVersion, request);
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a bind response
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeBindResult(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    BindResult message;
+
+    reader.readStartSequence(OP_TYPE_BIND_RESPONSE);
+    try
+    {
+      final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated());
+      final String matchedDN = reader.readOctetStringAsString();
+      final String diagnosticMessage = reader.readOctetStringAsString();
+      message = Responses.newBindResult(resultCode).setMatchedDN(matchedDN)
+          .setDiagnosticMessage(diagnosticMessage);
+      decodeResponseReferrals(reader, message);
+      if (reader.hasNextElement()
+          && (reader.peekType() == TYPE_SERVER_SASL_CREDENTIALS))
+      {
+        message.setServerSASLCredentials(reader
+            .readOctetString(TYPE_SERVER_SASL_CREDENTIALS));
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP BIND RESULT(messageID=%d, result=%s)", messageID,
+          message));
+    }
+
+    handler.bindResult(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP compare
+   * request protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeCompareRequest(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    CompareRequest message;
+
+    reader.readStartSequence(OP_TYPE_COMPARE_REQUEST);
+    try
+    {
+      final String dnString = reader.readOctetStringAsString();
+      final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
+      final DN dn = decodeDN(dnString, schema);
+
+      reader.readStartSequence();
+      try
+      {
+        final String ads = reader.readOctetStringAsString();
+        final AttributeDescription ad = decodeAttributeDescription(ads, schema);
+        final ByteString assertionValue = reader.readOctetString();
+        message = Requests.newCompareRequest(dn, ad, assertionValue);
+      }
+      finally
+      {
+        reader.readEndSequence();
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP COMPARE REQUEST(messageID=%d, request=%s)", messageID,
+          message));
+    }
+
+    handler.compareRequest(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a compare response
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeCompareResult(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    CompareResult message;
+
+    reader.readStartSequence(OP_TYPE_COMPARE_RESPONSE);
+    try
+    {
+      final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated());
+      final String matchedDN = reader.readOctetStringAsString();
+      final String diagnosticMessage = reader.readOctetStringAsString();
+      message = Responses.newCompareResult(resultCode).setMatchedDN(matchedDN)
+          .setDiagnosticMessage(diagnosticMessage);
+      decodeResponseReferrals(reader, message);
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP COMPARE RESULT(messageID=%d, result=%s)", messageID,
+          message));
+    }
+
+    handler.compareResult(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP control.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param request
+   *          The decoded request to decode controls for.
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private void decodeControl(final ASN1Reader reader, final Request request)
+      throws IOException
+  {
+    String oid;
+    boolean isCritical;
+    ByteString value;
+
+    reader.readStartSequence();
+    try
+    {
+      oid = reader.readOctetStringAsString();
+      isCritical = false;
+      value = null;
+      if (reader.hasNextElement()
+          && (reader.peekType() == UNIVERSAL_BOOLEAN_TYPE))
+      {
+        isCritical = reader.readBoolean();
+      }
+      if (reader.hasNextElement()
+          && (reader.peekType() == UNIVERSAL_OCTET_STRING_TYPE))
+      {
+        value = reader.readOctetString();
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    final Control c = GenericControl.newControl(oid, isCritical, value);
+    request.addControl(c);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP control.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param response
+   *          The decoded message to decode controls for.
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private void decodeControl(final ASN1Reader reader, final Response response)
+      throws IOException
+  {
+    String oid;
+    boolean isCritical;
+    ByteString value;
+
+    reader.readStartSequence();
+    try
+    {
+      oid = reader.readOctetStringAsString();
+      isCritical = false;
+      value = null;
+      if (reader.hasNextElement()
+          && (reader.peekType() == UNIVERSAL_BOOLEAN_TYPE))
+      {
+        isCritical = reader.readBoolean();
+      }
+      if (reader.hasNextElement()
+          && (reader.peekType() == UNIVERSAL_OCTET_STRING_TYPE))
+      {
+        value = reader.readOctetString();
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    final Control c = GenericControl.newControl(oid, isCritical, value);
+    response.addControl(c);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a set of controls.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param request
+   *          The decoded message to decode controls for.
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private void decodeControls(final ASN1Reader reader, final Request request)
+      throws IOException
+  {
+    if (reader.hasNextElement() && (reader.peekType() == TYPE_CONTROL_SEQUENCE))
+    {
+      reader.readStartSequence(TYPE_CONTROL_SEQUENCE);
+      try
+      {
+        while (reader.hasNextElement())
+        {
+          decodeControl(reader, request);
+        }
+      }
+      finally
+      {
+        reader.readEndSequence();
+      }
+    }
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a set of controls.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param response
+   *          The decoded message to decode controls for.
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private void decodeControls(final ASN1Reader reader, final Response response)
+      throws IOException
+  {
+    if (reader.hasNextElement() && (reader.peekType() == TYPE_CONTROL_SEQUENCE))
+    {
+      reader.readStartSequence(TYPE_CONTROL_SEQUENCE);
+      try
+      {
+        while (reader.hasNextElement())
+        {
+          decodeControl(reader, response);
+        }
+      }
+      finally
+      {
+        reader.readEndSequence();
+      }
+    }
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP delete
+   * request protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeDeleteRequest(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    final String dnString = reader
+        .readOctetStringAsString(OP_TYPE_DELETE_REQUEST);
+    final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
+    final DN dn = decodeDN(dnString, schema);
+    final DeleteRequest message = Requests.newDeleteRequest(dn);
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP DELETE REQUEST(messageID=%d, request=%s)", messageID,
+          message));
+    }
+
+    handler.deleteRequest(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a delete response
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeDeleteResult(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    Result message;
+
+    reader.readStartSequence(OP_TYPE_DELETE_RESPONSE);
+    try
+    {
+      final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated());
+      final String matchedDN = reader.readOctetStringAsString();
+      final String diagnosticMessage = reader.readOctetStringAsString();
+      message = Responses.newResult(resultCode).setMatchedDN(matchedDN)
+          .setDiagnosticMessage(diagnosticMessage);
+      decodeResponseReferrals(reader, message);
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP DELETE RESULT(messageID=%d, result=%s)", messageID,
+          message));
+    }
+
+    handler.deleteResult(p, messageID, message);
+  }
+
+
+
+  private DN decodeDN(final String dn, final Schema schema)
+      throws DecodeException
+  {
+    try
+    {
+      return DN.valueOf(dn, schema);
+    }
+    catch (final LocalizedIllegalArgumentException e)
+    {
+      throw DecodeException.error(e.getMessageObject());
+    }
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP extended
+   * request protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeExtendedRequest(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    String oid;
+    ByteString value;
+
+    reader.readStartSequence(OP_TYPE_EXTENDED_REQUEST);
+    try
+    {
+      oid = reader.readOctetStringAsString(TYPE_EXTENDED_REQUEST_OID);
+      value = null;
+      if (reader.hasNextElement()
+          && (reader.peekType() == TYPE_EXTENDED_REQUEST_VALUE))
+      {
+        value = reader.readOctetString(TYPE_EXTENDED_REQUEST_VALUE);
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    final GenericExtendedRequest message = Requests.newGenericExtendedRequest(
+        oid, value);
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP EXTENDED REQUEST(messageID=%d, request=%s)", messageID,
+          message));
+    }
+
+    handler.extendedRequest(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a extended response
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeExtendedResult(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+
+    GenericExtendedResult message;
+
+    reader.readStartSequence(OP_TYPE_EXTENDED_RESPONSE);
+    try
+    {
+      final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated());
+      final String matchedDN = reader.readOctetStringAsString();
+      final String diagnosticMessage = reader.readOctetStringAsString();
+      message = Responses.newGenericExtendedResult(resultCode).setMatchedDN(
+          matchedDN).setDiagnosticMessage(diagnosticMessage);
+      decodeResponseReferrals(reader, message);
+      if (reader.hasNextElement()
+          && (reader.peekType() == TYPE_EXTENDED_RESPONSE_OID))
+      {
+        message.setOID(reader
+            .readOctetStringAsString(TYPE_EXTENDED_RESPONSE_OID));
+      }
+      if (reader.hasNextElement()
+          && (reader.peekType() == TYPE_EXTENDED_RESPONSE_VALUE))
+      {
+        message.setValue(reader.readOctetString(TYPE_EXTENDED_RESPONSE_VALUE));
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP EXTENDED RESULT(messageID=%d, result=%s)", messageID,
+          message));
+    }
+
+    handler.extendedResult(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP intermediate
+   * response protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeIntermediateResponse(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    GenericIntermediateResponse message;
+
+    reader.readStartSequence(OP_TYPE_INTERMEDIATE_RESPONSE);
+    try
+    {
+      message = Responses.newGenericIntermediateResponse();
+      if (reader.hasNextElement()
+          && (reader.peekType() == TYPE_INTERMEDIATE_RESPONSE_OID))
+      {
+        message.setOID(reader
+            .readOctetStringAsString(TYPE_INTERMEDIATE_RESPONSE_OID));
+      }
+      if (reader.hasNextElement()
+          && (reader.peekType() == TYPE_INTERMEDIATE_RESPONSE_VALUE))
+      {
+        message.setValue(reader
+            .readOctetString(TYPE_INTERMEDIATE_RESPONSE_VALUE));
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP INTERMEDIATE RESPONSE(messageID=%d, response=%s)",
+          messageID, message));
+    }
+
+    handler.intermediateResponse(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a modify DN request
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeModifyDNRequest(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    ModifyDNRequest message;
+
+    reader.readStartSequence(OP_TYPE_MODIFY_DN_REQUEST);
+    try
+    {
+      final String dnString = reader.readOctetStringAsString();
+      final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
+      final DN dn = decodeDN(dnString, schema);
+
+      final String newRDNString = reader.readOctetStringAsString();
+      final RDN newRDN = decodeRDN(newRDNString, schema);
+
+      message = Requests.newModifyDNRequest(dn, newRDN);
+
+      message.setDeleteOldRDN(reader.readBoolean());
+
+      if (reader.hasNextElement()
+          && (reader.peekType() == TYPE_MODIFY_DN_NEW_SUPERIOR))
+      {
+        final String newSuperiorString = reader
+            .readOctetStringAsString(TYPE_MODIFY_DN_NEW_SUPERIOR);
+        final DN newSuperior = decodeDN(newSuperiorString, schema);
+        message.setNewSuperior(newSuperior);
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP MODIFY DN REQUEST(messageID=%d, request=%s)", messageID,
+          message));
+    }
+
+    handler.modifyDNRequest(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a modify DN response
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeModifyDNResult(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    Result message;
+
+    reader.readStartSequence(OP_TYPE_MODIFY_DN_RESPONSE);
+    try
+    {
+      final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated());
+      final String matchedDN = reader.readOctetStringAsString();
+      final String diagnosticMessage = reader.readOctetStringAsString();
+      message = Responses.newResult(resultCode).setMatchedDN(matchedDN)
+          .setDiagnosticMessage(diagnosticMessage);
+      decodeResponseReferrals(reader, message);
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP MODIFY DN RESULT(messageID=%d, result=%s)", messageID,
+          message));
+    }
+
+    handler.modifyDNResult(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP modify
+   * request protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeModifyRequest(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    ModifyRequest message;
+
+    reader.readStartSequence(OP_TYPE_MODIFY_REQUEST);
+    try
+    {
+      final String dnString = reader.readOctetStringAsString();
+      final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
+      final DN dn = decodeDN(dnString, schema);
+      message = Requests.newModifyRequest(dn);
+
+      reader.readStartSequence();
+      try
+      {
+        while (reader.hasNextElement())
+        {
+          reader.readStartSequence();
+          try
+          {
+            final int typeIntValue = reader.readEnumerated();
+            final ModificationType type = ModificationType
+                .valueOf(typeIntValue);
+            if (type == null)
+            {
+              throw DecodeException
+                  .error(ERR_LDAP_MODIFICATION_DECODE_INVALID_MOD_TYPE
+                      .get(typeIntValue));
+            }
+            reader.readStartSequence();
+            try
+            {
+              final String ads = reader.readOctetStringAsString();
+              final AttributeDescription ad = decodeAttributeDescription(ads,
+                  schema);
+              final Attribute attribute = options.getAttributeFactory()
+                  .newAttribute(ad);
+
+              reader.readStartSet();
+              try
+              {
+                while (reader.hasNextElement())
+                {
+                  attribute.add(reader.readOctetString());
+                }
+                message.addModification(new Modification(type, attribute));
+              }
+              finally
+              {
+                reader.readEndSet();
+              }
+            }
+            finally
+            {
+              reader.readEndSequence();
+            }
+          }
+          finally
+          {
+            reader.readEndSequence();
+          }
+        }
+      }
+      finally
+      {
+        reader.readEndSequence();
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP MODIFY REQUEST(messageID=%d, request=%s)", messageID,
+          message));
+    }
+
+    handler.modifyRequest(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a modify response
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeModifyResult(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    Result message;
+
+    reader.readStartSequence(OP_TYPE_MODIFY_RESPONSE);
+    try
+    {
+      final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated());
+      final String matchedDN = reader.readOctetStringAsString();
+      final String diagnosticMessage = reader.readOctetStringAsString();
+      message = Responses.newResult(resultCode).setMatchedDN(matchedDN)
+          .setDiagnosticMessage(diagnosticMessage);
+      decodeResponseReferrals(reader, message);
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP MODIFY RESULT(messageID=%d, result=%s)", messageID,
+          message));
+    }
+
+    handler.modifyResult(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeProtocolOp(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    final byte type = reader.peekType();
+
+    switch (type)
+    {
+    case OP_TYPE_UNBIND_REQUEST: // 0x42
+      decodeUnbindRequest(reader, messageID, handler, p);
+      break;
+    case 0x43: // 0x43
+    case 0x44: // 0x44
+    case 0x45: // 0x45
+    case 0x46: // 0x46
+    case 0x47: // 0x47
+    case 0x48: // 0x48
+    case 0x49: // 0x49
+      handler.unrecognizedMessage(p, messageID, type, reader
+          .readOctetString(type));
+      break;
+    case OP_TYPE_DELETE_REQUEST: // 0x4A
+      decodeDeleteRequest(reader, messageID, handler, p);
+      break;
+    case 0x4B: // 0x4B
+    case 0x4C: // 0x4C
+    case 0x4D: // 0x4D
+    case 0x4E: // 0x4E
+    case 0x4F: // 0x4F
+      handler.unrecognizedMessage(p, messageID, type, reader
+          .readOctetString(type));
+      break;
+    case OP_TYPE_ABANDON_REQUEST: // 0x50
+      decodeAbandonRequest(reader, messageID, handler, p);
+      break;
+    case 0x51: // 0x51
+    case 0x52: // 0x52
+    case 0x53: // 0x53
+    case 0x54: // 0x54
+    case 0x55: // 0x55
+    case 0x56: // 0x56
+    case 0x57: // 0x57
+    case 0x58: // 0x58
+    case 0x59: // 0x59
+    case 0x5A: // 0x5A
+    case 0x5B: // 0x5B
+    case 0x5C: // 0x5C
+    case 0x5D: // 0x5D
+    case 0x5E: // 0x5E
+    case 0x5F: // 0x5F
+      handler.unrecognizedMessage(p, messageID, type, reader
+          .readOctetString(type));
+      break;
+    case OP_TYPE_BIND_REQUEST: // 0x60
+      decodeBindRequest(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_BIND_RESPONSE: // 0x61
+      decodeBindResult(reader, messageID, handler, p);
+      break;
+    case 0x62: // 0x62
+      handler.unrecognizedMessage(p, messageID, type, reader
+          .readOctetString(type));
+      break;
+    case OP_TYPE_SEARCH_REQUEST: // 0x63
+      decodeSearchRequest(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_SEARCH_RESULT_ENTRY: // 0x64
+      decodeSearchResultEntry(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_SEARCH_RESULT_DONE: // 0x65
+      decodeSearchResult(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_MODIFY_REQUEST: // 0x66
+      decodeModifyRequest(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_MODIFY_RESPONSE: // 0x67
+      decodeModifyResult(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_ADD_REQUEST: // 0x68
+      decodeAddRequest(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_ADD_RESPONSE: // 0x69
+      decodeAddResult(reader, messageID, handler, p);
+      break;
+    case 0x6A: // 0x6A
+      handler.unrecognizedMessage(p, messageID, type, reader
+          .readOctetString(type));
+      break;
+    case OP_TYPE_DELETE_RESPONSE: // 0x6B
+      decodeDeleteResult(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_MODIFY_DN_REQUEST: // 0x6C
+      decodeModifyDNRequest(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_MODIFY_DN_RESPONSE: // 0x6D
+      decodeModifyDNResult(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_COMPARE_REQUEST: // 0x6E
+      decodeCompareRequest(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_COMPARE_RESPONSE: // 0x6F
+      decodeCompareResult(reader, messageID, handler, p);
+      break;
+    case 0x70: // 0x70
+    case 0x71: // 0x71
+    case 0x72: // 0x72
+      handler.unrecognizedMessage(p, messageID, type, reader
+          .readOctetString(type));
+      break;
+    case OP_TYPE_SEARCH_RESULT_REFERENCE: // 0x73
+      decodeSearchResultReference(reader, messageID, handler, p);
+      break;
+    case 0x74: // 0x74
+    case 0x75: // 0x75
+    case 0x76: // 0x76
+      handler.unrecognizedMessage(p, messageID, type, reader
+          .readOctetString(type));
+      break;
+    case OP_TYPE_EXTENDED_REQUEST: // 0x77
+      decodeExtendedRequest(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_EXTENDED_RESPONSE: // 0x78
+      decodeExtendedResult(reader, messageID, handler, p);
+      break;
+    case OP_TYPE_INTERMEDIATE_RESPONSE: // 0x79
+      decodeIntermediateResponse(reader, messageID, handler, p);
+      break;
+    default:
+      handler.unrecognizedMessage(p, messageID, type, reader
+          .readOctetString(type));
+      break;
+    }
+  }
+
+
+
+  private RDN decodeRDN(final String rdn, final Schema schema)
+      throws DecodeException
+  {
+    try
+    {
+      return RDN.valueOf(rdn, schema);
+    }
+    catch (final LocalizedIllegalArgumentException e)
+    {
+      throw DecodeException.error(e.getMessageObject());
+    }
+  }
+
+
+
+  private void decodeResponseReferrals(final ASN1Reader reader,
+      final Result message) throws IOException
+  {
+    if (reader.hasNextElement()
+        && (reader.peekType() == TYPE_REFERRAL_SEQUENCE))
+    {
+      reader.readStartSequence(TYPE_REFERRAL_SEQUENCE);
+      try
+      {
+        // Should have at least 1.
+        do
+        {
+          message.addReferralURI((reader.readOctetStringAsString()));
+        }
+        while (reader.hasNextElement());
+      }
+      finally
+      {
+        reader.readEndSequence();
+      }
+    }
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP search
+   * request protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeSearchRequest(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    SearchRequest message;
+
+    reader.readStartSequence(OP_TYPE_SEARCH_REQUEST);
+    try
+    {
+      final String baseDNString = reader.readOctetStringAsString();
+      final Schema schema = options.getSchemaResolver().resolveSchema(
+          baseDNString);
+      final DN baseDN = decodeDN(baseDNString, schema);
+
+      final int scopeIntValue = reader.readEnumerated();
+      final SearchScope scope = SearchScope.valueOf(scopeIntValue);
+      if (scope == null)
+      {
+        throw DecodeException
+            .error(ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_SCOPE
+                .get(scopeIntValue));
+      }
+
+      final int dereferencePolicyIntValue = reader.readEnumerated();
+      final DereferenceAliasesPolicy dereferencePolicy = DereferenceAliasesPolicy
+          .valueOf(dereferencePolicyIntValue);
+      if (dereferencePolicy == null)
+      {
+        throw DecodeException
+            .error(ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_DEREF
+                .get(dereferencePolicyIntValue));
+      }
+
+      final int sizeLimit = (int) reader.readInteger();
+      final int timeLimit = (int) reader.readInteger();
+      final boolean typesOnly = reader.readBoolean();
+      final Filter filter = LDAPUtils.decodeFilter(reader);
+
+      message = Requests.newSearchRequest(baseDN, scope, filter);
+      message.setDereferenceAliasesPolicy(dereferencePolicy);
+      try
+      {
+        message.setTimeLimit(timeLimit);
+        message.setSizeLimit(sizeLimit);
+      }
+      catch (final LocalizedIllegalArgumentException e)
+      {
+        throw DecodeException.error(e.getMessageObject());
+      }
+      message.setTypesOnly(typesOnly);
+
+      reader.readStartSequence();
+      try
+      {
+        while (reader.hasNextElement())
+        {
+          message.addAttribute(reader.readOctetStringAsString());
+        }
+      }
+      finally
+      {
+        reader.readEndSequence();
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP SEARCH REQUEST(messageID=%d, request=%s)", messageID,
+          message));
+    }
+
+    handler.searchRequest(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a search result done
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeSearchResult(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+
+    Result message;
+
+    reader.readStartSequence(OP_TYPE_SEARCH_RESULT_DONE);
+    try
+    {
+      final ResultCode resultCode = ResultCode.valueOf(reader.readEnumerated());
+      final String matchedDN = reader.readOctetStringAsString();
+      final String diagnosticMessage = reader.readOctetStringAsString();
+      message = Responses.newResult(resultCode).setMatchedDN(matchedDN)
+          .setDiagnosticMessage(diagnosticMessage);
+      decodeResponseReferrals(reader, message);
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP SEARCH RESULT(messageID=%d, result=%s)", messageID,
+          message));
+    }
+
+    handler.searchResult(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as an LDAP search
+   * result entry protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeSearchResultEntry(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    Entry entry;
+
+    reader.readStartSequence(OP_TYPE_SEARCH_RESULT_ENTRY);
+    try
+    {
+      final String dnString = reader.readOctetStringAsString();
+      final Schema schema = options.getSchemaResolver().resolveSchema(dnString);
+      final DN dn = decodeDN(dnString, schema);
+      entry = options.getEntryFactory().newEntry(dn);
+
+      reader.readStartSequence();
+      try
+      {
+        while (reader.hasNextElement())
+        {
+          reader.readStartSequence();
+          try
+          {
+            final String ads = reader.readOctetStringAsString();
+            final AttributeDescription ad = decodeAttributeDescription(ads,
+                schema);
+            final Attribute attribute = options.getAttributeFactory()
+                .newAttribute(ad);
+
+            reader.readStartSet();
+            try
+            {
+              while (reader.hasNextElement())
+              {
+                attribute.add(reader.readOctetString());
+              }
+              entry.addAttribute(attribute);
+            }
+            finally
+            {
+              reader.readEndSet();
+            }
+          }
+          finally
+          {
+            reader.readEndSequence();
+          }
+        }
+      }
+      finally
+      {
+        reader.readEndSequence();
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    final SearchResultEntry message = Responses.newSearchResultEntry(entry);
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP SEARCH RESULT ENTRY(messageID=%d, entry=%s)", messageID,
+          message));
+    }
+
+    handler.searchResultEntry(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 reader as a search result
+   * reference protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeSearchResultReference(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    SearchResultReference message;
+
+    reader.readStartSequence(OP_TYPE_SEARCH_RESULT_REFERENCE);
+    try
+    {
+      message = Responses.newSearchResultReference(reader
+          .readOctetStringAsString());
+      while (reader.hasNextElement())
+      {
+        message.addURI(reader.readOctetStringAsString());
+      }
+    }
+    finally
+    {
+      reader.readEndSequence();
+    }
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP SEARCH RESULT REFERENCE(messageID=%d, reference=%s)",
+          messageID, message));
+    }
+
+    handler.searchResultReference(p, messageID, message);
+  }
+
+
+
+  /**
+   * Decodes the elements from the provided ASN.1 read as an LDAP unbind request
+   * protocol op.
+   *
+   * @param reader
+   *          The ASN.1 reader.
+   * @param messageID
+   *          The decoded message ID for this message.
+   * @param handler
+   *          The <code>LDAPMessageHandler</code> that will handle this decoded
+   *          message.
+   * @param p
+   *          The parameter to pass into the <code>LDAPMessageHandler</code>
+   * @throws IOException
+   *           If an error occurred while reading bytes to decode.
+   */
+  private <P> void decodeUnbindRequest(final ASN1Reader reader,
+      final int messageID, final LDAPMessageHandler<P> handler, final P p)
+      throws IOException
+  {
+    UnbindRequest message;
+    reader.readNull(OP_TYPE_UNBIND_REQUEST);
+    message = Requests.newUnbindRequest();
+
+    decodeControls(reader, message);
+
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "DECODE LDAP UNBIND REQUEST(messageID=%d, request=%s)", messageID,
+          message));
+    }
+
+    handler.unbindRequest(p, messageID, message);
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPSearchFutureResultImpl.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPSearchFutureResultImpl.java
index 9a2f116..5385a1c 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/LDAPSearchFutureResultImpl.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPSearchFutureResultImpl.java
@@ -29,10 +29,7 @@
 
 
 
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.FutureResult;
-import org.opends.sdk.ResultHandler;
-import org.opends.sdk.SearchResultHandler;
+import org.opends.sdk.*;
 import org.opends.sdk.requests.SearchRequest;
 import org.opends.sdk.responses.Responses;
 import org.opends.sdk.responses.Result;
@@ -45,27 +42,30 @@
  * Search result future implementation.
  */
 final class LDAPSearchFutureResultImpl extends
-    AbstractLDAPFutureResultImpl<Result> implements FutureResult<Result>
+    AbstractLDAPFutureResultImpl<Result> implements FutureResult<Result>,
+    SearchResultHandler
 {
 
-  private final SearchResultHandler searchResultHandler;
+  private SearchResultHandler searchResultHandler;
 
   private final SearchRequest request;
 
 
 
-  LDAPSearchFutureResultImpl(int messageID, SearchRequest request,
-      ResultHandler<Result> resultHandler,
-      SearchResultHandler searchResultHandler, LDAPConnection connection)
+  LDAPSearchFutureResultImpl(final int messageID, final SearchRequest request,
+      final ResultHandler<Result> resultHandler,
+      final SearchResultHandler searchResultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler,
+      final AsynchronousConnection connection)
   {
-    super(messageID, resultHandler, connection);
+    super(messageID, resultHandler, intermediateResponseHandler, connection);
     this.request = request;
     this.searchResultHandler = searchResultHandler;
   }
 
 
 
-  void handleSearchResultEntry(SearchResultEntry entry)
+  public boolean handleEntry(final SearchResultEntry entry)
   {
     // FIXME: there's a potential race condition here - the future could
     // get cancelled between the isDone() call and the handler
@@ -73,16 +73,21 @@
     // the synchronizer.
     if (!isDone())
     {
+      updateTimestamp();
       if (searchResultHandler != null)
       {
-        searchResultHandler.handleEntry(entry);
+        if (!searchResultHandler.handleEntry(entry))
+        {
+          searchResultHandler = null;
+        }
       }
     }
+    return true;
   }
 
 
 
-  void handleSearchResultReference(SearchResultReference reference)
+  public boolean handleReference(final SearchResultReference reference)
   {
     // FIXME: there's a potential race condition here - the future could
     // get cancelled between the isDone() call and the handler
@@ -90,23 +95,30 @@
     // the synchronizer.
     if (!isDone())
     {
+      updateTimestamp();
       if (searchResultHandler != null)
       {
-        searchResultHandler.handleReference(reference);
+        if (!searchResultHandler.handleReference(reference))
+        {
+          searchResultHandler = null;
+        }
       }
     }
+    return true;
   }
 
 
 
-  /**
-   * {@inheritDoc}
-   */
-  Result newErrorResult(ResultCode resultCode,
-      String diagnosticMessage, Throwable cause)
+  @Override
+  public String toString()
   {
-    return Responses.newResult(resultCode).setDiagnosticMessage(
-        diagnosticMessage).setCause(cause);
+    final StringBuilder sb = new StringBuilder();
+    sb.append("LDAPSearchFutureResultImpl(");
+    sb.append("request = ");
+    sb.append(request);
+    super.toString(sb);
+    sb.append(")");
+    return sb.toString();
   }
 
 
@@ -115,4 +127,17 @@
   {
     return request;
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  Result newErrorResult(final ResultCode resultCode,
+      final String diagnosticMessage, final Throwable cause)
+  {
+    return Responses.newResult(resultCode).setDiagnosticMessage(
+        diagnosticMessage).setCause(cause);
+  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPServerFilter.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPServerFilter.java
new file mode 100644
index 0000000..c21c31b
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPServerFilter.java
@@ -0,0 +1,953 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import static com.sun.opends.sdk.ldap.LDAPConstants.OID_NOTICE_OF_DISCONNECTION;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLEngine;
+
+import org.opends.sdk.*;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.requests.*;
+import org.opends.sdk.responses.*;
+
+import com.sun.grizzly.Buffer;
+import com.sun.grizzly.Connection;
+import com.sun.grizzly.Grizzly;
+import com.sun.grizzly.attributes.Attribute;
+import com.sun.grizzly.filterchain.*;
+import com.sun.grizzly.ssl.SSLEngineConfigurator;
+import com.sun.grizzly.ssl.SSLFilter;
+import com.sun.grizzly.ssl.SSLUtils;
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * Grizzly filter implementation for decoding LDAP requests and handling server
+ * side logic for SSL and SASL operations over LDAP.
+ */
+final class LDAPServerFilter extends BaseFilter
+{
+  private abstract class AbstractHandler<R extends Result> implements
+      IntermediateResponseHandler, ResultHandler<R>
+  {
+    protected int messageID;
+    protected Connection<?> connection;
+
+
+
+    protected AbstractHandler(final int messageID,
+        final Connection<?> connection)
+    {
+      this.messageID = messageID;
+      this.connection = connection;
+    }
+
+
+
+    public boolean handleIntermediateResponse(
+        final IntermediateResponse response)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.intermediateResponse(asn1Writer, messageID, response);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+        return false;
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+      return true;
+    }
+
+  }
+
+
+
+  private final class AddHandler extends AbstractHandler<Result>
+  {
+    private AddHandler(final int messageID, final Connection<?> connection)
+    {
+      super(messageID, connection);
+    }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      handleResult(error.getResult());
+    }
+
+
+
+    public void handleResult(final Result result)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.addResult(asn1Writer, messageID, result);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+    }
+  }
+
+
+
+  private final class BindHandler extends AbstractHandler<BindResult>
+  {
+    private BindHandler(final int messageID, final Connection<?> connection)
+    {
+      super(messageID, connection);
+    }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      final Result result = error.getResult();
+      if (result instanceof BindResult)
+      {
+        handleResult((BindResult) result);
+      }
+      else
+      {
+        final BindResult newResult = Responses.newBindResult(result
+            .getResultCode());
+        newResult.setDiagnosticMessage(result.getDiagnosticMessage());
+        newResult.setMatchedDN(result.getMatchedDN());
+        newResult.setCause(result.getCause());
+        for (final Control control : result.getControls())
+        {
+          newResult.addControl(control);
+        }
+        handleResult(newResult);
+      }
+    }
+
+
+
+    public void handleResult(final BindResult result)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.bindResult(asn1Writer, messageID, result);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+    }
+  }
+
+
+
+  private final class ClientContextImpl implements LDAPClientContext
+  {
+    protected Connection<?> connection;
+
+
+
+    private ClientContextImpl(final Connection<?> connection)
+    {
+      this.connection = connection;
+    }
+
+
+
+    public void disconnect(final boolean sendNotification)
+    {
+      if (sendNotification)
+      {
+        final GenericExtendedResult notification = Responses
+            .newGenericExtendedResult(ResultCode.SUCCESS);
+        notification.setOID(OID_NOTICE_OF_DISCONNECTION);
+        sendUnsolicitedNotification(notification);
+      }
+      closeConnection(connection, -1, null);
+    }
+
+
+
+    public InetSocketAddress getLocalAddress()
+    {
+      return (InetSocketAddress) connection.getLocalAddress();
+    }
+
+
+
+    public InetSocketAddress getPeerAddress()
+    {
+      return (InetSocketAddress) connection.getPeerAddress();
+    }
+
+
+
+    public int getSecurityStrengthFactor()
+    {
+      int ssf = 0;
+      final SSLEngine sslEngine = SSLUtils.getSSLEngine(connection);
+      if (sslEngine != null)
+      {
+        final String cipherString = sslEngine.getSession().getCipherSuite();
+        for (final Map.Entry<String, Integer> mapEntry : CIPHER_KEY_SIZES
+            .entrySet())
+        {
+          if (cipherString.indexOf(mapEntry.getKey()) >= 0)
+          {
+            ssf = mapEntry.getValue();
+            break;
+          }
+        }
+      }
+
+      return ssf;
+    }
+
+
+
+    public void sendUnsolicitedNotification(final ExtendedResult notification)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.extendedResult(asn1Writer, 0, notification);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+    }
+
+
+
+    public void startSASL(final ConnectionSecurityLayer bindContext)
+    {
+      installFilter(connection, new SASLFilter(bindContext));
+    }
+
+
+
+    public void startTLS(final SSLContext sslContext)
+    {
+      Validator.ensureNotNull(sslContext);
+      SSLEngineConfigurator sslEngineConfigurator;
+
+      sslEngineConfigurator = new SSLEngineConfigurator(sslContext, false,
+          false, false);
+      installFilter(connection, new SSLFilter(sslEngineConfigurator, null));
+    }
+  }
+
+
+
+  private final class CompareHandler extends AbstractHandler<CompareResult>
+  {
+    private CompareHandler(final int messageID, final Connection<?> connection)
+    {
+      super(messageID, connection);
+    }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      final Result result = error.getResult();
+      if (result instanceof CompareResult)
+      {
+        handleResult((CompareResult) result);
+      }
+      else
+      {
+        final CompareResult newResult = Responses.newCompareResult(result
+            .getResultCode());
+        newResult.setDiagnosticMessage(result.getDiagnosticMessage());
+        newResult.setMatchedDN(result.getMatchedDN());
+        newResult.setCause(result.getCause());
+        for (final Control control : result.getControls())
+        {
+          newResult.addControl(control);
+        }
+        handleResult(newResult);
+      }
+    }
+
+
+
+    public void handleResult(final CompareResult result)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.compareResult(asn1Writer, messageID, result);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+    }
+  }
+
+
+
+  private final class DeleteHandler extends AbstractHandler<Result>
+  {
+    private DeleteHandler(final int messageID, final Connection<?> connection)
+    {
+      super(messageID, connection);
+    }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      handleResult(error.getResult());
+    }
+
+
+
+    public void handleResult(final Result result)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.deleteResult(asn1Writer, messageID, result);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+    }
+  }
+
+
+
+  private final class ExtendedHandler<R extends ExtendedResult> extends
+      AbstractHandler<R>
+  {
+    private ExtendedHandler(final int messageID, final Connection<?> connection)
+    {
+      super(messageID, connection);
+    }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      final Result result = error.getResult();
+      if (result instanceof ExtendedResult)
+      {
+        handleResult((ExtendedResult) result);
+      }
+      else
+      {
+        final ExtendedResult newResult = Responses
+            .newGenericExtendedResult(result.getResultCode());
+        newResult.setDiagnosticMessage(result.getDiagnosticMessage());
+        newResult.setMatchedDN(result.getMatchedDN());
+        newResult.setCause(result.getCause());
+        for (final Control control : result.getControls())
+        {
+          newResult.addControl(control);
+        }
+        handleResult(newResult);
+      }
+    }
+
+
+
+    public void handleResult(final ExtendedResult result)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.extendedResult(asn1Writer, messageID, result);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+    }
+  }
+
+
+
+  private final class ModifyDNHandler extends AbstractHandler<Result>
+  {
+    private ModifyDNHandler(final int messageID, final Connection<?> connection)
+    {
+      super(messageID, connection);
+    }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      handleResult(error.getResult());
+    }
+
+
+
+    public void handleResult(final Result result)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.modifyDNResult(asn1Writer, messageID, result);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+    }
+  }
+
+
+
+  private final class ModifyHandler extends AbstractHandler<Result>
+  {
+    private ModifyHandler(final int messageID, final Connection<?> connection)
+    {
+      super(messageID, connection);
+    }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      handleResult(error.getResult());
+    }
+
+
+
+    public void handleResult(final Result result)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.modifyResult(asn1Writer, messageID, result);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+    }
+  }
+
+
+
+  private final class SearchHandler extends AbstractHandler<Result> implements
+      SearchResultHandler
+  {
+    private SearchHandler(final int messageID, final Connection<?> connection)
+    {
+      super(messageID, connection);
+    }
+
+
+
+    public boolean handleEntry(final SearchResultEntry entry)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.searchResultEntry(asn1Writer, messageID, entry);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+        return false;
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+      return true;
+    }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      handleResult(error.getResult());
+    }
+
+
+
+    public boolean handleReference(final SearchResultReference reference)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.searchResultReference(asn1Writer, messageID, reference);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+        return false;
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+      return true;
+    }
+
+
+
+    public void handleResult(final Result result)
+    {
+      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
+      try
+      {
+        LDAP_WRITER.searchResult(asn1Writer, messageID, result);
+        connection.write(asn1Writer.getBuffer(), null);
+      }
+      catch (final IOException ioe)
+      {
+        closeConnection(connection, ioe);
+      }
+      finally
+      {
+        asn1Writer.recycle();
+      }
+    }
+  }
+
+
+
+  // Map of cipher phrases to effective key size (bits). Taken from the
+  // following RFCs: 5289, 4346, 3268,4132 and 4162.
+  private static final Map<String, Integer> CIPHER_KEY_SIZES;
+
+  static
+  {
+    CIPHER_KEY_SIZES = new LinkedHashMap<String, Integer>();
+    CIPHER_KEY_SIZES.put("_WITH_AES_256_CBC_", 256);
+    CIPHER_KEY_SIZES.put("_WITH_CAMELLIA_256_CBC_", 256);
+    CIPHER_KEY_SIZES.put("_WITH_AES_256_GCM_", 256);
+    CIPHER_KEY_SIZES.put("_WITH_3DES_EDE_CBC_", 112);
+    CIPHER_KEY_SIZES.put("_WITH_AES_128_GCM_", 128);
+    CIPHER_KEY_SIZES.put("_WITH_SEED_CBC_", 128);
+    CIPHER_KEY_SIZES.put("_WITH_CAMELLIA_128_CBC_", 128);
+    CIPHER_KEY_SIZES.put("_WITH_AES_128_CBC_", 128);
+    CIPHER_KEY_SIZES.put("_WITH_IDEA_CBC_", 128);
+    CIPHER_KEY_SIZES.put("_WITH_DES_CBC_", 56);
+    CIPHER_KEY_SIZES.put("_WITH_RC2_CBC_40_", 40);
+    CIPHER_KEY_SIZES.put("_WITH_RC4_40_", 40);
+    CIPHER_KEY_SIZES.put("_WITH_DES40_CBC_", 40);
+    CIPHER_KEY_SIZES.put("_WITH_NULL_", 0);
+  }
+
+  private static final LDAPWriter LDAP_WRITER = new LDAPWriter();
+
+  private static final Attribute<ServerConnection<Integer>>
+    LDAP_CONNECTION_ATTR = Grizzly.DEFAULT_ATTRIBUTE_BUILDER.
+      createAttribute("LDAPServerConnection");
+
+  private static final Attribute<ASN1BufferReader> LDAP_ASN1_READER_ATTR =
+    Grizzly.DEFAULT_ATTRIBUTE_BUILDER.createAttribute("LDAPASN1Reader");
+
+  private final AbstractLDAPMessageHandler<FilterChainContext>
+    serverRequestHandler = new AbstractLDAPMessageHandler<FilterChainContext>()
+  {
+    @Override
+    public void abandonRequest(final FilterChainContext ctx,
+        final int messageID, final AbandonRequest request)
+        throws UnexpectedRequestException
+    {
+      final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      conn.abandon(messageID, request);
+    }
+
+
+
+    @Override
+    public void addRequest(final FilterChainContext ctx, final int messageID,
+        final AddRequest request) throws UnexpectedRequestException
+    {
+      final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final AddHandler handler = new AddHandler(messageID, ctx.getConnection());
+      conn.add(messageID, request, handler, handler);
+    }
+
+
+
+    @Override
+    public void bindRequest(final FilterChainContext ctx, final int messageID,
+        final int version, final GenericBindRequest bindContext)
+        throws UnexpectedRequestException
+    {
+      final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final BindHandler handler = new BindHandler(messageID, ctx
+          .getConnection());
+      conn.bind(messageID, version, bindContext, handler, handler);
+    }
+
+
+
+    @Override
+    public void compareRequest(final FilterChainContext ctx,
+        final int messageID, final CompareRequest request)
+        throws UnexpectedRequestException
+    {
+      final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final CompareHandler handler = new CompareHandler(messageID, ctx
+          .getConnection());
+      conn.compare(messageID, request, handler, handler);
+    }
+
+
+
+    @Override
+    public void deleteRequest(final FilterChainContext ctx,
+        final int messageID, final DeleteRequest request)
+        throws UnexpectedRequestException
+    {
+      final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final DeleteHandler handler = new DeleteHandler(messageID, ctx
+          .getConnection());
+      conn.delete(messageID, request, handler, handler);
+    }
+
+
+
+    @Override
+    public <R extends ExtendedResult> void extendedRequest(
+        final FilterChainContext ctx, final int messageID,
+        final ExtendedRequest<R> request) throws UnexpectedRequestException
+    {
+      final ExtendedHandler<R> handler = new ExtendedHandler<R>(messageID, ctx
+          .getConnection());
+
+      final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      conn.extendedRequest(messageID, request, handler, handler);
+    }
+
+
+
+    @Override
+    public void modifyDNRequest(final FilterChainContext ctx,
+        final int messageID, final ModifyDNRequest request)
+        throws UnexpectedRequestException
+    {
+      final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final ModifyDNHandler handler = new ModifyDNHandler(messageID, ctx
+          .getConnection());
+      conn.modifyDN(messageID, request, handler, handler);
+    }
+
+
+
+    @Override
+    public void modifyRequest(final FilterChainContext ctx,
+        final int messageID, final ModifyRequest request)
+        throws UnexpectedRequestException
+    {
+      final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final ModifyHandler handler = new ModifyHandler(messageID, ctx
+          .getConnection());
+      conn.modify(messageID, request, handler, handler);
+    }
+
+
+
+    @Override
+    public void searchRequest(final FilterChainContext ctx,
+        final int messageID, final SearchRequest request)
+        throws UnexpectedRequestException
+    {
+      final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR.get(ctx
+          .getConnection());
+      final SearchHandler handler = new SearchHandler(messageID, ctx
+          .getConnection());
+      conn.search(messageID, request, handler, handler, handler);
+    }
+
+
+
+    @Override
+    public void unbindRequest(final FilterChainContext ctx,
+        final int messageID, final UnbindRequest request)
+    {
+      closeConnection(ctx.getConnection(), messageID, request);
+    }
+
+
+
+    @Override
+    public void unrecognizedMessage(final FilterChainContext ctx,
+        final int messageID, final byte messageTag,
+        final ByteString messageBytes)
+    {
+      closeConnection(ctx.getConnection(), new UnsupportedMessageException(
+          messageID, messageTag, messageBytes));
+    }
+  };
+
+  private final int maxASN1ElementSize;
+  private final LDAPReader ldapReader;
+  private final LDAPListenerImpl listener;
+
+
+
+  LDAPServerFilter(final LDAPListenerImpl listener,
+      final LDAPReader ldapReader, final int maxASN1ElementSize)
+  {
+    this.listener = listener;
+    this.ldapReader = ldapReader;
+    this.maxASN1ElementSize = maxASN1ElementSize;
+  }
+
+
+
+  @Override
+  public void exceptionOccurred(final FilterChainContext ctx,
+      final Throwable error)
+  {
+    closeConnection(ctx.getConnection(), error);
+  }
+
+
+
+  @Override
+  public NextAction handleAccept(final FilterChainContext ctx)
+      throws IOException
+  {
+    final Connection<?> connection = ctx.getConnection();
+    connection.configureBlocking(true);
+    ServerConnection<Integer> serverConn;
+    try
+    {
+      serverConn = listener.getConnectionFactory().accept(
+          new ClientContextImpl(connection));
+      LDAP_CONNECTION_ATTR.set(connection, serverConn);
+    }
+    catch (final ErrorResultException e)
+    {
+      connection.close();
+    }
+
+    return ctx.getStopAction();
+  }
+
+
+
+  @Override
+  public NextAction handleClose(final FilterChainContext ctx)
+      throws IOException
+  {
+    closeConnection(ctx.getConnection(), -1, null);
+    return ctx.getStopAction();
+  }
+
+
+
+  @Override
+  public NextAction handleRead(final FilterChainContext ctx) throws IOException
+  {
+    final Buffer buffer = (Buffer) ctx.getMessage();
+    ASN1BufferReader asn1Reader = LDAP_ASN1_READER_ATTR
+        .get(ctx.getConnection());
+    if (asn1Reader == null)
+    {
+      asn1Reader = new ASN1BufferReader(maxASN1ElementSize);
+      LDAP_ASN1_READER_ATTR.set(ctx.getConnection(), asn1Reader);
+    }
+    asn1Reader.appendBytesRead(buffer);
+
+    try
+    {
+      while (asn1Reader.elementAvailable())
+      {
+        ldapReader.decode(asn1Reader, serverRequestHandler, ctx);
+      }
+    }
+    finally
+    {
+      asn1Reader.disposeBytesRead();
+    }
+
+    return ctx.getStopAction();
+  }
+
+
+
+  private void closeConnection(final Connection<?> connection,
+      final int messageID, final UnbindRequest unbindRequest)
+  {
+    final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR
+        .remove(connection);
+    if (conn != null)
+    {
+      conn.closed(messageID, unbindRequest);
+      try
+      {
+        connection.close();
+      }
+      catch (final IOException e)
+      {
+        StaticUtils.DEBUG_LOG.warning("Error closing connection: " + e);
+      }
+    }
+  }
+
+
+
+  private void closeConnection(final Connection<?> connection,
+      final Throwable error)
+  {
+    final ServerConnection<Integer> conn = LDAP_CONNECTION_ATTR
+        .remove(connection);
+    if (conn != null)
+    {
+      conn.closed(error);
+      try
+      {
+        connection.close();
+      }
+      catch (final IOException e)
+      {
+        StaticUtils.DEBUG_LOG.warning("Error closing connection: " + e);
+      }
+    }
+  }
+
+
+
+  private synchronized void installFilter(final Connection<?> connection,
+      final com.sun.grizzly.filterchain.Filter filter)
+  {
+    FilterChain filterChain = (FilterChain) connection.getProcessor();
+    if (filter instanceof SSLFilter)
+    {
+      if (filterChain.get(filterChain.size() - 1) instanceof SSLFilter
+          || filterChain.get(filterChain.size() - 2) instanceof SSLFilter)
+      {
+        // SSLFilter already installed.
+        throw new IllegalStateException(
+            "SSLFilter already installed on connection");
+      }
+    }
+    if (filter instanceof SASLFilter)
+    {
+      if (filterChain.get(filterChain.size() - 1) instanceof SASLFilter)
+      {
+        // SASLFilter already installed.
+        throw new IllegalStateException(
+            "SASLFilter already installed on connection");
+      }
+    }
+
+    if (listener.getDefaultFilterChain() == filterChain)
+    {
+      filterChain = new DefaultFilterChain(filterChain);
+      connection.setProcessor(filterChain);
+    }
+
+    if (filter instanceof SSLFilter
+        && filterChain.get(filterChain.size() - 1) instanceof SASLFilter)
+    {
+      filterChain.add(filterChain.size() - 2, filter);
+    }
+    else
+    {
+      filterChain.add(filterChain.size() - 1, filter);
+    }
+
+  }
+}
diff --git a/sdk/src/org/opends/sdk/ldap/LDAPUtils.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPUtils.java
similarity index 68%
rename from sdk/src/org/opends/sdk/ldap/LDAPUtils.java
rename to sdk/src/com/sun/opends/sdk/ldap/LDAPUtils.java
index 872c9da..b91adc1 100644
--- a/sdk/src/org/opends/sdk/ldap/LDAPUtils.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPUtils.java
@@ -25,7 +25,7 @@
  *      Copyright 2009 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.ldap;
+package com.sun.opends.sdk.ldap;
 
 
 
@@ -36,36 +36,33 @@
 import java.util.LinkedList;
 import java.util.List;
 
-import org.opends.sdk.ByteSequence;
-import org.opends.sdk.ByteString;
-import org.opends.sdk.Filter;
-import org.opends.sdk.FilterVisitor;
+import org.opends.sdk.*;
 import org.opends.sdk.asn1.ASN1Reader;
 import org.opends.sdk.asn1.ASN1Writer;
 import org.opends.sdk.responses.SearchResultEntry;
-import org.opends.sdk.schema.Schema;
 
 
 
 /**
- * Common LDAP utility methods which may be used when implementing new
- * controls and extension.
+ * Common LDAP utility methods which may be used when implementing new controls
+ * and extension.
  */
 public final class LDAPUtils
 {
 
-  private static final FilterVisitor<IOException, ASN1Writer> ASN1_ENCODER = new FilterVisitor<IOException, ASN1Writer>()
+  private static final FilterVisitor<IOException, ASN1Writer> ASN1_ENCODER =
+    new FilterVisitor<IOException, ASN1Writer>()
   {
 
-    public IOException visitAndFilter(ASN1Writer writer,
-        List<Filter> subFilters)
+    public IOException visitAndFilter(final ASN1Writer writer,
+        final List<Filter> subFilters)
     {
       try
       {
         writer.writeStartSequence(TYPE_FILTER_AND);
-        for (Filter subFilter : subFilters)
+        for (final Filter subFilter : subFilters)
         {
-          IOException e = subFilter.accept(this, writer);
+          final IOException e = subFilter.accept(this, writer);
           if (e != null)
           {
             return e;
@@ -74,7 +71,7 @@
         writer.writeEndSequence();
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -82,8 +79,8 @@
 
 
 
-    public IOException visitApproxMatchFilter(ASN1Writer writer,
-        String attributeDescription, ByteString assertionValue)
+    public IOException visitApproxMatchFilter(final ASN1Writer writer,
+        final String attributeDescription, final ByteString assertionValue)
     {
       try
       {
@@ -93,7 +90,7 @@
         writer.writeEndSequence();
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -101,8 +98,8 @@
 
 
 
-    public IOException visitEqualityMatchFilter(ASN1Writer writer,
-        String attributeDescription, ByteString assertionValue)
+    public IOException visitEqualityMatchFilter(final ASN1Writer writer,
+        final String attributeDescription, final ByteString assertionValue)
     {
       try
       {
@@ -112,7 +109,7 @@
         writer.writeEndSequence();
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -120,9 +117,9 @@
 
 
 
-    public IOException visitExtensibleMatchFilter(ASN1Writer writer,
-        String matchingRule, String attributeDescription,
-        ByteString assertionValue, boolean dnAttributes)
+    public IOException visitExtensibleMatchFilter(final ASN1Writer writer,
+        final String matchingRule, final String attributeDescription,
+        final ByteString assertionValue, final boolean dnAttributes)
     {
       try
       {
@@ -135,12 +132,11 @@
 
         if (attributeDescription != null)
         {
-          writer.writeOctetString(TYPE_MATCHING_RULE_TYPE,
-              attributeDescription);
+          writer
+              .writeOctetString(TYPE_MATCHING_RULE_TYPE, attributeDescription);
         }
 
-        writer.writeOctetString(TYPE_MATCHING_RULE_VALUE,
-            assertionValue);
+        writer.writeOctetString(TYPE_MATCHING_RULE_VALUE, assertionValue);
 
         if (dnAttributes)
         {
@@ -150,7 +146,7 @@
         writer.writeEndSequence();
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -158,8 +154,8 @@
 
 
 
-    public IOException visitGreaterOrEqualFilter(ASN1Writer writer,
-        String attributeDescription, ByteString assertionValue)
+    public IOException visitGreaterOrEqualFilter(final ASN1Writer writer,
+        final String attributeDescription, final ByteString assertionValue)
     {
       try
       {
@@ -169,7 +165,7 @@
         writer.writeEndSequence();
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -177,8 +173,8 @@
 
 
 
-    public IOException visitLessOrEqualFilter(ASN1Writer writer,
-        String attributeDescription, ByteString assertionValue)
+    public IOException visitLessOrEqualFilter(final ASN1Writer writer,
+        final String attributeDescription, final ByteString assertionValue)
     {
       try
       {
@@ -188,7 +184,7 @@
         writer.writeEndSequence();
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -196,13 +192,13 @@
 
 
 
-    public IOException visitNotFilter(ASN1Writer writer,
-        Filter subFilter)
+    public IOException visitNotFilter(final ASN1Writer writer,
+        final Filter subFilter)
     {
       try
       {
         writer.writeStartSequence(TYPE_FILTER_NOT);
-        IOException e = subFilter.accept(this, writer);
+        final IOException e = subFilter.accept(this, writer);
         if (e != null)
         {
           return e;
@@ -210,7 +206,7 @@
         writer.writeEndSequence();
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -218,15 +214,15 @@
 
 
 
-    public IOException visitOrFilter(ASN1Writer writer,
-        List<Filter> subFilters)
+    public IOException visitOrFilter(final ASN1Writer writer,
+        final List<Filter> subFilters)
     {
       try
       {
         writer.writeStartSequence(TYPE_FILTER_OR);
-        for (Filter subFilter : subFilters)
+        for (final Filter subFilter : subFilters)
         {
-          IOException e = subFilter.accept(this, writer);
+          final IOException e = subFilter.accept(this, writer);
           if (e != null)
           {
             return e;
@@ -235,7 +231,7 @@
         writer.writeEndSequence();
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -243,16 +239,15 @@
 
 
 
-    public IOException visitPresentFilter(ASN1Writer writer,
-        String attributeDescription)
+    public IOException visitPresentFilter(final ASN1Writer writer,
+        final String attributeDescription)
     {
       try
       {
-        writer.writeOctetString(TYPE_FILTER_PRESENCE,
-            attributeDescription);
+        writer.writeOctetString(TYPE_FILTER_PRESENCE, attributeDescription);
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -260,9 +255,9 @@
 
 
 
-    public IOException visitSubstringsFilter(ASN1Writer writer,
-        String attributeDescription, ByteString initialSubstring,
-        List<ByteString> anySubstrings, ByteString finalSubstring)
+    public IOException visitSubstringsFilter(final ASN1Writer writer,
+        final String attributeDescription, final ByteString initialSubstring,
+        final List<ByteString> anySubstrings, final ByteString finalSubstring)
     {
       try
       {
@@ -275,7 +270,7 @@
           writer.writeOctetString(TYPE_SUBINITIAL, initialSubstring);
         }
 
-        for (ByteSequence anySubstring : anySubstrings)
+        for (final ByteSequence anySubstring : anySubstrings)
         {
           writer.writeOctetString(TYPE_SUBANY, anySubstring);
         }
@@ -289,7 +284,7 @@
         writer.writeEndSequence();
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -297,15 +292,15 @@
 
 
 
-    public IOException visitUnrecognizedFilter(ASN1Writer writer,
-        byte filterTag, ByteString filterBytes)
+    public IOException visitUnrecognizedFilter(final ASN1Writer writer,
+        final byte filterTag, final ByteString filterBytes)
     {
       try
       {
         writer.writeOctetString(filterTag, filterBytes);
         return null;
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         return e;
       }
@@ -315,20 +310,19 @@
 
 
   /**
-   * Reads the next ASN.1 element from the provided {@code ASN1Reader}
-   * as a {@code Filter}.
+   * Reads the next ASN.1 element from the provided {@code ASN1Reader} as a
+   * {@code Filter}.
    *
    * @param reader
-   *          The {@code ASN1Reader} from which the ASN.1 encoded
-   *          {@code Filter} should be read.
+   *          The {@code ASN1Reader} from which the ASN.1 encoded {@code Filter}
+   *          should be read.
    * @return The decoded {@code Filter}.
    * @throws IOException
    *           If an error occurs while reading from {@code reader}.
    */
-  public static Filter decodeFilter(ASN1Reader reader)
-      throws IOException
+  public static Filter decodeFilter(final ASN1Reader reader) throws IOException
   {
-    byte type = reader.peekType();
+    final byte type = reader.peekType();
 
     switch (type)
     {
@@ -357,58 +351,56 @@
       return decodeSubstringsFilter(reader);
 
     case TYPE_FILTER_PRESENCE:
-      return Filter.newPresentFilter(reader
-          .readOctetStringAsString(type));
+      return Filter.newPresentFilter(reader.readOctetStringAsString(type));
 
     case TYPE_FILTER_EXTENSIBLE_MATCH:
       return decodeExtensibleMatchFilter(reader);
 
     default:
-      return Filter.newUnrecognizedFilter(type, reader
-          .readOctetString(type));
+      return Filter.newUnrecognizedFilter(type, reader.readOctetString(type));
     }
   }
 
 
 
   /**
-   * Reads the next ASN.1 element from the provided {@code ASN1Reader}
-   * as a {@code SearchResultEntry}.
+   * Reads the next ASN.1 element from the provided {@code ASN1Reader} as a
+   * {@code SearchResultEntry}.
    *
    * @param reader
-   *          The {@code ASN1Reader} from which the ASN.1 encoded
-   *          {@code SearchResultEntry} should be read.
-   * @param schema
-   *          The schema to use when decoding the entry.
+   *          The {@code ASN1Reader} from which the ASN.1 encoded {@code
+   *          SearchResultEntry} should be read.
+   * @param options
+   *          The decode options to use when decoding the entry.
    * @return The decoded {@code SearchResultEntry}.
    * @throws IOException
    *           If an error occurs while reading from {@code reader}.
    */
   public static SearchResultEntry decodeSearchResultEntry(
-      ASN1Reader reader, Schema schema) throws IOException
+      final ASN1Reader reader, final DecodeOptions options) throws IOException
   {
-    return LDAPDecoder.decodeEntry(reader, schema);
+    return LDAPReader.decodeEntry(reader, options);
   }
 
 
 
   /**
-   * Writes the ASN.1 encoding of the provided {@code Filter} to the
-   * provided {@code ASN1Writer}.
+   * Writes the ASN.1 encoding of the provided {@code Filter} to the provided
+   * {@code ASN1Writer}.
    *
    * @param writer
-   *          The {@code ASN1Writer} to which the ASN.1 encoding of the
-   *          provided {@code Filter} should be written.
+   *          The {@code ASN1Writer} to which the ASN.1 encoding of the provided
+   *          {@code Filter} should be written.
    * @param filter
    *          The filter to be encoded.
    * @return The updated {@code ASN1Writer}.
    * @throws IOException
    *           If an error occurs while writing to {@code writer}.
    */
-  public static ASN1Writer encodeFilter(ASN1Writer writer, Filter filter)
-      throws IOException
+  public static ASN1Writer encodeFilter(final ASN1Writer writer,
+      final Filter filter) throws IOException
   {
-    IOException e = filter.accept(ASN1_ENCODER, writer);
+    final IOException e = filter.accept(ASN1_ENCODER, writer);
     if (e != null)
     {
       throw e;
@@ -422,29 +414,30 @@
 
 
   /**
-   * Writes the ASN.1 encoding of the provided {@code SearchResultEntry}
-   * to the provided {@code ASN1Writer}.
+   * Writes the ASN.1 encoding of the provided {@code SearchResultEntry} to the
+   * provided {@code ASN1Writer}.
    *
    * @param writer
-   *          The {@code ASN1Writer} to which the ASN.1 encoding of the
-   *          provided {@code SearchResultEntry} should be written.
+   *          The {@code ASN1Writer} to which the ASN.1 encoding of the provided
+   *          {@code SearchResultEntry} should be written.
    * @param entry
    *          The Search Result Entry to be encoded.
    * @return The updated {@code ASN1Writer}.
    * @throws IOException
    *           If an error occurs while writing to {@code writer}.
    */
-  public static ASN1Writer encodeSearchResultEntry(ASN1Writer writer,
-      SearchResultEntry entry) throws IOException
+  public static ASN1Writer encodeSearchResultEntry(final ASN1Writer writer,
+      final SearchResultEntry entry) throws IOException
   {
-    LDAPEncoder.encodeEntry(writer, entry);
+    // FIXME: this should include Controls.
+    LDAPWriter.encodeEntry(writer, entry);
     return writer;
   }
 
 
 
   // Decodes an and filter.
-  private static Filter decodeAndFilter(ASN1Reader reader)
+  private static Filter decodeAndFilter(final ASN1Reader reader)
       throws IOException
   {
     Filter filter;
@@ -454,11 +447,12 @@
     {
       if (reader.hasNextElement())
       {
-        List<Filter> subFilters = new LinkedList<Filter>();
+        final List<Filter> subFilters = new LinkedList<Filter>();
         do
         {
           subFilters.add(decodeFilter(reader));
-        } while (reader.hasNextElement());
+        }
+        while (reader.hasNextElement());
         filter = Filter.newAndFilter(subFilters);
       }
       else
@@ -478,7 +472,7 @@
 
 
   // Decodes an approximate match filter.
-  private static Filter decodeApproxMatchFilter(ASN1Reader reader)
+  private static Filter decodeApproxMatchFilter(final ASN1Reader reader)
       throws IOException
   {
     String attributeDescription;
@@ -495,14 +489,13 @@
       reader.readEndSequence();
     }
 
-    return Filter.newApproxMatchFilter(attributeDescription,
-        assertionValue);
+    return Filter.newApproxMatchFilter(attributeDescription, assertionValue);
   }
 
 
 
   // Decodes an equality match filter.
-  private static Filter decodeEqualityMatchFilter(ASN1Reader reader)
+  private static Filter decodeEqualityMatchFilter(final ASN1Reader reader)
       throws IOException
   {
     String attributeDescription;
@@ -519,14 +512,13 @@
       reader.readEndSequence();
     }
 
-    return Filter.newEqualityMatchFilter(attributeDescription,
-        assertionValue);
+    return Filter.newEqualityMatchFilter(attributeDescription, assertionValue);
   }
 
 
 
   // Decodes an extensible match filter.
-  private static Filter decodeExtensibleMatchFilter(ASN1Reader reader)
+  private static Filter decodeExtensibleMatchFilter(final ASN1Reader reader)
       throws IOException
   {
     String matchingRule;
@@ -540,8 +532,7 @@
       matchingRule = null;
       if (reader.peekType() == TYPE_MATCHING_RULE_ID)
       {
-        matchingRule = reader
-            .readOctetStringAsString(TYPE_MATCHING_RULE_ID);
+        matchingRule = reader.readOctetStringAsString(TYPE_MATCHING_RULE_ID);
       }
       attributeDescription = null;
       if (reader.peekType() == TYPE_MATCHING_RULE_TYPE)
@@ -562,15 +553,15 @@
       reader.readEndSequence();
     }
 
-    return Filter.newExtensibleMatchFilter(matchingRule,
-        attributeDescription, assertionValue, dnAttributes);
+    return Filter.newExtensibleMatchFilter(matchingRule, attributeDescription,
+        assertionValue, dnAttributes);
   }
 
 
 
   // Decodes a greater than or equal filter.
-  private static Filter decodeGreaterOrEqualMatchFilter(
-      ASN1Reader reader) throws IOException
+  private static Filter decodeGreaterOrEqualMatchFilter(final ASN1Reader reader)
+      throws IOException
   {
     String attributeDescription;
     ByteString assertionValue;
@@ -585,14 +576,13 @@
     {
       reader.readEndSequence();
     }
-    return Filter.newGreaterOrEqualFilter(attributeDescription,
-        assertionValue);
+    return Filter.newGreaterOrEqualFilter(attributeDescription, assertionValue);
   }
 
 
 
   // Decodes a less than or equal filter.
-  private static Filter decodeLessOrEqualMatchFilter(ASN1Reader reader)
+  private static Filter decodeLessOrEqualMatchFilter(final ASN1Reader reader)
       throws IOException
   {
     String attributeDescription;
@@ -609,14 +599,13 @@
       reader.readEndSequence();
     }
 
-    return Filter.newLessOrEqualFilter(attributeDescription,
-        assertionValue);
+    return Filter.newLessOrEqualFilter(attributeDescription, assertionValue);
   }
 
 
 
   // Decodes a not filter.
-  private static Filter decodeNotFilter(ASN1Reader reader)
+  private static Filter decodeNotFilter(final ASN1Reader reader)
       throws IOException
   {
     Filter subFilter;
@@ -637,7 +626,7 @@
 
 
   // Decodes an or filter.
-  private static Filter decodeOrFilter(ASN1Reader reader)
+  private static Filter decodeOrFilter(final ASN1Reader reader)
       throws IOException
   {
     Filter filter;
@@ -647,11 +636,12 @@
     {
       if (reader.hasNextElement())
       {
-        List<Filter> subFilters = new LinkedList<Filter>();
+        final List<Filter> subFilters = new LinkedList<Filter>();
         do
         {
           subFilters.add(decodeFilter(reader));
-        } while (reader.hasNextElement());
+        }
+        while (reader.hasNextElement());
         filter = Filter.newOrFilter(subFilters);
       }
       else
@@ -671,7 +661,7 @@
 
 
   // Decodes a sub-strings filter.
-  private static Filter decodeSubstringsFilter(ASN1Reader reader)
+  private static Filter decodeSubstringsFilter(final ASN1Reader reader)
       throws IOException
   {
     ByteString initialSubstring = null;
@@ -692,18 +682,16 @@
         {
           initialSubstring = reader.readOctetString(TYPE_SUBINITIAL);
         }
-        if (reader.hasNextElement()
-            && (reader.peekType() == TYPE_SUBANY))
+        if (reader.hasNextElement() && (reader.peekType() == TYPE_SUBANY))
         {
           anySubstrings = new LinkedList<ByteString>();
           do
           {
             anySubstrings.add(reader.readOctetString(TYPE_SUBANY));
-          } while (reader.hasNextElement()
-              && (reader.peekType() == TYPE_SUBANY));
+          }
+          while (reader.hasNextElement() && (reader.peekType() == TYPE_SUBANY));
         }
-        if (reader.hasNextElement()
-            && (reader.peekType() == TYPE_SUBFINAL))
+        if (reader.hasNextElement() && (reader.peekType() == TYPE_SUBFINAL))
         {
           finalSubstring = reader.readOctetString(TYPE_SUBFINAL);
         }
@@ -723,8 +711,8 @@
       anySubstrings = Collections.emptyList();
     }
 
-    return Filter.newSubstringsFilter(attributeDescription,
-        initialSubstring, anySubstrings, finalSubstring);
+    return Filter.newSubstringsFilter(attributeDescription, initialSubstring,
+        anySubstrings, finalSubstring);
   }
 
 
diff --git a/sdk/src/com/sun/opends/sdk/ldap/LDAPWriter.java b/sdk/src/com/sun/opends/sdk/ldap/LDAPWriter.java
new file mode 100644
index 0000000..4417714
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/LDAPWriter.java
@@ -0,0 +1,677 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import static com.sun.opends.sdk.ldap.LDAPConstants.*;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.logging.Level;
+
+import org.opends.sdk.Attribute;
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DN;
+import org.opends.sdk.Modification;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.requests.*;
+import org.opends.sdk.responses.*;
+
+import com.sun.opends.sdk.util.StaticUtils;
+
+
+
+/**
+ * Static methods for encoding LDAP messages.
+ */
+final class LDAPWriter implements LDAPMessageHandler<ASN1Writer>
+{
+  public static void encodeControl(final ASN1Writer writer,
+      final Control control) throws IOException
+  {
+    writer.writeStartSequence();
+    writer.writeOctetString(control.getOID());
+    if (control.isCritical())
+    {
+      writer.writeBoolean(control.isCritical());
+    }
+    if (control.getValue() != null)
+    {
+      writer.writeOctetString(control.getValue());
+    }
+    writer.writeEndSequence();
+  }
+
+
+
+  public static void encodeEntry(final ASN1Writer writer,
+      final SearchResultEntry searchResultEntry) throws IOException
+  {
+    writer.writeStartSequence(OP_TYPE_SEARCH_RESULT_ENTRY);
+    writer.writeOctetString(searchResultEntry.getName().toString());
+
+    writer.writeStartSequence();
+    for (final Attribute attr : searchResultEntry.getAllAttributes())
+    {
+      encodeAttribute(writer, attr);
+    }
+    writer.writeEndSequence();
+    writer.writeEndSequence();
+  }
+
+
+
+  private static void encodeAttribute(final ASN1Writer writer,
+      final Attribute attribute) throws IOException
+  {
+    writer.writeStartSequence();
+    writer.writeOctetString(attribute.getAttributeDescriptionAsString());
+
+    writer.writeStartSet();
+    for (final ByteString value : attribute)
+    {
+      writer.writeOctetString(value);
+    }
+    writer.writeEndSequence();
+
+    writer.writeEndSequence();
+  }
+
+
+
+  private static void encodeChange(final ASN1Writer writer,
+      final Modification change) throws IOException
+  {
+    writer.writeStartSequence();
+    writer.writeEnumerated(change.getModificationType().intValue());
+    encodeAttribute(writer, change.getAttribute());
+    writer.writeEndSequence();
+  }
+
+
+
+  private static void encodeMessageFooter(final ASN1Writer writer,
+      final Request request) throws IOException
+  {
+    final List<Control> controls = request.getControls();
+    if (!controls.isEmpty())
+    {
+      writer.writeStartSequence(TYPE_CONTROL_SEQUENCE);
+      for (final Control control : controls)
+      {
+        encodeControl(writer, control);
+      }
+      writer.writeEndSequence();
+    }
+
+    writer.writeEndSequence();
+  }
+
+
+
+  private static void encodeMessageFooter(final ASN1Writer writer,
+      final Response response) throws IOException
+  {
+    final List<Control> controls = response.getControls();
+    if (!controls.isEmpty())
+    {
+      writer.writeStartSequence(TYPE_CONTROL_SEQUENCE);
+      for (final Control control : controls)
+      {
+        encodeControl(writer, control);
+      }
+      writer.writeEndSequence();
+    }
+
+    writer.writeEndSequence();
+  }
+
+
+
+  private static void encodeMessageHeader(final ASN1Writer writer,
+      final int messageID) throws IOException
+  {
+    writer.writeStartSequence();
+    writer.writeInteger(messageID);
+  }
+
+
+
+  private static void encodeResultFooter(final ASN1Writer writer)
+      throws IOException
+  {
+    writer.writeEndSequence();
+  }
+
+
+
+  private static void encodeResultHeader(final ASN1Writer writer,
+      final byte typeTag, final Result rawMessage) throws IOException
+  {
+    writer.writeStartSequence(typeTag);
+    writer.writeEnumerated(rawMessage.getResultCode().intValue());
+    writer.writeOctetString(rawMessage.getMatchedDN());
+    writer.writeOctetString(rawMessage.getDiagnosticMessage());
+
+    final List<String> referralURIs = rawMessage.getReferralURIs();
+    if (!referralURIs.isEmpty())
+    {
+      writer.writeStartSequence(TYPE_REFERRAL_SEQUENCE);
+      for (final String s : referralURIs)
+      {
+        writer.writeOctetString(s);
+      }
+      writer.writeEndSequence();
+    }
+  }
+
+
+
+  public void abandonRequest(final ASN1Writer writer, final int messageID,
+      final AbandonRequest request) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP ABANDON REQUEST(messageID=%d, request=%s)", messageID,
+          request));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeInteger(OP_TYPE_ABANDON_REQUEST, request.getMessageID());
+    encodeMessageFooter(writer, request);
+  }
+
+
+
+  public void addRequest(final ASN1Writer writer, final int messageID,
+      final AddRequest request) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP ADD REQUEST(messageID=%d, request=%s)", messageID,
+          request));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeStartSequence(OP_TYPE_ADD_REQUEST);
+    writer.writeOctetString(request.getName().toString());
+
+    // Write the attributes
+    writer.writeStartSequence();
+    for (final Attribute attr : request.getAllAttributes())
+    {
+      encodeAttribute(writer, attr);
+    }
+    writer.writeEndSequence();
+
+    writer.writeEndSequence();
+    encodeMessageFooter(writer, request);
+  }
+
+
+
+  public void addResult(final ASN1Writer writer, final int messageID,
+      final Result result) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG
+          .finer(String.format(
+              "ENCODE LDAP ADD RESULT(messageID=%d, result=%s)", messageID,
+              result));
+    }
+    encodeMessageHeader(writer, messageID);
+    encodeResultHeader(writer, OP_TYPE_ADD_RESPONSE, result);
+    encodeResultFooter(writer);
+    encodeMessageFooter(writer, result);
+  }
+
+
+
+  public void bindRequest(final ASN1Writer writer, final int messageID,
+      final int version, final GenericBindRequest request) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP BIND REQUEST(messageID=%d, auth=0x%x, request=%s)",
+          messageID, request.getAuthenticationType(), request));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeStartSequence(OP_TYPE_BIND_REQUEST);
+
+    writer.writeInteger(version);
+    writer.writeOctetString(request.getName());
+    writer.writeOctetString(request.getAuthenticationType(), request
+        .getAuthenticationValue());
+
+    writer.writeEndSequence();
+    encodeMessageFooter(writer, request);
+  }
+
+
+
+  public void bindResult(final ASN1Writer writer, final int messageID,
+      final BindResult result) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String
+          .format("ENCODE LDAP BIND RESULT(messageID=%d, result=%s)",
+              messageID, result));
+    }
+    encodeMessageHeader(writer, messageID);
+    encodeResultHeader(writer, OP_TYPE_BIND_RESPONSE, result);
+
+    final ByteString saslCredentials = result.getServerSASLCredentials();
+    if (saslCredentials != null && saslCredentials.length() > 0)
+    {
+      writer.writeOctetString(TYPE_SERVER_SASL_CREDENTIALS, result
+          .getServerSASLCredentials());
+    }
+
+    encodeResultFooter(writer);
+    encodeMessageFooter(writer, result);
+  }
+
+
+
+  public void compareRequest(final ASN1Writer writer, final int messageID,
+      final CompareRequest request) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP COMPARE REQUEST(messageID=%d, request=%s)", messageID,
+          request));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeStartSequence(OP_TYPE_COMPARE_REQUEST);
+    writer.writeOctetString(request.getName().toString());
+
+    writer.writeStartSequence();
+    writer.writeOctetString(request.getAttributeDescription().toString());
+    writer.writeOctetString(request.getAssertionValue());
+    writer.writeEndSequence();
+
+    writer.writeEndSequence();
+    encodeMessageFooter(writer, request);
+  }
+
+
+
+  public void compareResult(final ASN1Writer writer, final int messageID,
+      final CompareResult result) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP COMPARE RESULT(messageID=%d, result=%s)", messageID,
+          result));
+    }
+    encodeMessageHeader(writer, messageID);
+    encodeResultHeader(writer, OP_TYPE_COMPARE_RESPONSE, result);
+    encodeResultFooter(writer);
+    encodeMessageFooter(writer, result);
+  }
+
+
+
+  public void deleteRequest(final ASN1Writer writer, final int messageID,
+      final DeleteRequest request) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP DELETE REQUEST(messageID=%d, request=%s)", messageID,
+          request));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeOctetString(OP_TYPE_DELETE_REQUEST, request.getName()
+        .toString());
+    encodeMessageFooter(writer, request);
+  }
+
+
+
+  public void deleteResult(final ASN1Writer writer, final int messageID,
+      final Result result) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP DELETE RESULT(messageID=%d, result=%s)", messageID,
+          result));
+    }
+    encodeMessageHeader(writer, messageID);
+    encodeResultHeader(writer, OP_TYPE_DELETE_RESPONSE, result);
+    encodeResultFooter(writer);
+    encodeMessageFooter(writer, result);
+  }
+
+
+
+  public <R extends ExtendedResult> void extendedRequest(
+      final ASN1Writer writer, final int messageID,
+      final ExtendedRequest<R> request) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP EXTENDED REQUEST(messageID=%d, request=%s)", messageID,
+          request));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeStartSequence(OP_TYPE_EXTENDED_REQUEST);
+    writer.writeOctetString(TYPE_EXTENDED_REQUEST_OID, request.getOID());
+
+    final ByteString requestValue = request.getValue();
+    if (requestValue != null)
+    {
+      writer.writeOctetString(TYPE_EXTENDED_REQUEST_VALUE, requestValue);
+    }
+
+    writer.writeEndSequence();
+    encodeMessageFooter(writer, request);
+  }
+
+
+
+  public void extendedResult(final ASN1Writer writer, final int messageID,
+      final ExtendedResult result) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP EXTENDED RESULT(messageID=%d, result=%s)", messageID,
+          result));
+    }
+    encodeMessageHeader(writer, messageID);
+    encodeResultHeader(writer, OP_TYPE_EXTENDED_RESPONSE, result);
+
+    final String responseName = result.getOID();
+    final ByteString responseValue = result.getValue();
+
+    if (responseName != null)
+    {
+      writer.writeOctetString(TYPE_EXTENDED_RESPONSE_OID, responseName);
+    }
+
+    if (responseValue != null)
+    {
+      writer.writeOctetString(TYPE_EXTENDED_RESPONSE_VALUE, responseValue);
+    }
+
+    encodeResultFooter(writer);
+    encodeMessageFooter(writer, result);
+  }
+
+
+
+  public void intermediateResponse(final ASN1Writer writer,
+      final int messageID, final IntermediateResponse response)
+      throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP INTERMEDIATE RESPONSE(messageID=%d, response=%s)",
+          messageID, response));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeStartSequence(OP_TYPE_INTERMEDIATE_RESPONSE);
+
+    final String responseName = response.getOID();
+    final ByteString responseValue = response.getValue();
+
+    if (responseName != null)
+    {
+      writer
+          .writeOctetString(TYPE_INTERMEDIATE_RESPONSE_OID, response.getOID());
+    }
+
+    if (responseValue != null)
+    {
+      writer.writeOctetString(TYPE_INTERMEDIATE_RESPONSE_VALUE, response
+          .getValue());
+    }
+
+    writer.writeEndSequence();
+    encodeMessageFooter(writer, response);
+  }
+
+
+
+  public void modifyDNRequest(final ASN1Writer writer, final int messageID,
+      final ModifyDNRequest request) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP MODIFY DN REQUEST(messageID=%d, request=%s)", messageID,
+          request));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeStartSequence(OP_TYPE_MODIFY_DN_REQUEST);
+    writer.writeOctetString(request.getName().toString());
+    writer.writeOctetString(request.getNewRDN().toString());
+    writer.writeBoolean(request.isDeleteOldRDN());
+
+    final DN newSuperior = request.getNewSuperior();
+    if (newSuperior != null)
+    {
+      writer.writeOctetString(TYPE_MODIFY_DN_NEW_SUPERIOR, newSuperior
+          .toString());
+    }
+
+    writer.writeEndSequence();
+    encodeMessageFooter(writer, request);
+  }
+
+
+
+  public void modifyDNResult(final ASN1Writer writer, final int messageID,
+      final Result result) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP MODIFY DN RESULT(messageID=%d, result=%s)", messageID,
+          result));
+    }
+    encodeMessageHeader(writer, messageID);
+    encodeResultHeader(writer, OP_TYPE_MODIFY_DN_RESPONSE, result);
+    encodeResultFooter(writer);
+    encodeMessageFooter(writer, result);
+  }
+
+
+
+  public void modifyRequest(final ASN1Writer writer, final int messageID,
+      final ModifyRequest request) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP MODIFY REQUEST(messageID=%d, request=%s)", messageID,
+          request));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeStartSequence(OP_TYPE_MODIFY_REQUEST);
+    writer.writeOctetString(request.getName().toString());
+
+    writer.writeStartSequence();
+    for (final Modification change : request.getModifications())
+    {
+      encodeChange(writer, change);
+    }
+    writer.writeEndSequence();
+
+    writer.writeEndSequence();
+    encodeMessageFooter(writer, request);
+  }
+
+
+
+  public void modifyResult(final ASN1Writer writer, final int messageID,
+      final Result result) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP MODIFY RESULT(messageID=%d, result=%s)", messageID,
+          result));
+    }
+    encodeMessageHeader(writer, messageID);
+    encodeResultHeader(writer, OP_TYPE_MODIFY_RESPONSE, result);
+    encodeResultFooter(writer);
+    encodeMessageFooter(writer, result);
+  }
+
+
+
+  public void searchRequest(final ASN1Writer writer, final int messageID,
+      final SearchRequest request) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP SEARCH REQUEST(messageID=%d, request=%s)", messageID,
+          request));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeStartSequence(OP_TYPE_SEARCH_REQUEST);
+    writer.writeOctetString(request.getName().toString());
+    writer.writeEnumerated(request.getScope().intValue());
+    writer.writeEnumerated(request.getDereferenceAliasesPolicy().intValue());
+    writer.writeInteger(request.getSizeLimit());
+    writer.writeInteger(request.getTimeLimit());
+    writer.writeBoolean(request.isTypesOnly());
+    LDAPUtils.encodeFilter(writer, request.getFilter());
+
+    writer.writeStartSequence();
+    for (final String attribute : request.getAttributes())
+    {
+      writer.writeOctetString(attribute);
+    }
+    writer.writeEndSequence();
+
+    writer.writeEndSequence();
+    encodeMessageFooter(writer, request);
+  }
+
+
+
+  public void searchResult(final ASN1Writer writer, final int messageID,
+      final Result result) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP SEARCH RESULT(messageID=%d, result=%s)", messageID,
+          result));
+    }
+    encodeMessageHeader(writer, messageID);
+    encodeResultHeader(writer, OP_TYPE_SEARCH_RESULT_DONE, result);
+    encodeResultFooter(writer);
+    encodeMessageFooter(writer, result);
+  }
+
+
+
+  public void searchResultEntry(final ASN1Writer writer, final int messageID,
+      final SearchResultEntry entry) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP SEARCH RESULT ENTRY(messageID=%d, entry=%s)", messageID,
+          entry));
+    }
+    encodeMessageHeader(writer, messageID);
+    encodeEntry(writer, entry);
+    encodeMessageFooter(writer, entry);
+  }
+
+
+
+  public void searchResultReference(final ASN1Writer writer,
+      final int messageID, final SearchResultReference reference)
+      throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP SEARCH RESULT REFERENCE(messageID=%d, reference=%s)",
+          messageID, reference));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeStartSequence(OP_TYPE_SEARCH_RESULT_REFERENCE);
+    for (final String url : reference.getURIs())
+    {
+      writer.writeOctetString(url);
+    }
+    writer.writeEndSequence();
+    encodeMessageFooter(writer, reference);
+  }
+
+
+
+  public void unbindRequest(final ASN1Writer writer, final int messageID,
+      final UnbindRequest request) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP UNBIND REQUEST(messageID=%d, request=%s)", messageID,
+          request));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeNull(OP_TYPE_UNBIND_REQUEST);
+    encodeMessageFooter(writer, request);
+  }
+
+
+
+  public void unrecognizedMessage(final ASN1Writer writer, final int messageID,
+      final byte messageTag, final ByteString messageBytes) throws IOException
+  {
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
+    {
+      StaticUtils.DEBUG_LOG.finer(String.format(
+          "ENCODE LDAP UNKNOWN MESSAGE(messageID=%d, messageTag=%s, "
+              + "messageBytes=%s)", messageID, StaticUtils
+              .byteToHex(messageTag), messageBytes.toString()));
+    }
+    encodeMessageHeader(writer, messageID);
+    writer.writeOctetString(messageTag, messageBytes);
+    writer.writeEndSequence();
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/SASLDecoderTransformer.java b/sdk/src/com/sun/opends/sdk/ldap/SASLDecoderTransformer.java
new file mode 100644
index 0000000..20e40cc
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/SASLDecoderTransformer.java
@@ -0,0 +1,109 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import org.opends.sdk.ConnectionSecurityLayer;
+import org.opends.sdk.ErrorResultException;
+
+import com.sun.grizzly.*;
+import com.sun.grizzly.attributes.AttributeStorage;
+import com.sun.grizzly.memory.MemoryManager;
+import com.sun.grizzly.memory.MemoryUtils;
+
+
+
+/**
+ * <tt>Transformer</tt>, which decodes SASL encrypted data, contained in the
+ * input Buffer, to the output Buffer.
+ */
+final class SASLDecoderTransformer extends AbstractTransformer<Buffer, Buffer>
+{
+  private static final int BUFFER_SIZE = 4096;
+  private final byte[] buffer = new byte[BUFFER_SIZE];
+  private final ConnectionSecurityLayer bindContext;
+
+  private final MemoryManager<Buffer> memoryManager;
+
+
+
+  @SuppressWarnings("unchecked")
+  public SASLDecoderTransformer(final ConnectionSecurityLayer bindContext)
+  {
+    this(bindContext, TransportFactory.getInstance().getDefaultMemoryManager());
+  }
+
+
+
+  public SASLDecoderTransformer(final ConnectionSecurityLayer bindContext,
+      final MemoryManager<Buffer> memoryManager)
+  {
+    this.bindContext = bindContext;
+    this.memoryManager = memoryManager;
+  }
+
+
+
+  public String getName()
+  {
+    return this.getClass().getName();
+  }
+
+
+
+  public boolean hasInputRemaining(final AttributeStorage storage,
+      final Buffer input)
+  {
+    return input != null && input.hasRemaining();
+  }
+
+
+
+  @Override
+  public TransformationResult<Buffer, Buffer> transformImpl(
+      final AttributeStorage storage, final Buffer input)
+      throws TransformationException
+  {
+
+    final int len = Math.min(buffer.length, input.remaining());
+    input.get(buffer, 0, len);
+
+    try
+    {
+      final Buffer output = MemoryUtils.wrap(memoryManager, bindContext.unwrap(
+          buffer, 0, len));
+      return TransformationResult.createCompletedResult(output, input);
+    }
+    catch (final ErrorResultException e)
+    {
+      return TransformationResult.createErrorResult(e.getResult()
+          .getResultCode().intValue(), e.getMessage());
+    }
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/SASLEncoderTransformer.java b/sdk/src/com/sun/opends/sdk/ldap/SASLEncoderTransformer.java
new file mode 100644
index 0000000..3e182f9
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/SASLEncoderTransformer.java
@@ -0,0 +1,109 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import org.opends.sdk.ConnectionSecurityLayer;
+import org.opends.sdk.ErrorResultException;
+
+import com.sun.grizzly.*;
+import com.sun.grizzly.attributes.AttributeStorage;
+import com.sun.grizzly.memory.MemoryManager;
+import com.sun.grizzly.memory.MemoryUtils;
+
+
+
+/**
+ * <tt>Transformer</tt>, which encodes SASL encrypted data, contained in the
+ * input Buffer, to the output Buffer.
+ */
+final class SASLEncoderTransformer extends AbstractTransformer<Buffer, Buffer>
+{
+  private static final int BUFFER_SIZE = 4096;
+  private final byte[] buffer = new byte[BUFFER_SIZE];
+  private final ConnectionSecurityLayer bindContext;
+
+  private final MemoryManager<Buffer> memoryManager;
+
+
+
+  @SuppressWarnings("unchecked")
+  public SASLEncoderTransformer(final ConnectionSecurityLayer bindContext)
+  {
+    this(bindContext, TransportFactory.getInstance().getDefaultMemoryManager());
+  }
+
+
+
+  public SASLEncoderTransformer(final ConnectionSecurityLayer bindContext,
+      final MemoryManager<Buffer> memoryManager)
+  {
+    this.bindContext = bindContext;
+    this.memoryManager = memoryManager;
+  }
+
+
+
+  public String getName()
+  {
+    return this.getClass().getName();
+  }
+
+
+
+  public boolean hasInputRemaining(final AttributeStorage storage,
+      final Buffer input)
+  {
+    return input != null && input.hasRemaining();
+  }
+
+
+
+  @Override
+  public TransformationResult<Buffer, Buffer> transformImpl(
+      final AttributeStorage storage, final Buffer input)
+      throws TransformationException
+  {
+
+    final int len = Math.min(buffer.length, input.remaining());
+    input.get(buffer, 0, len);
+
+    try
+    {
+      final Buffer output = MemoryUtils.wrap(memoryManager, bindContext.wrap(
+          buffer, 0, len));
+      return TransformationResult.createCompletedResult(output, input);
+    }
+    catch (final ErrorResultException e)
+    {
+      return TransformationResult.createErrorResult(e.getResult()
+          .getResultCode().intValue(), e.getMessage());
+    }
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/SASLFilter.java b/sdk/src/com/sun/opends/sdk/ldap/SASLFilter.java
index a4e1167..5676d44 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/SASLFilter.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/SASLFilter.java
@@ -29,326 +29,21 @@
 
 
 
-import java.io.IOException;
-
-import javax.security.sasl.SaslException;
-
-import org.opends.sdk.sasl.SASLContext;
+import org.opends.sdk.ConnectionSecurityLayer;
 
 import com.sun.grizzly.Buffer;
-import com.sun.grizzly.Connection;
-import com.sun.grizzly.Grizzly;
-import com.sun.grizzly.attributes.Attribute;
-import com.sun.grizzly.attributes.AttributeBuilder;
-import com.sun.grizzly.attributes.AttributeStorage;
-import com.sun.grizzly.filterchain.FilterAdapter;
-import com.sun.grizzly.filterchain.FilterChainContext;
-import com.sun.grizzly.filterchain.NextAction;
-import com.sun.grizzly.filterchain.StreamTransformerFilter;
-import com.sun.grizzly.streams.StreamReader;
-import com.sun.grizzly.streams.StreamWriter;
-import com.sun.grizzly.threadpool.WorkerThread;
+import com.sun.grizzly.filterchain.AbstractCodecFilter;
 
 
 
 /**
  * SASL filter adapter.
  */
-public final class SASLFilter extends FilterAdapter implements
-    StreamTransformerFilter
+final class SASLFilter extends AbstractCodecFilter<Buffer, Buffer>
 {
-  private static SASLFilter SINGLETON = new SASLFilter();
-
-  private static final String SASL_CONTEXT_ATTR_NAME = "SASLContextAttr";
-
-  private static final String SASL_INCOMING_BUFFER_NAME = "SASLIncomingBufferAttr";
-
-  private static final String SASL_OUTGOING_BUFFER_NAME = "SASLOutgoingBufferAttr";
-
-
-
-  public static SASLFilter getInstance(SASLContext saslContext,
-      Connection<?> connection)
+  public SASLFilter(final ConnectionSecurityLayer bindContext)
   {
-    SINGLETON.saslContextAttribute.set(connection, saslContext);
-    return SINGLETON;
-  }
-
-
-
-  private final Attribute<SASLContext> saslContextAttribute;
-
-  private final Attribute<byte[]> saslIncomingBufferAttribute;
-
-  private final Attribute<byte[]> saslOutgoingBufferAttribute;
-
-
-
-  private SASLFilter()
-  {
-    AttributeBuilder attrBuilder = getAttributeBuilder();
-    saslContextAttribute = attrBuilder
-        .createAttribute(SASL_CONTEXT_ATTR_NAME);
-    saslIncomingBufferAttribute = attrBuilder
-        .createAttribute(SASL_INCOMING_BUFFER_NAME);
-    saslOutgoingBufferAttribute = attrBuilder
-        .createAttribute(SASL_OUTGOING_BUFFER_NAME);
-  }
-
-
-
-  public StreamReader getStreamReader(StreamReader parentStreamReader)
-  {
-    return new SASLStreamReader(parentStreamReader, this);
-  }
-
-
-
-  public StreamWriter getStreamWriter(StreamWriter parentStreamWriter)
-  {
-    return new SASLStreamWriter(parentStreamWriter, this);
-  }
-
-
-
-  /**
-   * Wraps {@link com.sun.grizzly.filterchain.FilterChainContext}
-   * default {@link com.sun.grizzly.streams.StreamReader} and
-   * {@link com.sun.grizzly.streams.StreamWriter} with SASL aware ones.
-   */
-  @Override
-  public NextAction handleRead(FilterChainContext ctx,
-      NextAction nextAction) throws IOException
-  {
-    StreamReader parentReader = ctx.getStreamReader();
-    StreamWriter parentWriter = ctx.getStreamWriter();
-
-    SASLStreamReader saslStreamReader = new SASLStreamReader(
-        parentReader, this);
-    SASLStreamWriter saslStreamWriter = new SASLStreamWriter(
-        parentWriter, this);
-
-    ctx.setStreamReader(saslStreamReader);
-    ctx.setStreamWriter(saslStreamWriter);
-
-    saslStreamReader.pull();
-
-    if (!saslStreamReader.hasAvailableData())
-    {
-      nextAction = ctx.getStopAction();
-    }
-    return nextAction;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public NextAction handleWrite(FilterChainContext ctx,
-      NextAction nextAction) throws IOException
-  {
-    StreamWriter writer = ctx.getStreamWriter();
-
-    Object message = ctx.getMessage();
-
-    if (message instanceof Buffer<?>)
-    {
-      writer.writeBuffer((Buffer<?>) message);
-    }
-    writer.flush();
-
-    return nextAction;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public NextAction postClose(FilterChainContext ctx,
-      NextAction nextAction) throws IOException
-  {
-    saslContextAttribute.remove(ctx.getConnection());
-    saslIncomingBufferAttribute.remove(ctx.getConnection());
-    saslOutgoingBufferAttribute.remove(ctx.getConnection());
-    return nextAction;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public NextAction postRead(FilterChainContext ctx,
-      NextAction nextAction) throws IOException
-  {
-    SASLStreamReader saslStreamReader = (SASLStreamReader) ctx
-        .getStreamReader();
-    SASLStreamWriter saslStreamWriter = (SASLStreamWriter) ctx
-        .getStreamWriter();
-
-    ctx.setStreamReader(saslStreamReader.getUnderlyingReader());
-    ctx.setStreamWriter(saslStreamWriter.getUnderlyingWriter());
-
-    return nextAction;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public NextAction postWrite(FilterChainContext ctx,
-      NextAction nextAction) throws IOException
-  {
-    return nextAction;
-  }
-
-
-
-  public byte[] unwrap(Buffer<?> incoming, Connection<?> connection)
-      throws SaslException
-  {
-    SASLContext saslClient = saslContextAttribute.get(connection);
-    byte[] incomingBuffer = obtainIncomingBuffer(incoming.capacity(),
-        connection);
-    int remaining = incoming.remaining();
-
-    incoming.get(incomingBuffer, 0, remaining);
-    return saslClient.unwrap(incomingBuffer, 0, remaining);
-  }
-
-
-
-  public byte[] wrap(Buffer<?> outgoing, Connection<?> connection)
-      throws SaslException
-  {
-    SASLContext saslClient = saslContextAttribute.get(connection);
-    byte[] outgoingBuffer = obtainOutgoingBuffer(outgoing.capacity(),
-        connection);
-    int remaining = outgoing.remaining();
-
-    outgoing.get(outgoingBuffer, 0, remaining);
-    return saslClient.wrap(outgoingBuffer, 0, remaining);
-  }
-
-
-
-  protected final AttributeBuilder getAttributeBuilder()
-  {
-    return Grizzly.DEFAULT_ATTRIBUTE_BUILDER;
-  }
-
-
-
-  /**
-   * Obtaining incoming buffer
-   *
-   * @param size
-   *          The size of the buffer to allocate
-   * @param state
-   *          State storage
-   * @return incoming buffer
-   */
-  protected final byte[] obtainIncomingBuffer(int size,
-      AttributeStorage state)
-  {
-
-    // #1 - Try to get buffer from the attribute storage (connection)
-    byte[] buffer = saslIncomingBufferAttribute.get(state);
-
-    if ((buffer != null) && (buffer.length >= size))
-    {
-      return buffer;
-    }
-
-    // #2 - Try to get buffer from the WorkerThread (if possible)
-    Thread currentThread = Thread.currentThread();
-    boolean isWorkingThread = (currentThread instanceof WorkerThread);
-
-    if (isWorkingThread)
-    {
-      WorkerThread workerThread = (WorkerThread) currentThread;
-      buffer = saslIncomingBufferAttribute.get(workerThread);
-    }
-
-    if ((buffer != null) && (buffer.length >= size))
-    {
-      return buffer;
-    }
-
-    // #3 - Allocate new buffer
-    buffer = new byte[size];
-
-    if (isWorkingThread)
-    {
-      WorkerThread workerThread = (WorkerThread) currentThread;
-      saslIncomingBufferAttribute.set(workerThread, buffer);
-    }
-    else
-    {
-      saslIncomingBufferAttribute.set(state, buffer);
-    }
-
-    return buffer;
-  }
-
-
-
-  /**
-   * Obtaining outgoing buffer
-   *
-   * @param size
-   *          The size of the buffer to allocate
-   * @param state
-   *          State storage
-   * @return Outgoing buffer
-   */
-  protected final byte[] obtainOutgoingBuffer(int size,
-      AttributeStorage state)
-  {
-
-    // #1 - Try to get buffer from the attribute storage (connection)
-    byte[] buffer = saslOutgoingBufferAttribute.get(state);
-
-    if ((buffer != null) && (buffer.length >= size))
-    {
-      return buffer;
-    }
-
-    // #2 - Try to get buffer from the WorkerThread (if possible)
-    Thread currentThread = Thread.currentThread();
-    boolean isWorkingThread = (currentThread instanceof WorkerThread);
-
-    if (isWorkingThread)
-    {
-      WorkerThread workerThread = (WorkerThread) currentThread;
-      buffer = saslOutgoingBufferAttribute.get(workerThread);
-    }
-
-    if ((buffer != null) && (buffer.length >= size))
-    {
-      return buffer;
-    }
-
-    // #3 - Allocate new buffer
-    buffer = new byte[size];
-
-    if (isWorkingThread)
-    {
-      WorkerThread workerThread = (WorkerThread) currentThread;
-      saslOutgoingBufferAttribute.set(workerThread, buffer);
-    }
-    else
-    {
-      saslOutgoingBufferAttribute.set(state, buffer);
-    }
-
-    return buffer;
+    super(new SASLDecoderTransformer(bindContext), new SASLEncoderTransformer(
+        bindContext));
   }
 }
diff --git a/sdk/src/com/sun/opends/sdk/ldap/SASLStreamReader.java b/sdk/src/com/sun/opends/sdk/ldap/SASLStreamReader.java
deleted file mode 100644
index c7cac3a..0000000
--- a/sdk/src/com/sun/opends/sdk/ldap/SASLStreamReader.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package com.sun.opends.sdk.ldap;
-
-
-
-import java.io.IOException;
-
-import javax.security.sasl.SaslException;
-
-import com.sun.grizzly.Buffer;
-import com.sun.grizzly.streams.StreamReader;
-import com.sun.grizzly.streams.StreamReaderDecorator;
-
-
-
-/**
- * SASL stream reader.
- */
-public final class SASLStreamReader extends StreamReaderDecorator
-{
-  private final SASLFilter saslFilter;
-
-
-
-  public SASLStreamReader(StreamReader underlyingReader,
-      SASLFilter saslFilter)
-  {
-    super(underlyingReader);
-    this.saslFilter = saslFilter;
-  }
-
-
-
-  @Override
-  public boolean appendBuffer(Buffer buffer)
-  {
-    if (buffer == null)
-    {
-      return false;
-    }
-
-    byte[] appBuffer;
-    try
-    {
-      appBuffer = saslFilter.unwrap(buffer, getConnection());
-    }
-    catch (SaslException e)
-    {
-      throw new IllegalStateException(e);
-    }
-
-    if (appBuffer.length == 0)
-    {
-      return false;
-    }
-
-    Buffer newBuffer = newBuffer(appBuffer.length);
-    newBuffer.put(appBuffer);
-
-    if (super.appendBuffer(newBuffer))
-    {
-      buffer.dispose();
-      return true;
-    }
-
-    return false;
-  }
-
-
-
-  @Override
-  protected Buffer read0() throws IOException
-  {
-    return underlyingReader.readBuffer();
-  }
-
-
-
-  @Override
-  protected Buffer unwrap(Object data)
-  {
-    return (Buffer) data;
-  }
-
-
-
-  @Override
-  protected final Object wrap(Buffer buffer)
-  {
-    return buffer;
-  }
-}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/SASLStreamWriter.java b/sdk/src/com/sun/opends/sdk/ldap/SASLStreamWriter.java
deleted file mode 100644
index 50bab41..0000000
--- a/sdk/src/com/sun/opends/sdk/ldap/SASLStreamWriter.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package com.sun.opends.sdk.ldap;
-
-
-
-import java.io.IOException;
-import java.util.concurrent.Future;
-
-import com.sun.grizzly.Buffer;
-import com.sun.grizzly.CompletionHandler;
-import com.sun.grizzly.streams.StreamWriter;
-import com.sun.grizzly.streams.StreamWriterDecorator;
-
-
-
-/**
- * SASL stream writer.
- */
-@SuppressWarnings("unchecked")
-public final class SASLStreamWriter extends StreamWriterDecorator
-{
-  private final SASLFilter saslFilter;
-
-
-
-  public SASLStreamWriter(StreamWriter underlyingWriter,
-      SASLFilter saslFilter)
-  {
-    super(underlyingWriter);
-    this.saslFilter = saslFilter;
-  }
-
-
-
-  @Override
-  protected Future<Integer> flush0(Buffer buffer,
-      CompletionHandler<Integer> completionHandler) throws IOException
-  {
-    Future<Integer> lastWriterFuture = null;
-
-    if (buffer != null)
-    {
-      buffer.flip();
-
-      Buffer underlyingBuffer = underlyingWriter.getBuffer();
-      byte[] netBuffer = saslFilter.wrap(buffer, getConnection());
-      int remaining = netBuffer.length;
-      while (remaining > 0)
-      {
-        int writeSize = Math.min(remaining, underlyingBuffer
-            .remaining());
-        underlyingBuffer.put(netBuffer, netBuffer.length - remaining,
-            writeSize);
-        lastWriterFuture = underlyingWriter.flush();
-        remaining -= writeSize;
-      }
-      buffer.clear();
-    }
-
-    return lastWriterFuture;
-  }
-}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/TimeoutChecker.java b/sdk/src/com/sun/opends/sdk/ldap/TimeoutChecker.java
new file mode 100644
index 0000000..7139e0b
--- /dev/null
+++ b/sdk/src/com/sun/opends/sdk/ldap/TimeoutChecker.java
@@ -0,0 +1,157 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+
+import com.sun.grizzly.utils.LinkedTransferQueue;
+import com.sun.opends.sdk.util.StaticUtils;
+
+
+
+/**
+ * Checks connection for pending requests that have timed out.
+ */
+final class TimeoutChecker
+{
+  static final TimeoutChecker INSTANCE = new TimeoutChecker();
+
+  private final LinkedTransferQueue<LDAPConnection> connections;
+  private transient final ReentrantLock lock;
+  private transient final Condition available;
+
+
+
+  private TimeoutChecker()
+  {
+    this.connections = new LinkedTransferQueue<LDAPConnection>();
+    this.lock = new ReentrantLock();
+    this.available = lock.newCondition();
+
+    final Thread checkerThread = new Thread("Timeout Checker")
+    {
+      @Override
+      public void run()
+      {
+        StaticUtils.DEBUG_LOG.fine("Timeout Checker Starting");
+        final ReentrantLock lock = TimeoutChecker.this.lock;
+        lock.lock();
+        try
+        {
+          while (true)
+          {
+            final long currentTime = System.currentTimeMillis();
+            long delay = 0;
+
+            for (final LDAPConnection connection : connections)
+            {
+              StaticUtils.DEBUG_LOG.finer("Checking connection " + connection
+                  + " delay = " + delay);
+              final long newDelay = connection
+                  .cancelExpiredRequests(currentTime);
+              if (newDelay > 0)
+              {
+                if (delay > 0)
+                {
+                  delay = Math.min(newDelay, delay);
+                }
+                else
+                {
+                  delay = newDelay;
+                }
+              }
+            }
+
+            try
+            {
+              if (delay <= 0)
+              {
+                StaticUtils.DEBUG_LOG.finer("There are no connections with "
+                    + "timeout specified. Sleeping");
+                available.await();
+              }
+              else
+              {
+                StaticUtils.DEBUG_LOG.finer("Sleeping for " + delay + "ms");
+                available.await(delay, TimeUnit.MILLISECONDS);
+              }
+            }
+            catch (final InterruptedException e)
+            {
+              // Just go around again.
+            }
+          }
+        }
+        finally
+        {
+          lock.unlock();
+        }
+      }
+    };
+
+    checkerThread.setDaemon(true);
+    checkerThread.start();
+  }
+
+
+
+  void addConnection(final LDAPConnection connection)
+  {
+    final ReentrantLock lock = this.lock;
+    lock.lock();
+    try
+    {
+      connections.add(connection);
+      available.signalAll();
+    }
+    finally
+    {
+      lock.unlock();
+    }
+  }
+
+
+
+  void removeConnection(final LDAPConnection connection)
+  {
+    final ReentrantLock lock = this.lock;
+    lock.lock();
+    try
+    {
+      connections.remove(connection);
+    }
+    finally
+    {
+      lock.unlock();
+    }
+  }
+}
diff --git a/sdk/src/com/sun/opends/sdk/ldap/UnexpectedRequestException.java b/sdk/src/com/sun/opends/sdk/ldap/UnexpectedRequestException.java
index 9a855dc..0ba8a17 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/UnexpectedRequestException.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/UnexpectedRequestException.java
@@ -36,19 +36,18 @@
 
 
 
-
 /**
  * Thrown when an expected LDAP request is received.
  */
 @SuppressWarnings("serial")
-public final class UnexpectedRequestException extends IOException
+final class UnexpectedRequestException extends IOException
 {
   private final int messageID;
   private final Request request;
 
 
 
-  public UnexpectedRequestException(int messageID, Request request)
+  public UnexpectedRequestException(final int messageID, final Request request)
   {
     super(LocalizableMessage.raw("Unexpected LDAP request: id=%d, message=%s",
         messageID, request).toString());
diff --git a/sdk/src/com/sun/opends/sdk/ldap/UnexpectedResponseException.java b/sdk/src/com/sun/opends/sdk/ldap/UnexpectedResponseException.java
index 6336301..8ee00f4 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/UnexpectedResponseException.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/UnexpectedResponseException.java
@@ -36,19 +36,19 @@
 
 
 
-
 /**
  * Thrown when an unexpected LDAP response is received.
  */
 @SuppressWarnings("serial")
-public final class UnexpectedResponseException extends IOException
+final class UnexpectedResponseException extends IOException
 {
   private final int messageID;
   private final Response response;
 
 
 
-  public UnexpectedResponseException(int messageID, Response response)
+  public UnexpectedResponseException(final int messageID,
+      final Response response)
   {
     super(LocalizableMessage.raw("Unexpected LDAP response: id=%d, message=%s",
         messageID, response).toString());
diff --git a/sdk/src/com/sun/opends/sdk/ldap/UnsupportedMessageException.java b/sdk/src/com/sun/opends/sdk/ldap/UnsupportedMessageException.java
index aebac22..91c301a 100644
--- a/sdk/src/com/sun/opends/sdk/ldap/UnsupportedMessageException.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/UnsupportedMessageException.java
@@ -39,7 +39,7 @@
  * Thrown when an unsupported LDAP message is received.
  */
 @SuppressWarnings("serial")
-public final class UnsupportedMessageException extends IOException
+final class UnsupportedMessageException extends IOException
 {
   private final int id;
   private final byte tag;
@@ -47,12 +47,12 @@
 
 
 
-  public UnsupportedMessageException(int id, byte tag,
-      ByteString content)
+  public UnsupportedMessageException(final int id, final byte tag,
+      final ByteString content)
   {
-    super(org.opends.sdk.LocalizableMessage.raw(
-        "Unsupported LDAP message: id=%d, tag=%d, content=%s", id, tag,
-        content).toString());
+    super(org.opends.sdk.LocalizableMessage
+        .raw("Unsupported LDAP message: id=%d, tag=%d, content=%s", id, tag,
+            content).toString());
     this.id = id;
     this.tag = tag;
     this.content = content;
diff --git a/sdk/src/org/opends/sdk/sasl/package-info.java b/sdk/src/com/sun/opends/sdk/ldap/package-info.java
old mode 100755
new mode 100644
similarity index 86%
copy from sdk/src/org/opends/sdk/sasl/package-info.java
copy to sdk/src/com/sun/opends/sdk/ldap/package-info.java
index 6683fa9..a967a6b
--- a/sdk/src/org/opends/sdk/sasl/package-info.java
+++ b/sdk/src/com/sun/opends/sdk/ldap/package-info.java
@@ -22,10 +22,13 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
 /**
- * Classes and interfaces for common LDAP SASL Bind requests.
+ * Classes implementing LDAP protocol.
  */
-package org.opends.sdk.sasl;
+package com.sun.opends.sdk.ldap;
+
+
+
diff --git a/sdk/src/com/sun/opends/sdk/messages/messages.properties b/sdk/src/com/sun/opends/sdk/messages/messages.properties
index c968558..7b8f5c4 100755
--- a/sdk/src/com/sun/opends/sdk/messages/messages.properties
+++ b/sdk/src/com/sun/opends/sdk/messages/messages.properties
@@ -2919,6 +2919,9 @@
  component to separate the scheme from the rest of the URL
 SEVERE_ERR_LDAPURL_NO_SCHEME=The provided string "%s" cannot be decoded \
  as an LDAP URL because it does not contain a protocol scheme
+SEVERE_ERR_LDAPURL_BAD_SCHEME=The provided string "%s" cannot be decoded \
+ as an LDAP URL because the protocol scheme "%s" is invalid. It should be
+ either "ldap" or "ldaps"
 SEVERE_ERR_LDAPURL_NO_HOST=The provided string "%s" cannot be decoded as \
  an LDAP URL because it does not contain a host before the colon to specify \
  the port number
@@ -2931,6 +2934,14 @@
 SEVERE_ERR_LDAPURL_INVALID_PORT=The provided string "%s" cannot be \
  decoded as an LDAP URL because the provided port number %d is not within the \
  valid range between 1 and 65535
+SEVERE_ERR_LDAPURL_BAD_PORT=The provided port number %d is not within the \
+ valid range between 1 and 65535
+SEVERE_ERR_LDAPURL_INVALID_DN=The provided string "%s" cannot be \
+ decoded as an LDAP URL because the provided distinguished name could \
+ not be parsed: %s
+SEVERE_ERR_LDAPURL_INVALID_FILTER=The provided string "%s" cannot be \
+ decoded as an LDAP URL because the provided filter could \
+ not be parsed: %s
 SEVERE_ERR_LDAPURL_INVALID_SCOPE_STRING=The provided string "%s" cannot \
  be decoded as an LDAP URL because the scope string %s was not one of the \
  allowed values of base, one, sub, or subordinate
@@ -5692,3 +5703,134 @@
 INFO_INSTALLDS_DO_NOT_ENABLE_WINDOWS_SERVICE=Do not enable the server to \
  run as a Windows Service
 INFO_ERROR_EMPTY_RESPONSE=ERROR: a response must be provided in order to continue
+SEVERE_ERR_ACCTUSABLEREQ_CONTROL_BAD_OID=Cannot decode the provided \
+ control as an account availability request control because it contained \
+ the OID '%s', when '%s' was expected
+SEVERE_ERR_ACCTUSABLERES_CONTROL_BAD_OID=Cannot decode the provided \
+ control as an account availability response control because it contained \
+ the OID '%s', when '%s' was expected
+SEVERE_ERR_LDAPASSERT_CONTROL_BAD_OID=Cannot decode the provided \
+ control as an assertion control because it contained \
+ the OID '%s', when '%s' was expected
+SEVERE_ERR_AUTHZIDREQ_CONTROL_BAD_OID=Cannot decode the provided \
+ control as an authorization identity request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_AUTHZIDRESP_CONTROL_BAD_OID=Cannot decode the provided \
+ control as an authorization identity response control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_ECN_CONTROL_BAD_OID=Cannot decode the provided \
+ control as an entry change notification response control because it \
+ contained the OID '%s', when '%s' was expected
+MILD_ERR_ECN_INVALID_PREVIOUS_DN=Cannot decode the provided entry change \
+ notification control because it contains an invalid previous DN: %s
+SEVERE_ERR_GETEFFECTIVERIGHTS_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a get effective rights request control because it \
+ contained the OID '%s', when '%s' was expected
+MILD_ERR_GETEFFECTIVERIGHTS_INVALID_AUTHZIDDN=Cannot decode the provided \
+ get effective rights request control because it contains an invalid \
+ authorization ID distinguished name: %s
+MILD_ERR_GETEFFECTIVERIGHTS_UNKNOWN_ATTRIBUTE=Cannot decode the provided \
+ get effective rights request control because it contained an unrecognized \
+ attribute type: %s
+SEVERE_ERR_MATCHEDVALUES_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a matched values request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_LDAP_PAGED_RESULTS_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a simple paged results control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_SUBTREE_DELETE_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a tree delete request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PWEXPIRED_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a Netscape password expired response control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PWEXPIRING_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a Netscape password expiring response control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PSEARCH_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a persistent search request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PSEARCH_BAD_CHANGE_TYPES=Cannot decode the provided \
+ control as a persistent search request control because it an \
+ invalid changeTypes field '%d', when a value between 0 and 15 was expected
+SEVERE_ERR_ECN_BAD_CHANGE_TYPE=Cannot decode the provided \
+ control as a entry change notification control because it an \
+ invalid changeTypes field '%d', when a value of 1, 2, 4, or 8 was expected
+SEVERE_ERR_POSTREAD_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a post-read control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PREREAD_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a pre-read control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PROXYAUTH1_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a proxy authorization v1 control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PROXYAUTH1_INVALID_AUTHZIDDN=Cannot decode the provided \
+ proxy authorization v1 control because it contains an invalid \
+ authorization distinguished name: %s
+SEVERE_ERR_PROXYAUTH2_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a proxy authorization v2 control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PROXYAUTH2_INVALID_AUTHZIDDN=Cannot decode the provided \
+ proxy authorization v2 control because it contains an invalid \
+ authorization distinguished name: %s
+SEVERE_ERR_PROXYAUTH2_INVALID_AUTHZID_TYPE=Cannot decode the provided \
+ proxy authorization v2 control because the control value '%s' does not \
+ begin with a valid authorization ID type 'dn:' or 'u:'
+SEVERE_ERR_SORT_KEY_DEFAULT_MRULE_NOT_FOUND=The sort key '%s' could not be \
+ decoded because the attribute description '%s' does not have a default \
+ ordering matching rule
+SEVERE_ERR_SORT_KEY_MRULE_NOT_FOUND=The sort key '%s' could not be decoded \
+ because the ordering matching rule '%s' was not found in the schema
+SEVERE_ERR_SORT_KEY_NO_ATTR_NAME=The sort key '%s' could not be decoded \
+ because it did not contain an attribute description
+SEVERE_ERR_SORT_KEY_NO_MATCHING_RULE=The sort key '%s' could not be decoded \
+ because it contained a colon but no ordering matching rule name
+SEVERE_ERR_SORT_KEY_NO_SORT_KEYS=The list of sort keys '%s' could not be \
+ decoded because it did not contain any sort keys
+SEVERE_ERR_SORTREQ_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a server side sort request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_SORTRES_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a server side sort response control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_VLVREQ_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a virtual list view request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_VLVRES_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a virtual list view response control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PWPOLICYREQ_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a password policy request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PWPOLICYRES_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a password policy response control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_MANAGEDSAIT_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a ManageDsaIT request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_MANAGEDSAIT_INVALID_CONTROL_VALUE=Cannot decode the provided \
+ ManageDsaIT control because it contains a value
+SEVERE_ERR_SUBENTRIES_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a sub-entries request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_SUBENTRIES_INVALID_CONTROL_VALUE=Cannot decode the provided \
+ sub-entries control because it contains a value
+SEVERE_ERR_DECODE_CONTROL_FAILURE=# %s
+SEVERE_ERR_WHOAMI_INVALID_AUTHZID_TYPE=The provided authorization ID '%s' \
+ does not begin with a valid authorization ID type 'dn:' or 'u:'
+SEVERE_ERR_PERMISSIVE_MODIFY_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a permissive modify request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_PERMISSIVE_MODIFY_INVALID_CONTROL_VALUE=Cannot decode the provided \
+ permissive modify control because it contains a value
+SEVERE_ERR_REAL_ATTRS_ONLY_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a real attributes only request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_REAL_ATTRS_ONLY_INVALID_CONTROL_VALUE=Cannot decode the provided \
+ real attributes only control because it contains a value
+SEVERE_ERR_VIRTUAL_ATTRS_ONLY_CONTROL_BAD_OID=Cannot decode the provided \
+ control as a virtual attributes only request control because it \
+ contained the OID '%s', when '%s' was expected
+SEVERE_ERR_VIRTUAL_ATTRS_ONLY_INVALID_CONTROL_VALUE=Cannot decode the provided \
+ virtual attributes only control because it contains a value
diff --git a/sdk/src/com/sun/opends/sdk/tools/ApplicationKeyManager.java b/sdk/src/com/sun/opends/sdk/tools/ApplicationKeyManager.java
index 1b76900..ca919e9 100755
--- a/sdk/src/com/sun/opends/sdk/tools/ApplicationKeyManager.java
+++ b/sdk/src/com/sun/opends/sdk/tools/ApplicationKeyManager.java
@@ -47,14 +47,13 @@
 
 /**
  * This class is in charge of checking whether the certificates that are
- * presented are trusted or not. This implementation tries to check also
- * that the subject DN of the certificate corresponds to the host passed
- * using the setHostName method.
+ * presented are trusted or not. This implementation tries to check also that
+ * the subject DN of the certificate corresponds to the host passed using the
+ * setHostName method.
  *<p>
- * The constructor tries to use a default TrustManager from the system
- * and if it cannot be retrieved this class will only accept the
- * certificates explicitly accepted by the user (and specified by
- * calling acceptCertificate).
+ * The constructor tries to use a default TrustManager from the system and if it
+ * cannot be retrieved this class will only accept the certificates explicitly
+ * accepted by the user (and specified by calling acceptCertificate).
  *<p>
  * NOTE: this class is not aimed to be used when we have connections in
  * parallel.
@@ -79,7 +78,7 @@
    * @param password
    *          The keystore password to use for this keymanager.
    */
-  ApplicationKeyManager(KeyStore keystore, char[] password)
+  ApplicationKeyManager(final KeyStore keystore, final char[] password)
   {
     KeyManagerFactory kmf = null;
     String userSpecifiedAlgo = System
@@ -90,22 +89,26 @@
     // Handle IBM specific cases if the user did not specify a algorithm
     // and/or provider.
     if (userSpecifiedAlgo == null && Platform.isVendor("IBM"))
+    {
       userSpecifiedAlgo = "IbmX509";
+    }
     if (userSpecifiedProvider == null && Platform.isVendor("IBM"))
+    {
       userSpecifiedProvider = "IBMJSSE2";
+    }
 
     // Have some fallbacks to choose the provider and algorith of the
     // key manager. First see if the user wanted to use something
     // specific, then try with the SunJSSE provider and SunX509
     // algorithm. Finally, fallback to the default algorithm of the JVM.
-    String[] preferredProvider = { userSpecifiedProvider, "SunJSSE",
+    final String[] preferredProvider = { userSpecifiedProvider, "SunJSSE",
         null, null };
-    String[] preferredAlgo = { userSpecifiedAlgo, "SunX509", "SunX509",
+    final String[] preferredAlgo = { userSpecifiedAlgo, "SunX509", "SunX509",
         TrustManagerFactory.getDefaultAlgorithm() };
     for (int i = 0; i < preferredProvider.length && keyManager == null; i++)
     {
-      String provider = preferredProvider[i];
-      String algo = preferredAlgo[i];
+      final String provider = preferredProvider[i];
+      final String algo = preferredAlgo[i];
       if (algo == null)
       {
         continue;
@@ -121,40 +124,39 @@
           kmf = KeyManagerFactory.getInstance(algo);
         }
         kmf.init(keystore, password);
-        KeyManager kms[] = kmf.getKeyManagers();
+        final KeyManager kms[] = kmf.getKeyManagers();
         /*
-         * Iterate over the returned keymanagers, look for an instance
-         * of X509KeyManager. If found, use that as our "default" key
-         * manager.
+         * Iterate over the returned keymanagers, look for an instance of
+         * X509KeyManager. If found, use that as our "default" key manager.
          */
-        for (int j = 0; j < kms.length; j++)
+        for (final KeyManager km : kms)
         {
           if (kms[i] instanceof X509KeyManager)
           {
-            keyManager = (X509KeyManager) kms[j];
+            keyManager = (X509KeyManager) km;
             break;
           }
         }
       }
-      catch (NoSuchAlgorithmException e)
+      catch (final NoSuchAlgorithmException e)
       {
         // Nothing to do. Maybe we should avoid this and be strict, but
         // we are in a best effor mode.
         LOG.log(Level.WARNING, "Error with the algorithm", e);
       }
-      catch (KeyStoreException e)
+      catch (final KeyStoreException e)
       {
         // Nothing to do. Maybe we should avoid this and be strict, but
         // we are in a best effor mode..
         LOG.log(Level.WARNING, "Error with the keystore", e);
       }
-      catch (UnrecoverableKeyException e)
+      catch (final UnrecoverableKeyException e)
       {
         // Nothing to do. Maybe we should avoid this and be strict, but
         // we are in a best effor mode.
         LOG.log(Level.WARNING, "Error with the key", e);
       }
-      catch (NoSuchProviderException e)
+      catch (final NoSuchProviderException e)
       {
         // Nothing to do. Maybe we should avoid this and be strict, but
         // we are in a best effor mode.
@@ -166,25 +168,25 @@
 
 
   /**
-   * Choose an alias to authenticate the client side of a secure socket
-   * given the public key type and the list of certificate issuer
-   * authorities recognized by the peer (if any).
+   * Choose an alias to authenticate the client side of a secure socket given
+   * the public key type and the list of certificate issuer authorities
+   * recognized by the peer (if any).
    *
    * @param keyType
-   *          the key algorithm type name(s), ordered with the
-   *          most-preferred key type first.
+   *          the key algorithm type name(s), ordered with the most-preferred
+   *          key type first.
    * @param issuers
-   *          the list of acceptable CA issuer subject names or null if
-   *          it does not matter which issuers are used.
+   *          the list of acceptable CA issuer subject names or null if it does
+   *          not matter which issuers are used.
    * @param socket
-   *          the socket to be used for this connection. This parameter
-   *          can be null, in which case this method will return the
-   *          most generic alias to use.
+   *          the socket to be used for this connection. This parameter can be
+   *          null, in which case this method will return the most generic alias
+   *          to use.
    * @return the alias name for the desired key, or null if there are no
    *         matches.
    */
-  public String chooseClientAlias(String[] keyType,
-      Principal[] issuers, Socket socket)
+  public String chooseClientAlias(final String[] keyType,
+      final Principal[] issuers, final Socket socket)
   {
     if (keyManager != null)
     {
@@ -199,25 +201,25 @@
 
 
   /**
-   * Choose an alias to authenticate the client side of a secure socket
-   * given the public key type and the list of certificate issuer
-   * authorities recognized by the peer (if any).
+   * Choose an alias to authenticate the client side of a secure socket given
+   * the public key type and the list of certificate issuer authorities
+   * recognized by the peer (if any).
    *
    * @param keyType
-   *          the key algorithm type name(s), ordered with the
-   *          most-preferred key type first.
+   *          the key algorithm type name(s), ordered with the most-preferred
+   *          key type first.
    * @param issuers
-   *          the list of acceptable CA issuer subject names or null if
-   *          it does not matter which issuers are used.
+   *          the list of acceptable CA issuer subject names or null if it does
+   *          not matter which issuers are used.
    * @param socket
-   *          the socket to be used for this connection. This parameter
-   *          can be null, in which case this method will return the
-   *          most generic alias to use.
+   *          the socket to be used for this connection. This parameter can be
+   *          null, in which case this method will return the most generic alias
+   *          to use.
    * @return the alias name for the desired key, or null if there are no
    *         matches.
    */
-  public String chooseServerAlias(String keyType, Principal[] issuers,
-      Socket socket)
+  public String chooseServerAlias(final String keyType,
+      final Principal[] issuers, final Socket socket)
   {
     if (keyManager != null)
     {
@@ -236,11 +238,11 @@
    *
    * @param alias
    *          the alias name
-   * @return the certificate chain (ordered with the user's certificate
-   *         first and the root certificate authority last), or null if
-   *         the alias can't be found.
+   * @return the certificate chain (ordered with the user's certificate first
+   *         and the root certificate authority last), or null if the alias
+   *         can't be found.
    */
-  public X509Certificate[] getCertificateChain(String alias)
+  public X509Certificate[] getCertificateChain(final String alias)
   {
     if (keyManager != null)
     {
@@ -255,19 +257,20 @@
 
 
   /**
-   * Get the matching aliases for authenticating the server side of a
-   * secure socket given the public key type and the list of certificate
-   * issuer authorities recognized by the peer (if any).
+   * Get the matching aliases for authenticating the server side of a secure
+   * socket given the public key type and the list of certificate issuer
+   * authorities recognized by the peer (if any).
    *
    * @param keyType
    *          the key algorithm type name
    * @param issuers
-   *          the list of acceptable CA issuer subject names or null if
-   *          it does not matter which issuers are used.
-   * @return an array of the matching alias names, or null if there were
-   *         no matches.
+   *          the list of acceptable CA issuer subject names or null if it does
+   *          not matter which issuers are used.
+   * @return an array of the matching alias names, or null if there were no
+   *         matches.
    */
-  public String[] getClientAliases(String keyType, Principal[] issuers)
+  public String[] getClientAliases(final String keyType,
+      final Principal[] issuers)
   {
     if (keyManager != null)
     {
@@ -288,7 +291,7 @@
    *          the alias name
    * @return the requested key, or null if the alias can't be found.
    */
-  public PrivateKey getPrivateKey(String alias)
+  public PrivateKey getPrivateKey(final String alias)
   {
     if (keyManager != null)
     {
@@ -303,19 +306,20 @@
 
 
   /**
-   * Get the matching aliases for authenticating the server side of a
-   * secure socket given the public key type and the list of certificate
-   * issuer authorities recognized by the peer (if any).
+   * Get the matching aliases for authenticating the server side of a secure
+   * socket given the public key type and the list of certificate issuer
+   * authorities recognized by the peer (if any).
    *
    * @param keyType
    *          the key algorithm type name
    * @param issuers
-   *          the list of acceptable CA issuer subject names or null if
-   *          it does not matter which issuers are used.
-   * @return an array of the matching alias names, or null if there were
-   *         no matches.
+   *          the list of acceptable CA issuer subject names or null if it does
+   *          not matter which issuers are used.
+   * @return an array of the matching alias names, or null if there were no
+   *         matches.
    */
-  public String[] getServerAliases(String keyType, Principal[] issuers)
+  public String[] getServerAliases(final String keyType,
+      final Principal[] issuers)
   {
     if (keyManager != null)
     {
diff --git a/sdk/src/com/sun/opends/sdk/tools/Argument.java b/sdk/src/com/sun/opends/sdk/tools/Argument.java
index e501d99..a87c623 100644
--- a/sdk/src/com/sun/opends/sdk/tools/Argument.java
+++ b/sdk/src/com/sun/opends/sdk/tools/Argument.java
@@ -29,7 +29,7 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
 
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -39,11 +39,10 @@
 
 
 
-
 /**
- * This class defines a generic argument that may be used in the
- * argument list for an application. This is an abstract class that must
- * be subclassed in order to provide specific functionality.
+ * This class defines a generic argument that may be used in the argument list
+ * for an application. This is an abstract class that must be subclassed in
+ * order to provide specific functionality.
  */
 abstract class Argument
 {
@@ -67,22 +66,22 @@
   private boolean needsValue;
 
   // The single-character identifier for this argument.
-  private Character shortIdentifier;
+  private final Character shortIdentifier;
 
   // The unique ID of the description for this argument.
-  private LocalizableMessage description;
+  private final LocalizableMessage description;
 
   // The set of values for this argument.
-  private LinkedList<String> values;
+  private final LinkedList<String> values;
 
   // The default value for the argument if none other is provided.
   private String defaultValue;
 
   // The long identifier for this argument.
-  private String longIdentifier;
+  private final String longIdentifier;
 
   // The generic name that will be used to refer to this argument.
-  private String name;
+  private final String name;
 
   // The name of the property that can be used to set the default value.
   private String propertyName;
@@ -103,45 +102,44 @@
    * Creates a new argument with the provided information.
    *
    * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
+   *          The generic name that should be used to refer to this argument.
    * @param shortIdentifier
    *          The single-character identifier for this argument, or
    *          <CODE>null</CODE> if there is none.
    * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
    * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
+   *          Indicates whether this argument must be specified on the command
+   *          line.
    * @param isMultiValued
-   *          Indicates whether this argument may be specified more than
-   *          once to provide multiple values.
+   *          Indicates whether this argument may be specified more than once to
+   *          provide multiple values.
    * @param needsValue
    *          Indicates whether this argument requires a value.
    * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
    * @param defaultValue
-   *          The default value that should be used for this argument if
-   *          none is provided in a properties file or on the command
-   *          line. This may be <CODE>null</CODE> if there is no generic
-   *          default.
+   *          The default value that should be used for this argument if none is
+   *          provided in a properties file or on the command line. This may be
+   *          <CODE>null</CODE> if there is no generic default.
    * @param propertyName
-   *          The name of the property in a property file that may be
-   *          used to override the default value but will be overridden
-   *          by a command-line argument.
+   *          The name of the property in a property file that may be used to
+   *          override the default value but will be overridden by a
+   *          command-line argument.
    * @param description
    *          LocalizableMessage for the description of this argument.
    * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
    */
-  protected Argument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean isMultiValued,
-      boolean needsValue, LocalizableMessage valuePlaceholder,
-      String defaultValue, String propertyName, LocalizableMessage description)
+  protected Argument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final boolean isMultiValued, final boolean needsValue,
+      final LocalizableMessage valuePlaceholder, final String defaultValue,
+      final String propertyName, final LocalizableMessage description)
       throws ArgumentException
   {
     this.name = name;
@@ -158,13 +156,13 @@
 
     if ((shortIdentifier == null) && (longIdentifier == null))
     {
-      LocalizableMessage message = ERR_ARG_NO_IDENTIFIER.get(name);
+      final LocalizableMessage message = ERR_ARG_NO_IDENTIFIER.get(name);
       throw new ArgumentException(message);
     }
 
     if (needsValue && (valuePlaceholder == null))
     {
-      LocalizableMessage message = ERR_ARG_NO_VALUE_PLACEHOLDER.get(name);
+      final LocalizableMessage message = ERR_ARG_NO_VALUE_PLACEHOLDER.get(name);
       throw new ArgumentException(message);
     }
 
@@ -176,241 +174,87 @@
 
 
   /**
-   * Retrieves the generic name that will be used to refer to this
-   * argument.
+   * Adds a value to the set of values for this argument. This should only be
+   * called if the value is allowed by the <CODE>valueIsAcceptable</CODE>
+   * method.
    *
-   * @return The generic name that will be used to refer to this
-   *         argument.
+   * @param valueString
+   *          The string representation of the value to add to this argument.
    */
-  public String getName()
+  public void addValue(final String valueString)
   {
-    return name;
+    values.add(valueString);
   }
 
 
 
   /**
-   * Retrieves the single-character identifier that may be used to
-   * specify the value of this argument.
-   *
-   * @return The single-character identifier that may be used to specify
-   *         the value of this argument, or <CODE>null</CODE> if there
-   *         is none.
+   * Clears the set of values assigned to this argument.
    */
-  public Character getShortIdentifier()
+  public void clearValues()
   {
-    return shortIdentifier;
+    values.clear();
   }
 
 
 
   /**
-   * Retrieves the long (multi-character) identifier that may be used to
-   * specify the value of this argument.
+   * Retrieves the value of this argument as a <CODE>Boolean</CODE>.
    *
-   * @return The long (multi-character) identifier that may be used to
-   *         specify the value of this argument.
+   * @return The value of this argument as a <CODE>Boolean</CODE>.
+   * @throws ArgumentException
+   *           If this argument cannot be interpreted as a Boolean value.
    */
-  public String getLongIdentifier()
+  public boolean getBooleanValue() throws ArgumentException
   {
-    return longIdentifier;
+    if (values.isEmpty())
+    {
+      final LocalizableMessage message = ERR_ARG_NO_BOOLEAN_VALUE.get(name);
+      throw new ArgumentException(message);
+    }
+
+    final Iterator<String> iterator = values.iterator();
+    final String valueString = toLowerCase(iterator.next());
+
+    boolean booleanValue;
+    if (valueString.equals("true") || valueString.equals("yes")
+        || valueString.equals("on") || valueString.equals("1"))
+    {
+      booleanValue = true;
+    }
+    else if (valueString.equals("false") || valueString.equals("no")
+        || valueString.equals("off") || valueString.equals("0"))
+    {
+      booleanValue = false;
+    }
+    else
+    {
+      final LocalizableMessage message = ERR_ARG_CANNOT_DECODE_AS_BOOLEAN.get(
+          valueString, name);
+      throw new ArgumentException(message);
+    }
+
+    if (iterator.hasNext())
+    {
+      final LocalizableMessage message = ERR_ARG_BOOLEAN_MULTIPLE_VALUES
+          .get(name);
+      throw new ArgumentException(message);
+    }
+    else
+    {
+      return booleanValue;
+    }
   }
 
 
 
   /**
-   * Indicates whether this argument is required to have at least one
-   * value.
+   * Retrieves the default value that will be used for this argument if it is
+   * not specified on the command line and it is not set from a properties file.
    *
-   * @return <CODE>true</CODE> if this argument is required to have at
-   *         least one value, or <CODE>false</CODE> if it does not need
-   *         to have a value.
-   */
-  public boolean isRequired()
-  {
-    return isRequired;
-  }
-
-
-
-  /**
-   * Specifies whether this argument is required to have at least one
-   * value.
-   *
-   * @param isRequired
-   *          Indicates whether this argument is required to have at
-   *          least one value.
-   */
-  public void setRequired(boolean isRequired)
-  {
-    this.isRequired = isRequired;
-  }
-
-
-
-  /**
-   * Indicates whether this argument is present in the parsed set of
-   * command-line arguments.
-   *
-   * @return <CODE>true</CODE> if this argument is present in the parsed
-   *         set of command-line arguments, or <CODE>false</CODE> if
-   *         not.
-   */
-  public boolean isPresent()
-  {
-    return isPresent;
-  }
-
-
-
-  /**
-   * Specifies whether this argument is present in the parsed set of
-   * command-line arguments.
-   *
-   * @param isPresent
-   *          Indicates whether this argument is present in the set of
-   *          command-line arguments.
-   */
-  public void setPresent(boolean isPresent)
-  {
-    this.isPresent = isPresent;
-  }
-
-
-
-  /**
-   * Indicates whether this argument should be hidden from the usage
-   * information.
-   *
-   * @return <CODE>true</CODE> if this argument should be hidden from
-   *         the usage information, or <CODE>false</CODE> if not.
-   */
-  public boolean isHidden()
-  {
-    return isHidden;
-  }
-
-
-
-  /**
-   * Specifies whether this argument should be hidden from the usage
-   * information.
-   *
-   * @param isHidden
-   *          Indicates whether this argument should be hidden from the
-   *          usage information.
-   */
-  public void setHidden(boolean isHidden)
-  {
-    this.isHidden = isHidden;
-  }
-
-
-
-  /**
-   * Indicates whether this argument may be provided more than once on
-   * the command line to specify multiple values.
-   *
-   * @return <CODE>true</CODE> if this argument may be provided more
-   *         than once on the command line to specify multiple values,
-   *         or <CODE>false</CODE> if it may have at most one value.
-   */
-  public boolean isMultiValued()
-  {
-    return isMultiValued;
-  }
-
-
-
-  /**
-   * Specifies whether this argument may be provided more than once on
-   * the command line to specify multiple values.
-   *
-   * @param isMultiValued
-   *          Indicates whether this argument may be provided more than
-   *          once on the command line to specify multiple values.
-   */
-  public void setMultiValued(boolean isMultiValued)
-  {
-    this.isMultiValued = isMultiValued;
-  }
-
-
-
-  /**
-   * Indicates whether a value must be provided with this argument if it
-   * is present.
-   *
-   * @return <CODE>true</CODE> if a value must be provided with the
-   *         argument if it is present, or <CODE>false</CODE> if the
-   *         argument does not take a value and the presence of the
-   *         argument identifier itself is sufficient to convey the
-   *         necessary information.
-   */
-  public boolean needsValue()
-  {
-    return needsValue;
-  }
-
-
-
-  /**
-   * Specifies whether a value must be provided with this argument if it
-   * is present. If this is changed from <CODE>false</CODE> to
-   * <CODE>true</CODE>, then a value placeholder must also be provided.
-   *
-   * @param needsValue
-   *          Indicates whether a value must be provided with this
-   *          argument if it is present.
-   */
-  public void setNeedsValue(boolean needsValue)
-  {
-    this.needsValue = needsValue;
-  }
-
-
-
-  /**
-   * Retrieves the value placeholder that will be displayed for this
-   * argument in the generated usage information.
-   *
-   * @return The value placeholder that will be displayed for this
-   *         argument in the generated usage information, or
-   *         <CODE>null</CODE> if there is none.
-   */
-  public LocalizableMessage getValuePlaceholder()
-  {
-    return valuePlaceholder;
-  }
-
-
-
-  /**
-   * Specifies the value placeholder that will be displayed for this
-   * argument in the generated usage information. It may be
-   * <CODE>null</CODE> only if <CODE>needsValue()</CODE> returns
-   * <CODE>false</CODE>.
-   *
-   * @param valuePlaceholder
-   *          The value placeholder that will be displayed for this
-   *          argument in the generated usage information.
-   */
-  public void setValuePlaceholder(LocalizableMessage valuePlaceholder)
-  {
-    this.valuePlaceholder = valuePlaceholder;
-  }
-
-
-
-  /**
-   * Retrieves the default value that will be used for this argument if
-   * it is not specified on the command line and it is not set from a
-   * properties file.
-   *
-   * @return The default value that will be used for this argument if it
-   *         is not specified on the command line and it is not set from
-   *         a properties file, or <CODE>null</CODE> if there is no
-   *         default value.
+   * @return The default value that will be used for this argument if it is not
+   *         specified on the command line and it is not set from a properties
+   *         file, or <CODE>null</CODE> if there is no default value.
    */
   public String getDefaultValue()
   {
@@ -420,88 +264,6 @@
 
 
   /**
-   * Specifies the default value that will be used for this argument if
-   * it is not specified on the command line and it is not set from a
-   * properties file.
-   *
-   * @param defaultValue
-   *          The default value that will be used for this argument if
-   *          it is not specified on the command line and it is not set
-   *          from a properties file.
-   */
-  public void setDefaultValue(String defaultValue)
-  {
-    this.defaultValue = defaultValue;
-  }
-
-
-
-  /**
-   * Retrieves the name of a property in a properties file that may be
-   * used to set the default value for this argument if it is present. A
-   * value read from a properties file will override the default value
-   * returned from the <CODE>getDefaultValue</CODE>, but the properties
-   * file value will be overridden by a value supplied on the command
-   * line.
-   *
-   * @return The name of a property in a properties file that may be
-   *         used to set the default value for this argument if it is
-   *         present.
-   */
-  public String getPropertyName()
-  {
-    return propertyName;
-  }
-
-
-
-  /**
-   * Specifies the name of a property in a properties file that may be
-   * used to set the default value for this argument if it is present.
-   *
-   * @param propertyName
-   *          The name of a property in a properties file that may be
-   *          used to set the default value for this argument if it is
-   *          present.
-   */
-  public void setPropertyName(String propertyName)
-  {
-    this.propertyName = propertyName;
-  }
-
-
-
-  /**
-   * Indicates whether this argument was provided in the set of
-   * properties found is a properties file.
-   *
-   * @return <CODE>true</CODE> if this argument was provided in the set
-   *         of properties found is a properties file, or
-   *         <CODE>false</CODE> if not.
-   */
-  public boolean isValueSetByProperty()
-  {
-    return isValueSetByProperty;
-  }
-
-
-
-  /**
-   * Specifies whether this argument was provided in the set of
-   * properties found is a properties file.
-   *
-   * @param isValueSetByProperty
-   *          Specify whether this argument was provided in the set of
-   *          properties found is a properties file.
-   */
-  public void setValueSetByProperty(boolean isValueSetByProperty)
-  {
-    this.isValueSetByProperty = isValueSetByProperty;
-  }
-
-
-
-  /**
    * Retrieves the human-readable description for this argument.
    *
    * @return The human-readable description for this argument.
@@ -514,25 +276,225 @@
 
 
   /**
-   * Indicates whether this argument has at least one value.
+   * Retrieves the value of this argument as an integer.
    *
-   * @return <CODE>true</CODE> if this argument has at least one value,
-   *         or <CODE>false</CODE> if it does not have any values.
+   * @return The value of this argument as an integer.
+   * @throws ArgumentException
+   *           If there are multiple values, or the value cannot be parsed as an
+   *           integer.
    */
-  public boolean hasValue()
+  public double getDoubleValue() throws ArgumentException
   {
-    return (!values.isEmpty());
+    if (values.isEmpty())
+    {
+      final LocalizableMessage message = ERR_ARG_NO_INT_VALUE.get(name);
+      throw new ArgumentException(message);
+    }
+
+    final Iterator<String> iterator = values.iterator();
+    final String valueString = iterator.next();
+
+    double intValue;
+    try
+    {
+      intValue = Double.parseDouble(valueString);
+    }
+    catch (final Exception e)
+    {
+      final LocalizableMessage message = ERR_ARG_CANNOT_DECODE_AS_INT.get(
+          valueString, name);
+      throw new ArgumentException(message, e);
+    }
+
+    if (iterator.hasNext())
+    {
+      final LocalizableMessage message = ERR_ARG_INT_MULTIPLE_VALUES.get(name);
+      throw new ArgumentException(message);
+    }
+    else
+    {
+      return intValue;
+    }
   }
 
 
 
   /**
-   * Retrieves the string vale for this argument. If it has multiple
-   * values, then the first will be returned. If it does not have any
-   * values, then the default value will be returned.
+   * Retrieves the set of values for this argument as a list of integers.
    *
-   * @return The string value for this argument, or <CODE>null</CODE> if
-   *         there are no values and no default value has been given.
+   * @return A list of the integer representations of the values for this
+   *         argument.
+   * @throws ArgumentException
+   *           If any of the values cannot be parsed as an integer.
+   */
+  public LinkedList<Double> getDoubleValues() throws ArgumentException
+  {
+    final LinkedList<Double> intList = new LinkedList<Double>();
+
+    final Iterator<String> iterator = values.iterator();
+    while (iterator.hasNext())
+    {
+      final String valueString = iterator.next();
+
+      try
+      {
+        intList.add(Double.valueOf(valueString));
+      }
+      catch (final Exception e)
+      {
+        final LocalizableMessage message = ERR_ARG_CANNOT_DECODE_AS_INT.get(
+            valueString, name);
+        throw new ArgumentException(message, e);
+      }
+    }
+
+    return intList;
+  }
+
+
+
+  /**
+   * Retrieves the value of this argument as an integer.
+   *
+   * @return The value of this argument as an integer.
+   * @throws ArgumentException
+   *           If there are multiple values, or the value cannot be parsed as an
+   *           integer.
+   */
+  public int getIntValue() throws ArgumentException
+  {
+    if (values.isEmpty())
+    {
+      final LocalizableMessage message = ERR_ARG_NO_INT_VALUE.get(name);
+      throw new ArgumentException(message);
+    }
+
+    final Iterator<String> iterator = values.iterator();
+    final String valueString = iterator.next();
+
+    int intValue;
+    try
+    {
+      intValue = Integer.parseInt(valueString);
+    }
+    catch (final Exception e)
+    {
+      final LocalizableMessage message = ERR_ARG_CANNOT_DECODE_AS_INT.get(
+          valueString, name);
+      throw new ArgumentException(message, e);
+    }
+
+    if (iterator.hasNext())
+    {
+      final LocalizableMessage message = ERR_ARG_INT_MULTIPLE_VALUES.get(name);
+      throw new ArgumentException(message);
+    }
+    else
+    {
+      return intValue;
+    }
+  }
+
+
+
+  /**
+   * Retrieves the set of values for this argument as a list of integers.
+   *
+   * @return A list of the integer representations of the values for this
+   *         argument.
+   * @throws ArgumentException
+   *           If any of the values cannot be parsed as an integer.
+   */
+  public LinkedList<Integer> getIntValues() throws ArgumentException
+  {
+    final LinkedList<Integer> intList = new LinkedList<Integer>();
+
+    final Iterator<String> iterator = values.iterator();
+    while (iterator.hasNext())
+    {
+      final String valueString = iterator.next();
+
+      try
+      {
+        intList.add(Integer.valueOf(valueString));
+      }
+      catch (final Exception e)
+      {
+        final LocalizableMessage message = ERR_ARG_CANNOT_DECODE_AS_INT.get(
+            valueString, name);
+        throw new ArgumentException(message, e);
+      }
+    }
+
+    return intList;
+  }
+
+
+
+  /**
+   * Retrieves the long (multi-character) identifier that may be used to specify
+   * the value of this argument.
+   *
+   * @return The long (multi-character) identifier that may be used to specify
+   *         the value of this argument.
+   */
+  public String getLongIdentifier()
+  {
+    return longIdentifier;
+  }
+
+
+
+  /**
+   * Retrieves the generic name that will be used to refer to this argument.
+   *
+   * @return The generic name that will be used to refer to this argument.
+   */
+  public String getName()
+  {
+    return name;
+  }
+
+
+
+  /**
+   * Retrieves the name of a property in a properties file that may be used to
+   * set the default value for this argument if it is present. A value read from
+   * a properties file will override the default value returned from the
+   * <CODE>getDefaultValue</CODE>, but the properties file value will be
+   * overridden by a value supplied on the command line.
+   *
+   * @return The name of a property in a properties file that may be used to set
+   *         the default value for this argument if it is present.
+   */
+  public String getPropertyName()
+  {
+    return propertyName;
+  }
+
+
+
+  /**
+   * Retrieves the single-character identifier that may be used to specify the
+   * value of this argument.
+   *
+   * @return The single-character identifier that may be used to specify the
+   *         value of this argument, or <CODE>null</CODE> if there is none.
+   */
+  public Character getShortIdentifier()
+  {
+    return shortIdentifier;
+  }
+
+
+
+  /**
+   * Retrieves the string vale for this argument. If it has multiple values,
+   * then the first will be returned. If it does not have any values, then the
+   * default value will be returned.
+   *
+   * @return The string value for this argument, or <CODE>null</CODE> if there
+   *         are no values and no default value has been given.
    */
   public String getValue()
   {
@@ -547,6 +509,21 @@
 
 
   /**
+   * Retrieves the value placeholder that will be displayed for this argument in
+   * the generated usage information.
+   *
+   * @return The value placeholder that will be displayed for this argument in
+   *         the generated usage information, or <CODE>null</CODE> if there is
+   *         none.
+   */
+  public LocalizableMessage getValuePlaceholder()
+  {
+    return valuePlaceholder;
+  }
+
+
+
+  /**
    * Retrieves the set of string values for this argument.
    *
    * @return The set of string values for this argument.
@@ -559,209 +536,238 @@
 
 
   /**
-   * Retrieves the value of this argument as an integer.
+   * Indicates whether this argument has at least one value.
    *
-   * @return The value of this argument as an integer.
-   * @throws ArgumentException
-   *           If there are multiple values, or the value cannot be
-   *           parsed as an integer.
+   * @return <CODE>true</CODE> if this argument has at least one value, or
+   *         <CODE>false</CODE> if it does not have any values.
    */
-  public int getIntValue() throws ArgumentException
+  public boolean hasValue()
   {
-    if (values.isEmpty())
-    {
-      LocalizableMessage message = ERR_ARG_NO_INT_VALUE.get(name);
-      throw new ArgumentException(message);
-    }
-
-    Iterator<String> iterator = values.iterator();
-    String valueString = iterator.next();
-
-    int intValue;
-    try
-    {
-      intValue = Integer.parseInt(valueString);
-    }
-    catch (Exception e)
-    {
-      LocalizableMessage message =
-          ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, name);
-      throw new ArgumentException(message, e);
-    }
-
-    if (iterator.hasNext())
-    {
-      LocalizableMessage message = ERR_ARG_INT_MULTIPLE_VALUES.get(name);
-      throw new ArgumentException(message);
-    }
-    else
-    {
-      return intValue;
-    }
+    return (!values.isEmpty());
   }
 
 
 
   /**
-   * Retrieves the set of values for this argument as a list of
-   * integers.
+   * Indicates whether this argument should be hidden from the usage
+   * information.
    *
-   * @return A list of the integer representations of the values for
-   *         this argument.
-   * @throws ArgumentException
-   *           If any of the values cannot be parsed as an integer.
+   * @return <CODE>true</CODE> if this argument should be hidden from the usage
+   *         information, or <CODE>false</CODE> if not.
    */
-  public LinkedList<Integer> getIntValues() throws ArgumentException
+  public boolean isHidden()
   {
-    LinkedList<Integer> intList = new LinkedList<Integer>();
-
-    Iterator<String> iterator = values.iterator();
-    while (iterator.hasNext())
-    {
-      String valueString = iterator.next();
-
-      try
-      {
-        intList.add(Integer.valueOf(valueString));
-      }
-      catch (Exception e)
-      {
-        LocalizableMessage message =
-            ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, name);
-        throw new ArgumentException(message, e);
-      }
-    }
-
-    return intList;
+    return isHidden;
   }
 
 
 
   /**
-   * Retrieves the value of this argument as an integer.
+   * Indicates whether this argument may be provided more than once on the
+   * command line to specify multiple values.
    *
-   * @return The value of this argument as an integer.
-   * @throws ArgumentException
-   *           If there are multiple values, or the value cannot be
-   *           parsed as an integer.
+   * @return <CODE>true</CODE> if this argument may be provided more than once
+   *         on the command line to specify multiple values, or
+   *         <CODE>false</CODE> if it may have at most one value.
    */
-  public double getDoubleValue() throws ArgumentException
+  public boolean isMultiValued()
   {
-    if (values.isEmpty())
-    {
-      LocalizableMessage message = ERR_ARG_NO_INT_VALUE.get(name);
-      throw new ArgumentException(message);
-    }
-
-    Iterator<String> iterator = values.iterator();
-    String valueString = iterator.next();
-
-    double intValue;
-    try
-    {
-      intValue = Double.parseDouble(valueString);
-    }
-    catch (Exception e)
-    {
-      LocalizableMessage message =
-          ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, name);
-      throw new ArgumentException(message, e);
-    }
-
-    if (iterator.hasNext())
-    {
-      LocalizableMessage message = ERR_ARG_INT_MULTIPLE_VALUES.get(name);
-      throw new ArgumentException(message);
-    }
-    else
-    {
-      return intValue;
-    }
+    return isMultiValued;
   }
 
 
 
   /**
-   * Retrieves the set of values for this argument as a list of
-   * integers.
+   * Indicates whether this argument is present in the parsed set of
+   * command-line arguments.
    *
-   * @return A list of the integer representations of the values for
-   *         this argument.
-   * @throws ArgumentException
-   *           If any of the values cannot be parsed as an integer.
+   * @return <CODE>true</CODE> if this argument is present in the parsed set of
+   *         command-line arguments, or <CODE>false</CODE> if not.
    */
-  public LinkedList<Double> getDoubleValues() throws ArgumentException
+  public boolean isPresent()
   {
-    LinkedList<Double> intList = new LinkedList<Double>();
-
-    Iterator<String> iterator = values.iterator();
-    while (iterator.hasNext())
-    {
-      String valueString = iterator.next();
-
-      try
-      {
-        intList.add(Double.valueOf(valueString));
-      }
-      catch (Exception e)
-      {
-        LocalizableMessage message =
-            ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, name);
-        throw new ArgumentException(message, e);
-      }
-    }
-
-    return intList;
+    return isPresent;
   }
 
 
 
   /**
-   * Retrieves the value of this argument as a <CODE>Boolean</CODE>.
+   * Indicates whether this argument is required to have at least one value.
    *
-   * @return The value of this argument as a <CODE>Boolean</CODE>.
-   * @throws ArgumentException
-   *           If this argument cannot be interpreted as a Boolean
-   *           value.
+   * @return <CODE>true</CODE> if this argument is required to have at least one
+   *         value, or <CODE>false</CODE> if it does not need to have a value.
    */
-  public boolean getBooleanValue() throws ArgumentException
+  public boolean isRequired()
   {
-    if (values.isEmpty())
-    {
-      LocalizableMessage message = ERR_ARG_NO_BOOLEAN_VALUE.get(name);
-      throw new ArgumentException(message);
-    }
+    return isRequired;
+  }
 
-    Iterator<String> iterator = values.iterator();
-    String valueString = toLowerCase(iterator.next());
 
-    boolean booleanValue;
-    if (valueString.equals("true") || valueString.equals("yes")
-        || valueString.equals("on") || valueString.equals("1"))
-    {
-      booleanValue = true;
-    }
-    else if (valueString.equals("false") || valueString.equals("no")
-        || valueString.equals("off") || valueString.equals("0"))
-    {
-      booleanValue = false;
-    }
-    else
-    {
-      LocalizableMessage message =
-          ERR_ARG_CANNOT_DECODE_AS_BOOLEAN.get(valueString, name);
-      throw new ArgumentException(message);
-    }
 
-    if (iterator.hasNext())
-    {
-      LocalizableMessage message = ERR_ARG_BOOLEAN_MULTIPLE_VALUES.get(name);
-      throw new ArgumentException(message);
-    }
-    else
-    {
-      return booleanValue;
-    }
+  /**
+   * Indicates whether this argument was provided in the set of properties found
+   * is a properties file.
+   *
+   * @return <CODE>true</CODE> if this argument was provided in the set of
+   *         properties found is a properties file, or <CODE>false</CODE> if
+   *         not.
+   */
+  public boolean isValueSetByProperty()
+  {
+    return isValueSetByProperty;
+  }
+
+
+
+  /**
+   * Indicates whether a value must be provided with this argument if it is
+   * present.
+   *
+   * @return <CODE>true</CODE> if a value must be provided with the argument if
+   *         it is present, or <CODE>false</CODE> if the argument does not take
+   *         a value and the presence of the argument identifier itself is
+   *         sufficient to convey the necessary information.
+   */
+  public boolean needsValue()
+  {
+    return needsValue;
+  }
+
+
+
+  /**
+   * Specifies the default value that will be used for this argument if it is
+   * not specified on the command line and it is not set from a properties file.
+   *
+   * @param defaultValue
+   *          The default value that will be used for this argument if it is not
+   *          specified on the command line and it is not set from a properties
+   *          file.
+   */
+  public void setDefaultValue(final String defaultValue)
+  {
+    this.defaultValue = defaultValue;
+  }
+
+
+
+  /**
+   * Specifies whether this argument should be hidden from the usage
+   * information.
+   *
+   * @param isHidden
+   *          Indicates whether this argument should be hidden from the usage
+   *          information.
+   */
+  public void setHidden(final boolean isHidden)
+  {
+    this.isHidden = isHidden;
+  }
+
+
+
+  /**
+   * Specifies whether this argument may be provided more than once on the
+   * command line to specify multiple values.
+   *
+   * @param isMultiValued
+   *          Indicates whether this argument may be provided more than once on
+   *          the command line to specify multiple values.
+   */
+  public void setMultiValued(final boolean isMultiValued)
+  {
+    this.isMultiValued = isMultiValued;
+  }
+
+
+
+  /**
+   * Specifies whether a value must be provided with this argument if it is
+   * present. If this is changed from <CODE>false</CODE> to <CODE>true</CODE>,
+   * then a value placeholder must also be provided.
+   *
+   * @param needsValue
+   *          Indicates whether a value must be provided with this argument if
+   *          it is present.
+   */
+  public void setNeedsValue(final boolean needsValue)
+  {
+    this.needsValue = needsValue;
+  }
+
+
+
+  /**
+   * Specifies whether this argument is present in the parsed set of
+   * command-line arguments.
+   *
+   * @param isPresent
+   *          Indicates whether this argument is present in the set of
+   *          command-line arguments.
+   */
+  public void setPresent(final boolean isPresent)
+  {
+    this.isPresent = isPresent;
+  }
+
+
+
+  /**
+   * Specifies the name of a property in a properties file that may be used to
+   * set the default value for this argument if it is present.
+   *
+   * @param propertyName
+   *          The name of a property in a properties file that may be used to
+   *          set the default value for this argument if it is present.
+   */
+  public void setPropertyName(final String propertyName)
+  {
+    this.propertyName = propertyName;
+  }
+
+
+
+  /**
+   * Specifies whether this argument is required to have at least one value.
+   *
+   * @param isRequired
+   *          Indicates whether this argument is required to have at least one
+   *          value.
+   */
+  public void setRequired(final boolean isRequired)
+  {
+    this.isRequired = isRequired;
+  }
+
+
+
+  /**
+   * Specifies the value placeholder that will be displayed for this argument in
+   * the generated usage information. It may be <CODE>null</CODE> only if
+   * <CODE>needsValue()</CODE> returns <CODE>false</CODE>.
+   *
+   * @param valuePlaceholder
+   *          The value placeholder that will be displayed for this argument in
+   *          the generated usage information.
+   */
+  public void setValuePlaceholder(final LocalizableMessage valuePlaceholder)
+  {
+    this.valuePlaceholder = valuePlaceholder;
+  }
+
+
+
+  /**
+   * Specifies whether this argument was provided in the set of properties found
+   * is a properties file.
+   *
+   * @param isValueSetByProperty
+   *          Specify whether this argument was provided in the set of
+   *          properties found is a properties file.
+   */
+  public void setValueSetByProperty(final boolean isValueSetByProperty)
+  {
+    this.isValueSetByProperty = isValueSetByProperty;
   }
 
 
@@ -773,37 +779,11 @@
    * @param valueString
    *          The value for which to make the determination.
    * @param invalidReason
-   *          A buffer into which the invalid reason may be written if
-   *          the value is not acceptable.
-   * @return <CODE>true</CODE> if the value is acceptable, or
-   *         <CODE>false</CODE> if it is not.
+   *          A buffer into which the invalid reason may be written if the value
+   *          is not acceptable.
+   * @return <CODE>true</CODE> if the value is acceptable, or <CODE>false</CODE>
+   *         if it is not.
    */
   public abstract boolean valueIsAcceptable(String valueString,
       LocalizableMessageBuilder invalidReason);
-
-
-
-  /**
-   * Adds a value to the set of values for this argument. This should
-   * only be called if the value is allowed by the
-   * <CODE>valueIsAcceptable</CODE> method.
-   *
-   * @param valueString
-   *          The string representation of the value to add to this
-   *          argument.
-   */
-  public void addValue(String valueString)
-  {
-    values.add(valueString);
-  }
-
-
-
-  /**
-   * Clears the set of values assigned to this argument.
-   */
-  public void clearValues()
-  {
-    values.clear();
-  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/ArgumentException.java b/sdk/src/com/sun/opends/sdk/tools/ArgumentException.java
index 7198525..4c9ba59 100644
--- a/sdk/src/com/sun/opends/sdk/tools/ArgumentException.java
+++ b/sdk/src/com/sun/opends/sdk/tools/ArgumentException.java
@@ -33,23 +33,13 @@
 
 
 
-
 /**
- * This class defines an exception that may be thrown if there is a
- * problem with an argument definition.
+ * This class defines an exception that may be thrown if there is a problem with
+ * an argument definition.
  */
-final class ArgumentException extends Exception implements
-    LocalizableException
+@SuppressWarnings("serial")
+final class ArgumentException extends Exception implements LocalizableException
 {
-  /**
-   * The serial version identifier required to satisfy the compiler
-   * because this class extends <CODE>java.lang.Exception</CODE>, which
-   * implements the <CODE>java.io.Serializable</CODE> interface. This
-   * value was generated using the <CODE>serialver</CODE> command-line
-   * utility included with the Java SDK.
-   */
-  private static final long serialVersionUID = 5623155045312160730L;
-
   // The I18N message associated with this exception.
   private final LocalizableMessage message;
 
@@ -57,11 +47,11 @@
 
   /**
    * Creates a new argument exception with the provided message.
-   * 
+   *
    * @param message
    *          The message that explains the problem that occurred.
    */
-  ArgumentException(LocalizableMessage message)
+  ArgumentException(final LocalizableMessage message)
   {
     super(String.valueOf(message));
     this.message = message;
@@ -70,15 +60,14 @@
 
 
   /**
-   * Creates a new argument exception with the provided message and root
-   * cause.
-   * 
+   * Creates a new argument exception with the provided message and root cause.
+   *
    * @param message
    *          The message that explains the problem that occurred.
    * @param cause
    *          The exception that was caught to trigger this exception.
    */
-  ArgumentException(LocalizableMessage message, Throwable cause)
+  ArgumentException(final LocalizableMessage message, final Throwable cause)
   {
     super(String.valueOf(message), cause);
     this.message = message;
diff --git a/sdk/src/com/sun/opends/sdk/tools/ArgumentGroup.java b/sdk/src/com/sun/opends/sdk/tools/ArgumentGroup.java
index 7a70077..a4466ec 100644
--- a/sdk/src/com/sun/opends/sdk/tools/ArgumentGroup.java
+++ b/sdk/src/com/sun/opends/sdk/tools/ArgumentGroup.java
@@ -38,10 +38,9 @@
 
 
 
-
 /**
- * Class for organizing options into logical groups when arguement usage
- * is printed. To use an argument group, create an instance and use
+ * Class for organizing options into logical groups when arguement usage is
+ * printed. To use an argument group, create an instance and use
  * {@link org.opends.server.util.args.ArgumentParser #addArgument(Argument, ArgumentGroup)}
  * when adding arguments for to the parser.
  */
@@ -55,22 +54,22 @@
   private List<Argument> args = null;
 
   // Governs groups position within usage statement
-  private Integer priority;
+  private final Integer priority;
 
 
 
   /**
    * Creates a parameterized instance.
-   * 
+   *
    * @param description
    *          for options in this group that is printed before argument
    *          descriptions in usage output
    * @param priority
-   *          number governing the position of this group within the
-   *          usage statement. Groups with higher priority values appear
-   *          before groups with lower priority.
+   *          number governing the position of this group within the usage
+   *          statement. Groups with higher priority values appear before groups
+   *          with lower priority.
    */
-  ArgumentGroup(LocalizableMessage description, int priority)
+  ArgumentGroup(final LocalizableMessage description, final int priority)
   {
     this.description = description;
     this.priority = priority;
@@ -80,46 +79,9 @@
 
 
   /**
-   * Gets the description for this group of arguments.
-   * 
-   * @return description for this argument group
-   */
-  LocalizableMessage getDescription()
-  {
-    return this.description;
-  }
-
-
-
-  /**
-   * Sets the description for this group of arguments.
-   * 
-   * @param description
-   *          for this argument group
-   */
-  void setDescription(LocalizableMessage description)
-  {
-    this.description = description;
-  }
-
-
-
-  /**
-   * Gets the list of arguments associated with this group.
-   * 
-   * @return list of associated arguments
-   */
-  List<Argument> getArguments()
-  {
-    return Collections.unmodifiableList(args);
-  }
-
-
-
-  /**
    * {@inheritDoc}
    */
-  public int compareTo(ArgumentGroup o)
+  public int compareTo(final ArgumentGroup o)
   {
     // Groups with higher priority numbers appear before
     // those with lower priority in the usage output
@@ -129,57 +91,25 @@
 
 
   /**
-   * Indicates whether this group contains any members.
-   * 
-   * @return boolean where true means this group contains members
-   */
-  boolean containsArguments()
-  {
-    return this.args.size() > 0;
-  }
-
-
-
-  /**
-   * Indicates whether this group contains any non-hidden members.
-   * 
-   * @return boolean where true means this group contains non-hidden
-   *         members
-   */
-  boolean containsNonHiddenArguments()
-  {
-    for (Argument arg : args)
-    {
-      if (!arg.isHidden())
-      {
-        return true;
-      }
-    }
-    return false;
-  }
-
-
-
-  /**
    * Adds an argument to this group.
-   * 
+   *
    * @param arg
    *          to add
    * @return boolean where true indicates the add was successful
    */
-  boolean addArgument(Argument arg)
+  boolean addArgument(final Argument arg)
   {
     boolean success = false;
     if (arg != null)
     {
-      Character newShort = arg.getShortIdentifier();
-      String newLong = arg.getLongIdentifier();
+      final Character newShort = arg.getShortIdentifier();
+      final String newLong = arg.getLongIdentifier();
 
       // See if there is already an argument in this group that the
       // new argument should replace
-      for (Iterator<Argument> it = this.args.iterator(); it.hasNext();)
+      for (final Iterator<Argument> it = this.args.iterator(); it.hasNext();)
       {
-        Argument a = it.next();
+        final Argument a = it.next();
         if (newShort != null && newShort.equals(a.getShortIdentifier())
             || newLong != null && newLong.equals(a.getLongIdentifier()))
         {
@@ -196,15 +126,83 @@
 
 
   /**
+   * Indicates whether this group contains any members.
+   *
+   * @return boolean where true means this group contains members
+   */
+  boolean containsArguments()
+  {
+    return this.args.size() > 0;
+  }
+
+
+
+  /**
+   * Indicates whether this group contains any non-hidden members.
+   *
+   * @return boolean where true means this group contains non-hidden members
+   */
+  boolean containsNonHiddenArguments()
+  {
+    for (final Argument arg : args)
+    {
+      if (!arg.isHidden())
+      {
+        return true;
+      }
+    }
+    return false;
+  }
+
+
+
+  /**
+   * Gets the list of arguments associated with this group.
+   *
+   * @return list of associated arguments
+   */
+  List<Argument> getArguments()
+  {
+    return Collections.unmodifiableList(args);
+  }
+
+
+
+  /**
+   * Gets the description for this group of arguments.
+   *
+   * @return description for this argument group
+   */
+  LocalizableMessage getDescription()
+  {
+    return this.description;
+  }
+
+
+
+  /**
    * Removes an argument from this group.
-   * 
+   *
    * @param arg
    *          to remove
    * @return boolean where true indicates the remove was successful
    */
-  boolean removeArgument(Argument arg)
+  boolean removeArgument(final Argument arg)
   {
     return this.args.remove(arg);
   }
 
+
+
+  /**
+   * Sets the description for this group of arguments.
+   *
+   * @param description
+   *          for this argument group
+   */
+  void setDescription(final LocalizableMessage description)
+  {
+    this.description = description;
+  }
+
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/ArgumentParser.java b/sdk/src/com/sun/opends/sdk/tools/ArgumentParser.java
index 8de195f..546185a 100644
--- a/sdk/src/com/sun/opends/sdk/tools/ArgumentParser.java
+++ b/sdk/src/com/sun/opends/sdk/tools/ArgumentParser.java
@@ -30,8 +30,12 @@
 
 import static com.sun.opends.sdk.messages.Messages.*;
 import static com.sun.opends.sdk.tools.ToolConstants.*;
-import static com.sun.opends.sdk.tools.Utils.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.tools.Utils.PROPERTY_SCRIPT_NAME;
+import static com.sun.opends.sdk.tools.Utils.wrapText;
+import static com.sun.opends.sdk.util.StaticUtils.EOL;
+import static com.sun.opends.sdk.util.StaticUtils.getBytes;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -44,17 +48,15 @@
 
 
 
-
 /**
- * This class defines a utility that can be used to deal with
- * command-line arguments for applications in a CLIP-compliant manner
- * using either short one-character or longer word-based arguments. It
- * is also integrated with the Directory Server message catalog so that
- * it can display messages in an internationalizeable format, can
- * automatically generate usage information, can detect conflicts
- * between arguments, and can interact with a properties file to obtain
- * default values for arguments there if they are not specified on the
- * command-line.
+ * This class defines a utility that can be used to deal with command-line
+ * arguments for applications in a CLIP-compliant manner using either short
+ * one-character or longer word-based arguments. It is also integrated with the
+ * Directory Server message catalog so that it can display messages in an
+ * internationalizeable format, can automatically generate usage information,
+ * can detect conflicts between arguments, and can interact with a properties
+ * file to obtain default values for arguments there if they are not specified
+ * on the command-line.
  */
 final class ArgumentParser
 {
@@ -64,8 +66,8 @@
   private StringArgument filePropertiesPathArgument;
 
   /**
-   * The argument that will be used to indicate that we'll not look for
-   * default properties file.
+   * The argument that will be used to indicate that we'll not look for default
+   * properties file.
    */
   private BooleanArgument noPropertiesFileArgument;
 
@@ -79,17 +81,17 @@
 
   // The set of unnamed trailing arguments that were provided for this
   // parser.
-  private ArrayList<String> trailingArguments;
+  private final ArrayList<String> trailingArguments;
 
   // Indicates whether this parser will allow additional unnamed
   // arguments at
   // the end of the list.
-  private boolean allowsTrailingArguments;
+  private final boolean allowsTrailingArguments;
 
   // Indicates whether long arguments should be treated in a
   // case-sensitive
   // manner.
-  private boolean longArgumentsCaseSensitive;
+  private final boolean longArgumentsCaseSensitive;
 
   // Indicates whether the usage or version information has been
   // displayed.
@@ -100,26 +102,26 @@
 
   // The set of arguments defined for this parser, referenced by short
   // ID.
-  private HashMap<Character, Argument> shortIDMap;
+  private final HashMap<Character, Argument> shortIDMap;
 
   // The set of arguments defined for this parser, referenced by
   // argument name.
-  private HashMap<String, Argument> argumentMap;
+  private final HashMap<String, Argument> argumentMap;
 
   // The set of arguments defined for this parser, referenced by long
   // ID.
-  private HashMap<String, Argument> longIDMap;
+  private final HashMap<String, Argument> longIDMap;
 
   // The maximum number of unnamed trailing arguments that may be
   // provided.
-  private int maxTrailingArguments;
+  private final int maxTrailingArguments;
 
   // The minimum number of unnamed trailing arguments that may be
   // provided.
-  private int minTrailingArguments;
+  private final int minTrailingArguments;
 
   // The total set of arguments defined for this parser.
-  private LinkedList<Argument> argumentList;
+  private final LinkedList<Argument> argumentList;
 
   // The output stream to which usage information should be printed.
   private OutputStream usageOutputStream;
@@ -127,17 +129,17 @@
   // The fully-qualified name of the Java class that should be invoked
   // to launch
   // the program with which this argument parser is associated.
-  private String mainClassName;
+  private final String mainClassName;
 
   // A human-readable description for the tool, which will be included
   // when
   // displaying usage information.
-  private LocalizableMessage toolDescription;
+  private final LocalizableMessage toolDescription;
 
   // The display name that will be used for the trailing arguments in
   // the usage
   // information.
-  private String trailingArgsDisplayName;
+  private final String trailingArgsDisplayName;
 
   // The raw set of command-line arguments that were provided.
   private String[] rawArguments;
@@ -146,33 +148,32 @@
   private Set<ArgumentGroup> argumentGroups;
 
   /**
-   * Group for arguments that have not been explicitly grouped. These
-   * will appear at the top of the usage statement without a header.
+   * Group for arguments that have not been explicitly grouped. These will
+   * appear at the top of the usage statement without a header.
    */
-  private ArgumentGroup defaultArgGroup = new ArgumentGroup(
+  private final ArgumentGroup defaultArgGroup = new ArgumentGroup(
       LocalizableMessage.EMPTY, Integer.MAX_VALUE);
 
   /**
-   * Group for arguments that are related to connection through LDAP.
-   * This includes options like the bind DN, the port, etc.
+   * Group for arguments that are related to connection through LDAP. This
+   * includes options like the bind DN, the port, etc.
    */
-  private ArgumentGroup ldapArgGroup = new ArgumentGroup(
-      INFO_DESCRIPTION_LDAP_CONNECTION_ARGS.get(),
-      Integer.MIN_VALUE + 2);
+  private final ArgumentGroup ldapArgGroup = new ArgumentGroup(
+      INFO_DESCRIPTION_LDAP_CONNECTION_ARGS.get(), Integer.MIN_VALUE + 2);
 
   /**
    * Group for arguments that are related to utility input/output like
-   * properties file, no-prompt etc. These will appear toward the bottom
-   * of the usage statement.
+   * properties file, no-prompt etc. These will appear toward the bottom of the
+   * usage statement.
    */
-  private ArgumentGroup ioArgGroup = new ArgumentGroup(
+  private final ArgumentGroup ioArgGroup = new ArgumentGroup(
       INFO_DESCRIPTION_IO_ARGS.get(), Integer.MIN_VALUE + 1);
 
   /**
-   * Group for arguments that are general like help, version etc. These
-   * will appear at the end of the usage statement.
+   * Group for arguments that are general like help, version etc. These will
+   * appear at the end of the usage statement.
    */
-  private ArgumentGroup generalArgGroup = new ArgumentGroup(
+  private final ArgumentGroup generalArgGroup = new ArgumentGroup(
       INFO_DESCRIPTION_GENERAL_ARGS.get(), Integer.MIN_VALUE);
 
   private final static String INDENT = "    ";
@@ -182,22 +183,23 @@
 
 
   /**
-   * Creates a new instance of this argument parser with no arguments.
-   * Unnamed trailing arguments will not be allowed.
+   * Creates a new instance of this argument parser with no arguments. Unnamed
+   * trailing arguments will not be allowed.
    *
    * @param mainClassName
-   *          The fully-qualified name of the Java class that should be
-   *          invoked to launch the program with which this argument
-   *          parser is associated.
+   *          The fully-qualified name of the Java class that should be invoked
+   *          to launch the program with which this argument parser is
+   *          associated.
    * @param toolDescription
-   *          A human-readable description for the tool, which will be
-   *          included when displaying usage information.
+   *          A human-readable description for the tool, which will be included
+   *          when displaying usage information.
    * @param longArgumentsCaseSensitive
    *          Indicates whether long arguments should be treated in a
    *          case-sensitive manner.
    */
-  ArgumentParser(String mainClassName, LocalizableMessage toolDescription,
-      boolean longArgumentsCaseSensitive)
+  ArgumentParser(final String mainClassName,
+      final LocalizableMessage toolDescription,
+      final boolean longArgumentsCaseSensitive)
   {
     this.mainClassName = mainClassName;
     this.toolDescription = toolDescription;
@@ -225,39 +227,39 @@
 
 
   /**
-   * Creates a new instance of this argument parser with no arguments
-   * that may or may not be allowed to have unnamed trailing arguments.
+   * Creates a new instance of this argument parser with no arguments that may
+   * or may not be allowed to have unnamed trailing arguments.
    *
    * @param mainClassName
-   *          The fully-qualified name of the Java class that should be
-   *          invoked to launch the program with which this argument
-   *          parser is associated.
+   *          The fully-qualified name of the Java class that should be invoked
+   *          to launch the program with which this argument parser is
+   *          associated.
    * @param toolDescription
-   *          A human-readable description for the tool, which will be
-   *          included when displaying usage information.
+   *          A human-readable description for the tool, which will be included
+   *          when displaying usage information.
    * @param longArgumentsCaseSensitive
    *          Indicates whether long arguments should be treated in a
    *          case-sensitive manner.
    * @param allowsTrailingArguments
-   *          Indicates whether this parser allows unnamed trailing
-   *          arguments to be provided.
+   *          Indicates whether this parser allows unnamed trailing arguments to
+   *          be provided.
    * @param minTrailingArguments
-   *          The minimum number of unnamed trailing arguments that must
-   *          be provided. A value less than or equal to zero indicates
-   *          that no minimum will be enforced.
+   *          The minimum number of unnamed trailing arguments that must be
+   *          provided. A value less than or equal to zero indicates that no
+   *          minimum will be enforced.
    * @param maxTrailingArguments
-   *          The maximum number of unnamed trailing arguments that may
-   *          be provided. A value less than or equal to zero indicates
-   *          that no maximum will be enforced.
+   *          The maximum number of unnamed trailing arguments that may be
+   *          provided. A value less than or equal to zero indicates that no
+   *          maximum will be enforced.
    * @param trailingArgsDisplayName
-   *          The display name that should be used as a placeholder for
-   *          unnamed trailing arguments in the generated usage
-   *          information.
+   *          The display name that should be used as a placeholder for unnamed
+   *          trailing arguments in the generated usage information.
    */
-  ArgumentParser(String mainClassName, LocalizableMessage toolDescription,
-      boolean longArgumentsCaseSensitive,
-      boolean allowsTrailingArguments, int minTrailingArguments,
-      int maxTrailingArguments, String trailingArgsDisplayName)
+  ArgumentParser(final String mainClassName,
+      final LocalizableMessage toolDescription,
+      final boolean longArgumentsCaseSensitive,
+      final boolean allowsTrailingArguments, final int minTrailingArguments,
+      final int maxTrailingArguments, final String trailingArgsDisplayName)
   {
     this.mainClassName = mainClassName;
     this.toolDescription = toolDescription;
@@ -283,264 +285,15 @@
 
 
   /**
-   * Retrieves the fully-qualified name of the Java class that should be
-   * invoked to launch the program with which this argument parser is
-   * associated.
-   *
-   * @return The fully-qualified name of the Java class that should be
-   *         invoked to launch the program with which this argument
-   *         parser is associated.
-   */
-  String getMainClassName()
-  {
-    return mainClassName;
-  }
-
-
-
-  /**
-   * Retrieves a human-readable description for this tool, which should
-   * be included at the top of the command-line usage information.
-   *
-   * @return A human-readable description for this tool, or {@code null}
-   *         if none is available.
-   */
-  LocalizableMessage getToolDescription()
-  {
-    return toolDescription;
-  }
-
-
-
-  /**
-   * Indicates whether this parser will allow unnamed trailing
-   * arguments. These will be arguments at the end of the list that are
-   * not preceded by either a long or short identifier and will need to
-   * be manually parsed by the application using this parser. Note that
-   * once an unnamed trailing argument has been identified, all
-   * remaining arguments will be classified as such.
-   *
-   * @return <CODE>true</CODE> if this parser allows unnamed trailing
-   *         arguments, or <CODE>false</CODE> if it does not.
-   */
-  boolean allowsTrailingArguments()
-  {
-    return allowsTrailingArguments;
-  }
-
-
-
-  /**
-   * Retrieves the minimum number of unnamed trailing arguments that
-   * must be provided.
-   *
-   * @return The minimum number of unnamed trailing arguments that must
-   *         be provided, or a value less than or equal to zero if no
-   *         minimum will be enforced.
-   */
-  int getMinTrailingArguments()
-  {
-    return minTrailingArguments;
-  }
-
-
-
-  /**
-   * Retrieves the maximum number of unnamed trailing arguments that may
-   * be provided.
-   *
-   * @return The maximum number of unnamed trailing arguments that may
-   *         be provided, or a value less than or equal to zero if no
-   *         maximum will be enforced.
-   */
-  int getMaxTrailingArguments()
-  {
-    return maxTrailingArguments;
-  }
-
-
-
-  /**
-   * Retrieves the list of all arguments that have been defined for this
-   * argument parser.
-   *
-   * @return The list of all arguments that have been defined for this
-   *         argument parser.
-   */
-  LinkedList<Argument> getArgumentList()
-  {
-    return argumentList;
-  }
-
-
-
-  /**
-   * Retrieves the argument with the specified name.
-   *
-   * @param name
-   *          The name of the argument to retrieve.
-   * @return The argument with the specified name, or <CODE>null</CODE>
-   *         if there is no such argument.
-   */
-  Argument getArgument(String name)
-  {
-    return argumentMap.get(name);
-  }
-
-
-
-  /**
-   * Retrieves the set of arguments mapped by the short identifier that
-   * may be used to reference them. Note that arguments that do not have
-   * a short identifier will not be present in this list.
-   *
-   * @return The set of arguments mapped by the short identifier that
-   *         may be used to reference them.
-   */
-  HashMap<Character, Argument> getArgumentsByShortID()
-  {
-    return shortIDMap;
-  }
-
-
-
-  /**
-   * Retrieves the argument with the specified short identifier.
-   *
-   * @param shortID
-   *          The short ID for the argument to retrieve.
-   * @return The argument with the specified short identifier, or
-   *         <CODE>null</CODE> if there is no such argument.
-   */
-  Argument getArgumentForShortID(Character shortID)
-  {
-    return shortIDMap.get(shortID);
-  }
-
-
-
-  /**
-   * Retrieves the set of arguments mapped by the long identifier that
-   * may be used to reference them. Note that arguments that do not have
-   * a long identifier will not be present in this list.
-   *
-   * @return The set of arguments mapped by the long identifier that may
-   *         be used to reference them.
-   */
-  HashMap<String, Argument> getArgumentsByLongID()
-  {
-    return longIDMap;
-  }
-
-
-
-  /**
-   * Retrieves the argument with the specified long identifier.
-   *
-   * @param longID
-   *          The long identifier of the argument to retrieve.
-   * @return The argument with the specified long identifier, or
-   *         <CODE>null</CODE> if there is no such argument.
-   */
-  Argument getArgumentForLongID(String longID)
-  {
-    return longIDMap.get(longID);
-  }
-
-
-
-  /**
-   * Retrieves the set of unnamed trailing arguments that were provided
-   * on the command line.
-   *
-   * @return The set of unnamed trailing arguments that were provided on
-   *         the command line.
-   */
-  ArrayList<String> getTrailingArguments()
-  {
-    return trailingArguments;
-  }
-
-
-
-  /**
-   * Retrieves the raw set of arguments that were provided.
-   *
-   * @return The raw set of arguments that were provided, or
-   *         <CODE>null</CODE> if the argument list has not yet been
-   *         parsed.
-   */
-  String[] getRawArguments()
-  {
-    return rawArguments;
-  }
-
-
-
-  /**
-   * Sets the usage group description for the default argument group.
-   *
-   * @param description
-   *          for the default group
-   */
-  void setDefaultArgumentGroupDescription(LocalizableMessage description)
-  {
-    this.defaultArgGroup.setDescription(description);
-  }
-
-
-
-  /**
-   * Sets the usage group description for the LDAP argument group.
-   *
-   * @param description
-   *          for the LDAP group
-   */
-  void setLdapArgumentGroupDescription(LocalizableMessage description)
-  {
-    this.ldapArgGroup.setDescription(description);
-  }
-
-
-
-  /**
-   * Sets the usage group description for the input/output argument
-   * group.
-   *
-   * @param description
-   *          for the input/output group
-   */
-  void setInputOutputArgumentGroupDescription(LocalizableMessage description)
-  {
-    this.ioArgGroup.setDescription(description);
-  }
-
-
-
-  /**
-   * Sets the usage group description for the general argument group.
-   *
-   * @param description
-   *          for the general group
-   */
-  void setGeneralArgumentGroupDescription(LocalizableMessage description)
-  {
-    this.generalArgGroup.setDescription(description);
-  }
-
-
-
-  /**
-   * Adds the provided argument to the set of arguments handled by this
-   * parser.
+   * Adds the provided argument to the set of arguments handled by this parser.
    *
    * @param argument
    *          The argument to be added.
    * @throws ArgumentException
-   *           If the provided argument conflicts with another argument
-   *           that has already been defined.
+   *           If the provided argument conflicts with another argument that has
+   *           already been defined.
    */
-  void addArgument(Argument argument) throws ArgumentException
+  void addArgument(final Argument argument) throws ArgumentException
   {
     addArgument(argument, null);
   }
@@ -548,98 +301,27 @@
 
 
   /**
-   * Adds the provided argument to the set of arguments handled by this
-   * parser and puts the arguement in the default group.
-   *
-   * @param argument
-   *          The argument to be added.
-   * @throws ArgumentException
-   *           If the provided argument conflicts with another argument
-   *           that has already been defined.
-   */
-  void addDefaultArgument(Argument argument) throws ArgumentException
-  {
-    addArgument(argument, defaultArgGroup);
-  }
-
-
-
-  /**
-   * Adds the provided argument to the set of arguments handled by this
-   * parser and puts the argument in the LDAP connection group.
-   *
-   * @param argument
-   *          The argument to be added.
-   * @throws ArgumentException
-   *           If the provided argument conflicts with another argument
-   *           that has already been defined.
-   */
-  void addLdapConnectionArgument(Argument argument)
-      throws ArgumentException
-  {
-    addArgument(argument, ldapArgGroup);
-  }
-
-
-
-  /**
-   * Adds the provided argument to the set of arguments handled by this
-   * parser and puts the argument in the input/output group.
-   *
-   * @param argument
-   *          The argument to be added.
-   * @throws ArgumentException
-   *           If the provided argument conflicts with another argument
-   *           that has already been defined.
-   */
-  void addInputOutputArgument(Argument argument)
-      throws ArgumentException
-  {
-    addArgument(argument, ioArgGroup);
-  }
-
-
-
-  /**
-   * Adds the provided argument to the set of arguments handled by this
-   * parser and puts the arguement in the general group.
-   *
-   * @param argument
-   *          The argument to be added.
-   * @throws ArgumentException
-   *           If the provided argument conflicts with another argument
-   *           that has already been defined.
-   */
-  void addGeneralArgument(Argument argument) throws ArgumentException
-  {
-    addArgument(argument, generalArgGroup);
-  }
-
-
-
-  /**
-   * Adds the provided argument to the set of arguments handled by this
-   * parser.
+   * Adds the provided argument to the set of arguments handled by this parser.
    *
    * @param argument
    *          The argument to be added.
    * @param group
    *          The argument group to which the argument belongs.
    * @throws ArgumentException
-   *           If the provided argument conflicts with another argument
-   *           that has already been defined.
+   *           If the provided argument conflicts with another argument that has
+   *           already been defined.
    */
-  void addArgument(Argument argument, ArgumentGroup group)
+  void addArgument(final Argument argument, ArgumentGroup group)
       throws ArgumentException
   {
 
-    Character shortID = argument.getShortIdentifier();
+    final Character shortID = argument.getShortIdentifier();
     if ((shortID != null) && shortIDMap.containsKey(shortID))
     {
-      String conflictingName = shortIDMap.get(shortID).getName();
+      final String conflictingName = shortIDMap.get(shortID).getName();
 
-      LocalizableMessage message = ERR_ARGPARSER_DUPLICATE_SHORT_ID.get(argument
-          .getName(), String.valueOf(shortID), conflictingName);
+      final LocalizableMessage message = ERR_ARGPARSER_DUPLICATE_SHORT_ID.get(
+          argument.getName(), String.valueOf(shortID), conflictingName);
       throw new ArgumentException(message);
     }
 
@@ -651,13 +333,12 @@
         // identifier.
         try
         {
-          versionArgument = new BooleanArgument(
-              OPTION_LONG_PRODUCT_VERSION, null,
-              OPTION_LONG_PRODUCT_VERSION,
+          versionArgument = new BooleanArgument(OPTION_LONG_PRODUCT_VERSION,
+              null, OPTION_LONG_PRODUCT_VERSION,
               INFO_DESCRIPTION_PRODUCT_VERSION.get());
           this.generalArgGroup.addArgument(versionArgument);
         }
-        catch (ArgumentException e)
+        catch (final ArgumentException e)
         {
           // ignore
         }
@@ -673,10 +354,10 @@
       }
       if (longIDMap.containsKey(longID))
       {
-        String conflictingName = longIDMap.get(longID).getName();
+        final String conflictingName = longIDMap.get(longID).getName();
 
-        LocalizableMessage message = ERR_ARGPARSER_DUPLICATE_LONG_ID.get(argument
-            .getName(), argument.getLongIdentifier(), conflictingName);
+        final LocalizableMessage message = ERR_ARGPARSER_DUPLICATE_LONG_ID.get(
+            argument.getName(), argument.getLongIdentifier(), conflictingName);
         throw new ArgumentException(message);
       }
     }
@@ -704,637 +385,87 @@
 
 
   /**
-   * Sets the provided argument as one which will automatically trigger
-   * the output of usage information if it is provided on the command
-   * line and no further argument validation will be performed. Note
-   * that the caller will still need to add this argument to the parser
-   * with the <CODE>addArgument</CODE> method, and the argument should
-   * not be required and should not take a value. Also, the caller will
-   * still need to check for the presence of the usage argument after
-   * calling <CODE>parseArguments</CODE> to know that no further
-   * processing will be required.
+   * Adds the provided argument to the set of arguments handled by this parser
+   * and puts the arguement in the default group.
    *
    * @param argument
-   *          The argument whose presence should automatically trigger
-   *          the display of usage information.
-   */
-  void setUsageArgument(Argument argument)
-  {
-    usageArgument = argument;
-    usageOutputStream = System.out;
-  }
-
-
-
-  /**
-   * Sets the provided argument as one which will automatically trigger
-   * the output of usage information if it is provided on the command
-   * line and no further argument validation will be performed. Note
-   * that the caller will still need to add this argument to the parser
-   * with the <CODE>addArgument</CODE> method, and the argument should
-   * not be required and should not take a value. Also, the caller will
-   * still need to check for the presence of the usage argument after
-   * calling <CODE>parseArguments</CODE> to know that no further
-   * processing will be required.
-   *
-   * @param argument
-   *          The argument whose presence should automatically trigger
-   *          the display of usage information.
-   * @param outputStream
-   *          The output stream to which the usage information should be
-   *          written.
-   */
-  void setUsageArgument(Argument argument, OutputStream outputStream)
-  {
-    usageArgument = argument;
-    usageOutputStream = outputStream;
-  }
-
-
-
-  /**
-   * Sets the provided argument which will be used to identify the file
-   * properties.
-   *
-   * @param argument
-   *          The argument which will be used to identify the file
-   *          properties.
-   */
-  void setFilePropertiesArgument(StringArgument argument)
-  {
-    filePropertiesPathArgument = argument;
-  }
-
-
-
-  /**
-   * Sets the provided argument which will be used to identify the file
-   * properties.
-   *
-   * @param argument
-   *          The argument which will be used to indicate if we have to
-   *          look for properties file.
-   */
-  void setNoPropertiesFileArgument(BooleanArgument argument)
-  {
-    noPropertiesFileArgument = argument;
-  }
-
-
-
-  /**
-   * Parses the provided set of arguments and updates the information
-   * associated with this parser accordingly.
-   *
-   * @param rawArguments
-   *          The raw set of arguments to parse.
+   *          The argument to be added.
    * @throws ArgumentException
-   *           If a problem was encountered while parsing the provided
-   *           arguments.
+   *           If the provided argument conflicts with another argument that has
+   *           already been defined.
    */
-  void parseArguments(String[] rawArguments) throws ArgumentException
+  void addDefaultArgument(final Argument argument) throws ArgumentException
   {
-    parseArguments(rawArguments, null);
+    addArgument(argument, defaultArgGroup);
   }
 
 
 
   /**
-   * Parses the provided set of arguments and updates the information
-   * associated with this parser accordingly. Default values for
-   * unspecified arguments may be read from the specified properties
-   * file.
+   * Adds the provided argument to the set of arguments handled by this parser
+   * and puts the arguement in the general group.
    *
-   * @param rawArguments
-   *          The set of raw arguments to parse.
-   * @param propertiesFile
-   *          The path to the properties file to use to obtain default
-   *          values for unspecified properties.
-   * @param requirePropertiesFile
-   *          Indicates whether the parsing should fail if the provided
-   *          properties file does not exist or is not accessible.
+   * @param argument
+   *          The argument to be added.
    * @throws ArgumentException
-   *           If a problem was encountered while parsing the provided
-   *           arguments or interacting with the properties file.
+   *           If the provided argument conflicts with another argument that has
+   *           already been defined.
    */
-  void parseArguments(String[] rawArguments, String propertiesFile,
-      boolean requirePropertiesFile) throws ArgumentException
+  void addGeneralArgument(final Argument argument) throws ArgumentException
   {
-    this.rawArguments = rawArguments;
-
-    Properties argumentProperties = null;
-
-    try
-    {
-      Properties p = new Properties();
-      FileInputStream fis = new FileInputStream(propertiesFile);
-      p.load(fis);
-      fis.close();
-      argumentProperties = p;
-    }
-    catch (Exception e)
-    {
-      if (requirePropertiesFile)
-      {
-        LocalizableMessage message = ERR_ARGPARSER_CANNOT_READ_PROPERTIES_FILE
-            .get(String.valueOf(propertiesFile), getExceptionMessage(e));
-        throw new ArgumentException(message, e);
-      }
-    }
-
-    parseArguments(rawArguments, argumentProperties);
+    addArgument(argument, generalArgGroup);
   }
 
 
 
   /**
-   * Parses the provided set of arguments and updates the information
-   * associated with this parser accordingly. Default values for
-   * unspecified arguments may be read from the specified properties if
-   * any are provided.
+   * Adds the provided argument to the set of arguments handled by this parser
+   * and puts the argument in the input/output group.
    *
-   * @param rawArguments
-   *          The set of raw arguments to parse.
-   * @param argumentProperties
-   *          A set of properties that may be used to provide default
-   *          values for arguments not included in the given raw
-   *          arguments.
+   * @param argument
+   *          The argument to be added.
    * @throws ArgumentException
-   *           If a problem was encountered while parsing the provided
-   *           arguments.
+   *           If the provided argument conflicts with another argument that has
+   *           already been defined.
    */
-  void parseArguments(String[] rawArguments,
-      Properties argumentProperties) throws ArgumentException
+  void addInputOutputArgument(final Argument argument) throws ArgumentException
   {
-    this.rawArguments = rawArguments;
+    addArgument(argument, ioArgGroup);
+  }
 
-    boolean inTrailingArgs = false;
 
-    int numArguments = rawArguments.length;
-    for (int i = 0; i < numArguments; i++)
-    {
-      String arg = rawArguments[i];
 
-      if (inTrailingArgs)
-      {
-        trailingArguments.add(arg);
-        if ((maxTrailingArguments > 0)
-            && (trailingArguments.size() > maxTrailingArguments))
-        {
-          LocalizableMessage message = ERR_ARGPARSER_TOO_MANY_TRAILING_ARGS
-              .get(maxTrailingArguments);
-          throw new ArgumentException(message);
-        }
+  /**
+   * Adds the provided argument to the set of arguments handled by this parser
+   * and puts the argument in the LDAP connection group.
+   *
+   * @param argument
+   *          The argument to be added.
+   * @throws ArgumentException
+   *           If the provided argument conflicts with another argument that has
+   *           already been defined.
+   */
+  void addLdapConnectionArgument(final Argument argument)
+      throws ArgumentException
+  {
+    addArgument(argument, ldapArgGroup);
+  }
 
-        continue;
-      }
 
-      if (arg.equals("--"))
-      {
-        // This is a special indicator that we have reached the end of
-        // the named
-        // arguments and that everything that follows after this should
-        // be
-        // considered trailing arguments.
-        inTrailingArgs = true;
-      }
-      else if (arg.startsWith("--"))
-      {
-        // This indicates that we are using the long name to reference
-        // the
-        // argument. It may be in any of the following forms:
-        // --name
-        // --name value
-        // --name=value
 
-        String argName = arg.substring(2);
-        String argValue = null;
-        int equalPos = argName.indexOf('=');
-        if (equalPos < 0)
-        {
-          // This is fine. The value is not part of the argument name
-          // token.
-        }
-        else if (equalPos == 0)
-        {
-          // The argument starts with "--=", which is not acceptable.
-          LocalizableMessage message = ERR_ARGPARSER_LONG_ARG_WITHOUT_NAME
-              .get(arg);
-          throw new ArgumentException(message);
-        }
-        else
-        {
-          // The argument is in the form --name=value, so parse them
-          // both out.
-          argValue = argName.substring(equalPos + 1);
-          argName = argName.substring(0, equalPos);
-        }
-
-        // If we're not case-sensitive, then convert the name to
-        // lowercase.
-        String origArgName = argName;
-        if (!longArgumentsCaseSensitive)
-        {
-          argName = toLowerCase(argName);
-        }
-
-        // Get the argument with the specified name.
-        Argument a = longIDMap.get(argName);
-        if (a == null)
-        {
-          if (argName.equals(OPTION_LONG_HELP))
-          {
-            // "--help" will always be interpreted as requesting usage
-            // information.
-            try
-            {
-              getUsage(usageOutputStream);
-            }
-            catch (Exception e)
-            {
-            }
-
-            return;
-          }
-          else if (argName.equals(OPTION_LONG_PRODUCT_VERSION))
-          {
-            // "--version" will always be interpreted as requesting
-            // version
-            // information.
-            usageOrVersionDisplayed = true;
-            versionPresent = true;
-            try
-            {
-              // TODO
-              // DirectoryServer.printVersion(usageOutputStream);
-            }
-            catch (Exception e)
-            {
-            }
-
-            return;
-          }
-          else
-          {
-            // There is no such argument registered.
-            LocalizableMessage message = ERR_ARGPARSER_NO_ARGUMENT_WITH_LONG_ID
-                .get(origArgName);
-            throw new ArgumentException(message);
-          }
-        }
-        else
-        {
-          a.setPresent(true);
-
-          // If this is the usage argument, then immediately stop and
-          // print
-          // usage information.
-          if ((usageArgument != null)
-              && usageArgument.getName().equals(a.getName()))
-          {
-            try
-            {
-              getUsage(usageOutputStream);
-            }
-            catch (Exception e)
-            {
-            }
-
-            return;
-          }
-        }
-
-        // See if the argument takes a value. If so, then make sure one
-        // was
-        // provided. If not, then make sure none was provided.
-        if (a.needsValue())
-        {
-          if (argValue == null)
-          {
-            if ((i + 1) == numArguments)
-            {
-              LocalizableMessage message = ERR_ARGPARSER_NO_VALUE_FOR_ARGUMENT_WITH_LONG_ID
-                  .get(origArgName);
-              throw new ArgumentException(message);
-            }
-
-            argValue = rawArguments[++i];
-          }
-
-          LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
-          if (!a.valueIsAcceptable(argValue, invalidReason))
-          {
-            LocalizableMessage message = ERR_ARGPARSER_VALUE_UNACCEPTABLE_FOR_LONG_ID
-                .get(argValue, origArgName, invalidReason.toString());
-            throw new ArgumentException(message);
-          }
-
-          // If the argument already has a value, then make sure it is
-          // acceptable to have more than one.
-          if (a.hasValue() && (!a.isMultiValued()))
-          {
-            LocalizableMessage message = ERR_ARGPARSER_NOT_MULTIVALUED_FOR_LONG_ID
-                .get(origArgName);
-            throw new ArgumentException(message);
-          }
-
-          a.addValue(argValue);
-        }
-        else
-        {
-          if (argValue != null)
-          {
-            LocalizableMessage message = ERR_ARGPARSER_ARG_FOR_LONG_ID_DOESNT_TAKE_VALUE
-                .get(origArgName);
-            throw new ArgumentException(message);
-          }
-        }
-      }
-      else if (arg.startsWith("-"))
-      {
-        // This indicates that we are using the 1-character name to
-        // reference
-        // the argument. It may be in any of the following forms:
-        // -n
-        // -nvalue
-        // -n value
-        if (arg.equals("-"))
-        {
-          LocalizableMessage message = ERR_ARGPARSER_INVALID_DASH_AS_ARGUMENT
-              .get();
-          throw new ArgumentException(message);
-        }
-
-        char argCharacter = arg.charAt(1);
-        String argValue;
-        if (arg.length() > 2)
-        {
-          argValue = arg.substring(2);
-        }
-        else
-        {
-          argValue = null;
-        }
-
-        // Get the argument with the specified short ID.
-        Argument a = shortIDMap.get(argCharacter);
-        if (a == null)
-        {
-          if (argCharacter == '?')
-          {
-            // "-?" will always be interpreted as requesting usage
-            // information.
-            try
-            {
-              getUsage(usageOutputStream);
-            }
-            catch (Exception e)
-            {
-            }
-
-            return;
-          }
-          else if ((argCharacter == OPTION_SHORT_PRODUCT_VERSION)
-              && (!shortIDMap.containsKey(OPTION_SHORT_PRODUCT_VERSION)))
-          {
-            // "-V" will always be interpreted as requesting
-            // version information except if it's already defined (e.g
-            // in
-            // ldap tools).
-            usageOrVersionDisplayed = true;
-            versionPresent = true;
-            try
-            {
-              // TODO
-              // DirectoryServer.printVersion(usageOutputStream);
-            }
-            catch (Exception e)
-            {
-            }
-            return;
-          }
-          else
-          {
-            // There is no such argument registered.
-            LocalizableMessage message = ERR_ARGPARSER_NO_ARGUMENT_WITH_SHORT_ID
-                .get(String.valueOf(argCharacter));
-            throw new ArgumentException(message);
-          }
-        }
-        else
-        {
-          a.setPresent(true);
-
-          // If this is the usage argument, then immediately stop and
-          // print
-          // usage information.
-          if ((usageArgument != null)
-              && usageArgument.getName().equals(a.getName()))
-          {
-            try
-            {
-              getUsage(usageOutputStream);
-            }
-            catch (Exception e)
-            {
-            }
-
-            return;
-          }
-        }
-
-        // See if the argument takes a value. If so, then make sure one
-        // was
-        // provided. If not, then make sure none was provided.
-        if (a.needsValue())
-        {
-          if (argValue == null)
-          {
-            if ((i + 1) == numArguments)
-            {
-              LocalizableMessage message = ERR_ARGPARSER_NO_VALUE_FOR_ARGUMENT_WITH_SHORT_ID
-                  .get(String.valueOf(argCharacter));
-              throw new ArgumentException(message);
-            }
-
-            argValue = rawArguments[++i];
-          }
-
-          LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
-          if (!a.valueIsAcceptable(argValue, invalidReason))
-          {
-            LocalizableMessage message = ERR_ARGPARSER_VALUE_UNACCEPTABLE_FOR_SHORT_ID
-                .get(argValue, String.valueOf(argCharacter),
-                    invalidReason.toString());
-            throw new ArgumentException(message);
-          }
-
-          // If the argument already has a value, then make sure it is
-          // acceptable to have more than one.
-          if (a.hasValue() && (!a.isMultiValued()))
-          {
-            LocalizableMessage message = ERR_ARGPARSER_NOT_MULTIVALUED_FOR_SHORT_ID
-                .get(String.valueOf(argCharacter));
-            throw new ArgumentException(message);
-          }
-
-          a.addValue(argValue);
-        }
-        else
-        {
-          if (argValue != null)
-          {
-            // If we've gotten here, then it means that we're in a
-            // scenario like
-            // "-abc" where "a" is a valid argument that doesn't take a
-            // value.
-            // However, this could still be valid if all remaining
-            // characters in
-            // the value are also valid argument characters that don't
-            // take
-            // values.
-            int valueLength = argValue.length();
-            for (int j = 0; j < valueLength; j++)
-            {
-              char c = argValue.charAt(j);
-              Argument b = shortIDMap.get(c);
-              if (b == null)
-              {
-                // There is no such argument registered.
-                LocalizableMessage message = ERR_ARGPARSER_NO_ARGUMENT_WITH_SHORT_ID
-                    .get(String.valueOf(argCharacter));
-                throw new ArgumentException(message);
-              }
-              else if (b.needsValue())
-              {
-                // This means we're in a scenario like "-abc" where b is
-                // a
-                // valid argument that takes a value. We don't support
-                // that.
-                LocalizableMessage message = ERR_ARGPARSER_CANT_MIX_ARGS_WITH_VALUES
-                    .get(String.valueOf(argCharacter), argValue, String
-                        .valueOf(c));
-                throw new ArgumentException(message);
-              }
-              else
-              {
-                b.setPresent(true);
-
-                // If this is the usage argument, then immediately stop
-                // and
-                // print usage information.
-                if ((usageArgument != null)
-                    && usageArgument.getName().equals(b.getName()))
-                {
-                  try
-                  {
-                    getUsage(usageOutputStream);
-                  }
-                  catch (Exception e)
-                  {
-                  }
-
-                  return;
-                }
-              }
-            }
-          }
-        }
-      }
-      else if (allowsTrailingArguments)
-      {
-        // It doesn't start with a dash, so it must be a trailing
-        // argument if
-        // that is acceptable.
-        inTrailingArgs = true;
-        trailingArguments.add(arg);
-      }
-      else
-      {
-        // It doesn't start with a dash and we don't allow trailing
-        // arguments,
-        // so this is illegal.
-        LocalizableMessage message = ERR_ARGPARSER_DISALLOWED_TRAILING_ARGUMENT
-            .get(arg);
-        throw new ArgumentException(message);
-      }
-    }
-
-    // If we allow trailing arguments and there is a minimum number,
-    // then make
-    // sure at least that many were provided.
-    if (allowsTrailingArguments && (minTrailingArguments > 0))
-    {
-      if (trailingArguments.size() < minTrailingArguments)
-      {
-        LocalizableMessage message = ERR_ARGPARSER_TOO_FEW_TRAILING_ARGUMENTS
-            .get(minTrailingArguments);
-        throw new ArgumentException(message);
-      }
-    }
-
-    // If we don't have the argumentProperties, try to load a properties
-    // file.
-    if (argumentProperties == null)
-    {
-      argumentProperties = checkExternalProperties();
-    }
-
-    // Iterate through all of the arguments. For any that were not
-    // provided on
-    // the command line, see if there is an alternate default that can
-    // be used.
-    // For cases where there is not, see that argument is required.
-    for (Argument a : argumentList)
-    {
-      if (!a.isPresent())
-      {
-        // See if there is a value in the properties that can be used
-        if ((argumentProperties != null)
-            && (a.getPropertyName() != null))
-        {
-          String value = argumentProperties.getProperty(a
-              .getPropertyName().toLowerCase());
-          LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
-          if (value != null)
-          {
-            Boolean addValue = true;
-            if (!(a instanceof BooleanArgument))
-            {
-              addValue = a.valueIsAcceptable(value, invalidReason);
-            }
-            if (addValue)
-            {
-              a.addValue(value);
-              if (a.needsValue())
-              {
-                a.setPresent(true);
-              }
-              a.setValueSetByProperty(true);
-            }
-          }
-        }
-      }
-
-      if ((!a.isPresent()) && a.needsValue())
-      {
-        // See if the argument defines a default.
-        if (a.getDefaultValue() != null)
-        {
-          a.addValue(a.getDefaultValue());
-        }
-
-        // If there is still no value and the argument is required, then
-        // that's
-        // a problem.
-        if ((!a.hasValue()) && a.isRequired())
-        {
-          LocalizableMessage message = ERR_ARGPARSER_NO_VALUE_FOR_REQUIRED_ARG
-              .get(a.getName());
-          throw new ArgumentException(message);
-        }
-      }
-    }
+  /**
+   * Indicates whether this parser will allow unnamed trailing arguments. These
+   * will be arguments at the end of the list that are not preceded by either a
+   * long or short identifier and will need to be manually parsed by the
+   * application using this parser. Note that once an unnamed trailing argument
+   * has been identified, all remaining arguments will be classified as such.
+   *
+   * @return <CODE>true</CODE> if this parser allows unnamed trailing arguments,
+   *         or <CODE>false</CODE> if it does not.
+   */
+  boolean allowsTrailingArguments()
+  {
+    return allowsTrailingArguments;
   }
 
 
@@ -1372,16 +503,16 @@
     else
     {
       // Check in "user home"/.opends directory
-      String userDir = System.getProperty("user.home");
+      final String userDir = System.getProperty("user.home");
       propertiesFilePath = findPropertiesFile(userDir + File.separator
           + DEFAULT_OPENDS_CONFIG_DIR);
 
       // TODO
       /*
-       * if (propertiesFilePath == null) { // check
-       * "Opends instance"/config directory String instanceDir =
-       * DirectoryServer.getInstanceRoot(); propertiesFilePath =
-       * findPropertiesFile(instanceDir+ File.separator + "config"); }
+       * if (propertiesFilePath == null) { // check "Opends instance"/config
+       * directory String instanceDir = DirectoryServer.getInstanceRoot();
+       * propertiesFilePath = findPropertiesFile(instanceDir+ File.separator +
+       * "config"); }
        */
     }
 
@@ -1392,18 +523,18 @@
     }
 
     // We have a location for the properties file.
-    Properties argumentProperties = new Properties();
-    String scriptName = System.getProperty(Utils.PROPERTY_SCRIPT_NAME);
+    final Properties argumentProperties = new Properties();
+    final String scriptName = System.getProperty(Utils.PROPERTY_SCRIPT_NAME);
     try
     {
-      Properties p = new Properties();
-      FileInputStream fis = new FileInputStream(propertiesFilePath);
+      final Properties p = new Properties();
+      final FileInputStream fis = new FileInputStream(propertiesFilePath);
       p.load(fis);
       fis.close();
 
-      for (Enumeration<?> e = p.propertyNames(); e.hasMoreElements();)
+      for (final Enumeration<?> e = p.propertyNames(); e.hasMoreElements();)
       {
-        String currentPropertyName = (String) e.nextElement();
+        final String currentPropertyName = (String) e.nextElement();
         String propertyName = currentPropertyName;
 
         // Property name form <script name>.<property name> has the
@@ -1412,8 +543,8 @@
         {
           if (currentPropertyName.startsWith(scriptName))
           {
-            propertyName = currentPropertyName.substring(scriptName
-                .length() + 1);
+            propertyName = currentPropertyName
+                .substring(scriptName.length() + 1);
           }
           else
           {
@@ -1427,10 +558,10 @@
             .getProperty(currentPropertyName));
       }
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
-      LocalizableMessage message = ERR_ARGPARSER_CANNOT_READ_PROPERTIES_FILE.get(
-          String.valueOf(propertiesFilePath), getExceptionMessage(e));
+      final LocalizableMessage message = ERR_ARGPARSER_CANNOT_READ_PROPERTIES_FILE
+          .get(String.valueOf(propertiesFilePath), getExceptionMessage(e));
       throw new ArgumentException(message, e);
     }
     return argumentProperties;
@@ -1439,58 +570,275 @@
 
 
   /**
-   * Get the absolute path of the properties file.
+   * Retrieves the argument with the specified name.
    *
-   * @param directory
-   *          The location in which we should look for properties file
-   * @return The absolute path of the properties file or null
+   * @param name
+   *          The name of the argument to retrieve.
+   * @return The argument with the specified name, or <CODE>null</CODE> if there
+   *         is no such argument.
    */
-  private String findPropertiesFile(String directory)
+  Argument getArgument(final String name)
   {
-    // Look for the tools properties file
-    File f = new File(directory, DEFAULT_OPENDS_PROPERTIES_FILE_NAME
-        + DEFAULT_OPENDS_PROPERTIES_FILE_EXTENSION);
-    if (f.exists() && f.canRead())
-    {
-      return f.getAbsolutePath();
-    }
-    else
-    {
-      return null;
-    }
+    return argumentMap.get(name);
   }
 
 
 
   /**
-   * Appends usage information based on the defined arguments to the
-   * provided buffer.
+   * Retrieves the argument with the specified long identifier.
+   *
+   * @param longID
+   *          The long identifier of the argument to retrieve.
+   * @return The argument with the specified long identifier, or
+   *         <CODE>null</CODE> if there is no such argument.
+   */
+  Argument getArgumentForLongID(final String longID)
+  {
+    return longIDMap.get(longID);
+  }
+
+
+
+  /**
+   * Retrieves the argument with the specified short identifier.
+   *
+   * @param shortID
+   *          The short ID for the argument to retrieve.
+   * @return The argument with the specified short identifier, or
+   *         <CODE>null</CODE> if there is no such argument.
+   */
+  Argument getArgumentForShortID(final Character shortID)
+  {
+    return shortIDMap.get(shortID);
+  }
+
+
+
+  /**
+   * Retrieves the list of all arguments that have been defined for this
+   * argument parser.
+   *
+   * @return The list of all arguments that have been defined for this argument
+   *         parser.
+   */
+  LinkedList<Argument> getArgumentList()
+  {
+    return argumentList;
+  }
+
+
+
+  /**
+   * Retrieves the set of arguments mapped by the long identifier that may be
+   * used to reference them. Note that arguments that do not have a long
+   * identifier will not be present in this list.
+   *
+   * @return The set of arguments mapped by the long identifier that may be used
+   *         to reference them.
+   */
+  HashMap<String, Argument> getArgumentsByLongID()
+  {
+    return longIDMap;
+  }
+
+
+
+  /**
+   * Retrieves the set of arguments mapped by the short identifier that may be
+   * used to reference them. Note that arguments that do not have a short
+   * identifier will not be present in this list.
+   *
+   * @return The set of arguments mapped by the short identifier that may be
+   *         used to reference them.
+   */
+  HashMap<Character, Argument> getArgumentsByShortID()
+  {
+    return shortIDMap;
+  }
+
+
+
+  /**
+   * Retrieves the fully-qualified name of the Java class that should be invoked
+   * to launch the program with which this argument parser is associated.
+   *
+   * @return The fully-qualified name of the Java class that should be invoked
+   *         to launch the program with which this argument parser is
+   *         associated.
+   */
+  String getMainClassName()
+  {
+    return mainClassName;
+  }
+
+
+
+  /**
+   * Retrieves the maximum number of unnamed trailing arguments that may be
+   * provided.
+   *
+   * @return The maximum number of unnamed trailing arguments that may be
+   *         provided, or a value less than or equal to zero if no maximum will
+   *         be enforced.
+   */
+  int getMaxTrailingArguments()
+  {
+    return maxTrailingArguments;
+  }
+
+
+
+  /**
+   * Retrieves the minimum number of unnamed trailing arguments that must be
+   * provided.
+   *
+   * @return The minimum number of unnamed trailing arguments that must be
+   *         provided, or a value less than or equal to zero if no minimum will
+   *         be enforced.
+   */
+  int getMinTrailingArguments()
+  {
+    return minTrailingArguments;
+  }
+
+
+
+  /**
+   * Retrieves the raw set of arguments that were provided.
+   *
+   * @return The raw set of arguments that were provided, or <CODE>null</CODE>
+   *         if the argument list has not yet been parsed.
+   */
+  String[] getRawArguments()
+  {
+    return rawArguments;
+  }
+
+
+
+  /**
+   * Given an argument, returns an appropriate group. Arguments may be part of
+   * one of the special groups or the default group.
+   *
+   * @param argument
+   *          for which a group is requested
+   * @return argument group appropriate for <code>argument</code>
+   */
+  ArgumentGroup getStandardGroup(final Argument argument)
+  {
+    ArgumentGroup group;
+    if (isInputOutputArgument(argument))
+    {
+      group = ioArgGroup;
+    }
+    else if (isGeneralArgument(argument))
+    {
+      group = generalArgGroup;
+    }
+    else if (isLdapConnectionArgument(argument))
+    {
+      group = ldapArgGroup;
+    }
+    else
+    {
+      group = defaultArgGroup;
+    }
+    return group;
+  }
+
+
+
+  /**
+   * Retrieves a human-readable description for this tool, which should be
+   * included at the top of the command-line usage information.
+   *
+   * @return A human-readable description for this tool, or {@code null} if none
+   *         is available.
+   */
+  LocalizableMessage getToolDescription()
+  {
+    return toolDescription;
+  }
+
+
+
+  /**
+   * Retrieves the set of unnamed trailing arguments that were provided on the
+   * command line.
+   *
+   * @return The set of unnamed trailing arguments that were provided on the
+   *         command line.
+   */
+  ArrayList<String> getTrailingArguments()
+  {
+    return trailingArguments;
+  }
+
+
+
+  /**
+   * Retrieves a string containing usage information based on the defined
+   * arguments.
+   *
+   * @return A string containing usage information based on the defined
+   *         arguments.
+   */
+  String getUsage()
+  {
+    final StringBuilder buffer = new StringBuilder();
+    getUsage(buffer);
+
+    return buffer.toString();
+  }
+
+
+
+  /**
+   * Writes usage information based on the defined arguments to the provided
+   * output stream.
+   *
+   * @param outputStream
+   *          The output stream to which the usage information should be
+   *          written.
+   * @throws IOException
+   *           If a problem occurs while attempting to write the usage
+   *           information to the provided output stream.
+   */
+  void getUsage(final OutputStream outputStream) throws IOException
+  {
+    final StringBuilder buffer = new StringBuilder();
+    getUsage(buffer);
+
+    outputStream.write(getBytes(buffer.toString()));
+  }
+
+
+
+  /**
+   * Appends usage information based on the defined arguments to the provided
+   * buffer.
    *
    * @param buffer
-   *          The buffer to which the usage information should be
-   *          appended.
+   *          The buffer to which the usage information should be appended.
    */
-  void getUsage(StringBuilder buffer)
+  void getUsage(final StringBuilder buffer)
   {
     usageOrVersionDisplayed = true;
     if ((toolDescription != null) && (toolDescription.length() > 0))
     {
-      buffer
-          .append(wrapText(toolDescription.toString(), MAX_LENGTH - 1));
+      buffer.append(wrapText(toolDescription.toString(), MAX_LENGTH - 1));
       buffer.append(EOL);
       buffer.append(EOL);
     }
 
-    String scriptName = System.getProperty(PROPERTY_SCRIPT_NAME);
+    final String scriptName = System.getProperty(PROPERTY_SCRIPT_NAME);
     if ((scriptName == null) || (scriptName.length() == 0))
     {
-      buffer.append(INFO_ARGPARSER_USAGE_JAVA_CLASSNAME
-          .get(mainClassName));
+      buffer.append(INFO_ARGPARSER_USAGE_JAVA_CLASSNAME.get(mainClassName));
     }
     else
     {
-      buffer.append(INFO_ARGPARSER_USAGE_JAVA_SCRIPTNAME
-          .get(scriptName));
+      buffer.append(INFO_ARGPARSER_USAGE_JAVA_SCRIPTNAME.get(scriptName));
     }
 
     if (allowsTrailingArguments)
@@ -1512,13 +860,13 @@
 
     Argument helpArgument = null;
 
-    boolean printHeaders = printUsageGroupHeaders();
-    for (ArgumentGroup argGroup : argumentGroups)
+    final boolean printHeaders = printUsageGroupHeaders();
+    for (final ArgumentGroup argGroup : argumentGroups)
     {
       if (argGroup.containsArguments() && printHeaders)
       {
         // Print the groups description if any
-        LocalizableMessage groupDesc = argGroup.getDescription();
+        final LocalizableMessage groupDesc = argGroup.getDescription();
         if (groupDesc != null && !LocalizableMessage.EMPTY.equals(groupDesc))
         {
           buffer.append(EOL);
@@ -1528,7 +876,7 @@
         }
       }
 
-      for (Argument a : argGroup.getArguments())
+      for (final Argument a : argGroup.getArguments())
       {
         // If this argument is hidden, then skip it.
         if (a.isHidden())
@@ -1561,15 +909,15 @@
 
 
   /**
-   * Retrieves a message containing usage information based on the
-   * defined arguments.
+   * Retrieves a message containing usage information based on the defined
+   * arguments.
    *
    * @return A string containing usage information based on the defined
    *         arguments.
    */
   LocalizableMessage getUsageMessage()
   {
-    StringBuilder buffer = new StringBuilder();
+    final StringBuilder buffer = new StringBuilder();
     getUsage(buffer);
 
     // TODO: rework getUsage(OutputStream) to work with messages
@@ -1580,50 +928,751 @@
 
 
   /**
-   * Retrieves a string containing usage information based on the
-   * defined arguments.
+   * Returns whether the usage argument was provided or not. This method should
+   * be called after a call to parseArguments.
    *
-   * @return A string containing usage information based on the defined
-   *         arguments.
+   * @return <CODE>true</CODE> if the usage argument was provided and
+   *         <CODE>false</CODE> otherwise.
    */
-  String getUsage()
+  boolean isUsageArgumentPresent()
   {
-    StringBuilder buffer = new StringBuilder();
-    getUsage(buffer);
-
-    return buffer.toString();
+    boolean isUsageArgumentPresent = false;
+    if (usageArgument != null)
+    {
+      isUsageArgumentPresent = usageArgument.isPresent();
+    }
+    return isUsageArgumentPresent;
   }
 
 
 
   /**
-   * Writes usage information based on the defined arguments to the
-   * provided output stream.
+   * Returns whether the version argument was provided or not. This method
+   * should be called after a call to parseArguments.
    *
+   * @return <CODE>true</CODE> if the version argument was provided and
+   *         <CODE>false</CODE> otherwise.
+   */
+  boolean isVersionArgumentPresent()
+  {
+    return versionPresent;
+  }
+
+
+
+  /**
+   * Parses the provided set of arguments and updates the information associated
+   * with this parser accordingly.
+   *
+   * @param rawArguments
+   *          The raw set of arguments to parse.
+   * @throws ArgumentException
+   *           If a problem was encountered while parsing the provided
+   *           arguments.
+   */
+  void parseArguments(final String[] rawArguments) throws ArgumentException
+  {
+    parseArguments(rawArguments, null);
+  }
+
+
+
+  /**
+   * Parses the provided set of arguments and updates the information associated
+   * with this parser accordingly. Default values for unspecified arguments may
+   * be read from the specified properties if any are provided.
+   *
+   * @param rawArguments
+   *          The set of raw arguments to parse.
+   * @param argumentProperties
+   *          A set of properties that may be used to provide default values for
+   *          arguments not included in the given raw arguments.
+   * @throws ArgumentException
+   *           If a problem was encountered while parsing the provided
+   *           arguments.
+   */
+  void parseArguments(final String[] rawArguments, Properties argumentProperties)
+      throws ArgumentException
+  {
+    this.rawArguments = rawArguments;
+
+    boolean inTrailingArgs = false;
+
+    final int numArguments = rawArguments.length;
+    for (int i = 0; i < numArguments; i++)
+    {
+      final String arg = rawArguments[i];
+
+      if (inTrailingArgs)
+      {
+        trailingArguments.add(arg);
+        if ((maxTrailingArguments > 0)
+            && (trailingArguments.size() > maxTrailingArguments))
+        {
+          final LocalizableMessage message = ERR_ARGPARSER_TOO_MANY_TRAILING_ARGS
+              .get(maxTrailingArguments);
+          throw new ArgumentException(message);
+        }
+
+        continue;
+      }
+
+      if (arg.equals("--"))
+      {
+        // This is a special indicator that we have reached the end of
+        // the named
+        // arguments and that everything that follows after this should
+        // be
+        // considered trailing arguments.
+        inTrailingArgs = true;
+      }
+      else if (arg.startsWith("--"))
+      {
+        // This indicates that we are using the long name to reference
+        // the
+        // argument. It may be in any of the following forms:
+        // --name
+        // --name value
+        // --name=value
+
+        String argName = arg.substring(2);
+        String argValue = null;
+        final int equalPos = argName.indexOf('=');
+        if (equalPos < 0)
+        {
+          // This is fine. The value is not part of the argument name
+          // token.
+        }
+        else if (equalPos == 0)
+        {
+          // The argument starts with "--=", which is not acceptable.
+          final LocalizableMessage message = ERR_ARGPARSER_LONG_ARG_WITHOUT_NAME
+              .get(arg);
+          throw new ArgumentException(message);
+        }
+        else
+        {
+          // The argument is in the form --name=value, so parse them
+          // both out.
+          argValue = argName.substring(equalPos + 1);
+          argName = argName.substring(0, equalPos);
+        }
+
+        // If we're not case-sensitive, then convert the name to
+        // lowercase.
+        final String origArgName = argName;
+        if (!longArgumentsCaseSensitive)
+        {
+          argName = toLowerCase(argName);
+        }
+
+        // Get the argument with the specified name.
+        final Argument a = longIDMap.get(argName);
+        if (a == null)
+        {
+          if (argName.equals(OPTION_LONG_HELP))
+          {
+            // "--help" will always be interpreted as requesting usage
+            // information.
+            try
+            {
+              getUsage(usageOutputStream);
+            }
+            catch (final Exception e)
+            {
+            }
+
+            return;
+          }
+          else if (argName.equals(OPTION_LONG_PRODUCT_VERSION))
+          {
+            // "--version" will always be interpreted as requesting
+            // version
+            // information.
+            usageOrVersionDisplayed = true;
+            versionPresent = true;
+            try
+            {
+              // TODO
+              // DirectoryServer.printVersion(usageOutputStream);
+            }
+            catch (final Exception e)
+            {
+            }
+
+            return;
+          }
+          else
+          {
+            // There is no such argument registered.
+            final LocalizableMessage message = ERR_ARGPARSER_NO_ARGUMENT_WITH_LONG_ID
+                .get(origArgName);
+            throw new ArgumentException(message);
+          }
+        }
+        else
+        {
+          a.setPresent(true);
+
+          // If this is the usage argument, then immediately stop and
+          // print
+          // usage information.
+          if ((usageArgument != null)
+              && usageArgument.getName().equals(a.getName()))
+          {
+            try
+            {
+              getUsage(usageOutputStream);
+            }
+            catch (final Exception e)
+            {
+            }
+
+            return;
+          }
+        }
+
+        // See if the argument takes a value. If so, then make sure one
+        // was
+        // provided. If not, then make sure none was provided.
+        if (a.needsValue())
+        {
+          if (argValue == null)
+          {
+            if ((i + 1) == numArguments)
+            {
+              final LocalizableMessage message = ERR_ARGPARSER_NO_VALUE_FOR_ARGUMENT_WITH_LONG_ID
+                  .get(origArgName);
+              throw new ArgumentException(message);
+            }
+
+            argValue = rawArguments[++i];
+          }
+
+          final LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
+          if (!a.valueIsAcceptable(argValue, invalidReason))
+          {
+            final LocalizableMessage message = ERR_ARGPARSER_VALUE_UNACCEPTABLE_FOR_LONG_ID
+                .get(argValue, origArgName, invalidReason.toString());
+            throw new ArgumentException(message);
+          }
+
+          // If the argument already has a value, then make sure it is
+          // acceptable to have more than one.
+          if (a.hasValue() && (!a.isMultiValued()))
+          {
+            final LocalizableMessage message = ERR_ARGPARSER_NOT_MULTIVALUED_FOR_LONG_ID
+                .get(origArgName);
+            throw new ArgumentException(message);
+          }
+
+          a.addValue(argValue);
+        }
+        else
+        {
+          if (argValue != null)
+          {
+            final LocalizableMessage message = ERR_ARGPARSER_ARG_FOR_LONG_ID_DOESNT_TAKE_VALUE
+                .get(origArgName);
+            throw new ArgumentException(message);
+          }
+        }
+      }
+      else if (arg.startsWith("-"))
+      {
+        // This indicates that we are using the 1-character name to
+        // reference
+        // the argument. It may be in any of the following forms:
+        // -n
+        // -nvalue
+        // -n value
+        if (arg.equals("-"))
+        {
+          final LocalizableMessage message = ERR_ARGPARSER_INVALID_DASH_AS_ARGUMENT
+              .get();
+          throw new ArgumentException(message);
+        }
+
+        final char argCharacter = arg.charAt(1);
+        String argValue;
+        if (arg.length() > 2)
+        {
+          argValue = arg.substring(2);
+        }
+        else
+        {
+          argValue = null;
+        }
+
+        // Get the argument with the specified short ID.
+        final Argument a = shortIDMap.get(argCharacter);
+        if (a == null)
+        {
+          if (argCharacter == '?')
+          {
+            // "-?" will always be interpreted as requesting usage
+            // information.
+            try
+            {
+              getUsage(usageOutputStream);
+            }
+            catch (final Exception e)
+            {
+            }
+
+            return;
+          }
+          else if ((argCharacter == OPTION_SHORT_PRODUCT_VERSION)
+              && (!shortIDMap.containsKey(OPTION_SHORT_PRODUCT_VERSION)))
+          {
+            // "-V" will always be interpreted as requesting
+            // version information except if it's already defined (e.g
+            // in
+            // ldap tools).
+            usageOrVersionDisplayed = true;
+            versionPresent = true;
+            try
+            {
+              // TODO
+              // DirectoryServer.printVersion(usageOutputStream);
+            }
+            catch (final Exception e)
+            {
+            }
+            return;
+          }
+          else
+          {
+            // There is no such argument registered.
+            final LocalizableMessage message = ERR_ARGPARSER_NO_ARGUMENT_WITH_SHORT_ID
+                .get(String.valueOf(argCharacter));
+            throw new ArgumentException(message);
+          }
+        }
+        else
+        {
+          a.setPresent(true);
+
+          // If this is the usage argument, then immediately stop and
+          // print
+          // usage information.
+          if ((usageArgument != null)
+              && usageArgument.getName().equals(a.getName()))
+          {
+            try
+            {
+              getUsage(usageOutputStream);
+            }
+            catch (final Exception e)
+            {
+            }
+
+            return;
+          }
+        }
+
+        // See if the argument takes a value. If so, then make sure one
+        // was
+        // provided. If not, then make sure none was provided.
+        if (a.needsValue())
+        {
+          if (argValue == null)
+          {
+            if ((i + 1) == numArguments)
+            {
+              final LocalizableMessage message = ERR_ARGPARSER_NO_VALUE_FOR_ARGUMENT_WITH_SHORT_ID
+                  .get(String.valueOf(argCharacter));
+              throw new ArgumentException(message);
+            }
+
+            argValue = rawArguments[++i];
+          }
+
+          final LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
+          if (!a.valueIsAcceptable(argValue, invalidReason))
+          {
+            final LocalizableMessage message = ERR_ARGPARSER_VALUE_UNACCEPTABLE_FOR_SHORT_ID
+                .get(argValue, String.valueOf(argCharacter), invalidReason
+                    .toString());
+            throw new ArgumentException(message);
+          }
+
+          // If the argument already has a value, then make sure it is
+          // acceptable to have more than one.
+          if (a.hasValue() && (!a.isMultiValued()))
+          {
+            final LocalizableMessage message = ERR_ARGPARSER_NOT_MULTIVALUED_FOR_SHORT_ID
+                .get(String.valueOf(argCharacter));
+            throw new ArgumentException(message);
+          }
+
+          a.addValue(argValue);
+        }
+        else
+        {
+          if (argValue != null)
+          {
+            // If we've gotten here, then it means that we're in a
+            // scenario like
+            // "-abc" where "a" is a valid argument that doesn't take a
+            // value.
+            // However, this could still be valid if all remaining
+            // characters in
+            // the value are also valid argument characters that don't
+            // take
+            // values.
+            final int valueLength = argValue.length();
+            for (int j = 0; j < valueLength; j++)
+            {
+              final char c = argValue.charAt(j);
+              final Argument b = shortIDMap.get(c);
+              if (b == null)
+              {
+                // There is no such argument registered.
+                final LocalizableMessage message = ERR_ARGPARSER_NO_ARGUMENT_WITH_SHORT_ID
+                    .get(String.valueOf(argCharacter));
+                throw new ArgumentException(message);
+              }
+              else if (b.needsValue())
+              {
+                // This means we're in a scenario like "-abc" where b is
+                // a
+                // valid argument that takes a value. We don't support
+                // that.
+                final LocalizableMessage message = ERR_ARGPARSER_CANT_MIX_ARGS_WITH_VALUES
+                    .get(String.valueOf(argCharacter), argValue, String
+                        .valueOf(c));
+                throw new ArgumentException(message);
+              }
+              else
+              {
+                b.setPresent(true);
+
+                // If this is the usage argument, then immediately stop
+                // and
+                // print usage information.
+                if ((usageArgument != null)
+                    && usageArgument.getName().equals(b.getName()))
+                {
+                  try
+                  {
+                    getUsage(usageOutputStream);
+                  }
+                  catch (final Exception e)
+                  {
+                  }
+
+                  return;
+                }
+              }
+            }
+          }
+        }
+      }
+      else if (allowsTrailingArguments)
+      {
+        // It doesn't start with a dash, so it must be a trailing
+        // argument if
+        // that is acceptable.
+        inTrailingArgs = true;
+        trailingArguments.add(arg);
+      }
+      else
+      {
+        // It doesn't start with a dash and we don't allow trailing
+        // arguments,
+        // so this is illegal.
+        final LocalizableMessage message = ERR_ARGPARSER_DISALLOWED_TRAILING_ARGUMENT
+            .get(arg);
+        throw new ArgumentException(message);
+      }
+    }
+
+    // If we allow trailing arguments and there is a minimum number,
+    // then make
+    // sure at least that many were provided.
+    if (allowsTrailingArguments && (minTrailingArguments > 0))
+    {
+      if (trailingArguments.size() < minTrailingArguments)
+      {
+        final LocalizableMessage message = ERR_ARGPARSER_TOO_FEW_TRAILING_ARGUMENTS
+            .get(minTrailingArguments);
+        throw new ArgumentException(message);
+      }
+    }
+
+    // If we don't have the argumentProperties, try to load a properties
+    // file.
+    if (argumentProperties == null)
+    {
+      argumentProperties = checkExternalProperties();
+    }
+
+    // Iterate through all of the arguments. For any that were not
+    // provided on
+    // the command line, see if there is an alternate default that can
+    // be used.
+    // For cases where there is not, see that argument is required.
+    for (final Argument a : argumentList)
+    {
+      if (!a.isPresent())
+      {
+        // See if there is a value in the properties that can be used
+        if ((argumentProperties != null) && (a.getPropertyName() != null))
+        {
+          final String value = argumentProperties.getProperty(a
+              .getPropertyName().toLowerCase());
+          final LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder();
+          if (value != null)
+          {
+            Boolean addValue = true;
+            if (!(a instanceof BooleanArgument))
+            {
+              addValue = a.valueIsAcceptable(value, invalidReason);
+            }
+            if (addValue)
+            {
+              a.addValue(value);
+              if (a.needsValue())
+              {
+                a.setPresent(true);
+              }
+              a.setValueSetByProperty(true);
+            }
+          }
+        }
+      }
+
+      if ((!a.isPresent()) && a.needsValue())
+      {
+        // See if the argument defines a default.
+        if (a.getDefaultValue() != null)
+        {
+          a.addValue(a.getDefaultValue());
+        }
+
+        // If there is still no value and the argument is required, then
+        // that's
+        // a problem.
+        if ((!a.hasValue()) && a.isRequired())
+        {
+          final LocalizableMessage message = ERR_ARGPARSER_NO_VALUE_FOR_REQUIRED_ARG
+              .get(a.getName());
+          throw new ArgumentException(message);
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * Parses the provided set of arguments and updates the information associated
+   * with this parser accordingly. Default values for unspecified arguments may
+   * be read from the specified properties file.
+   *
+   * @param rawArguments
+   *          The set of raw arguments to parse.
+   * @param propertiesFile
+   *          The path to the properties file to use to obtain default values
+   *          for unspecified properties.
+   * @param requirePropertiesFile
+   *          Indicates whether the parsing should fail if the provided
+   *          properties file does not exist or is not accessible.
+   * @throws ArgumentException
+   *           If a problem was encountered while parsing the provided arguments
+   *           or interacting with the properties file.
+   */
+  void parseArguments(final String[] rawArguments, final String propertiesFile,
+      final boolean requirePropertiesFile) throws ArgumentException
+  {
+    this.rawArguments = rawArguments;
+
+    Properties argumentProperties = null;
+
+    try
+    {
+      final Properties p = new Properties();
+      final FileInputStream fis = new FileInputStream(propertiesFile);
+      p.load(fis);
+      fis.close();
+      argumentProperties = p;
+    }
+    catch (final Exception e)
+    {
+      if (requirePropertiesFile)
+      {
+        final LocalizableMessage message = ERR_ARGPARSER_CANNOT_READ_PROPERTIES_FILE
+            .get(String.valueOf(propertiesFile), getExceptionMessage(e));
+        throw new ArgumentException(message, e);
+      }
+    }
+
+    parseArguments(rawArguments, argumentProperties);
+  }
+
+
+
+  /**
+   * Indicates whether or not argument group description headers should be
+   * printed.
+   *
+   * @return boolean where true means print the descriptions
+   */
+  boolean printUsageGroupHeaders()
+  {
+    // If there is only a single group then we won't print them.
+    int groupsContainingArgs = 0;
+    for (final ArgumentGroup argGroup : argumentGroups)
+    {
+      if (argGroup.containsNonHiddenArguments())
+      {
+        groupsContainingArgs++;
+      }
+    }
+    return groupsContainingArgs > 1;
+  }
+
+
+
+  /**
+   * Sets the usage group description for the default argument group.
+   *
+   * @param description
+   *          for the default group
+   */
+  void setDefaultArgumentGroupDescription(final LocalizableMessage description)
+  {
+    this.defaultArgGroup.setDescription(description);
+  }
+
+
+
+  /**
+   * Sets the provided argument which will be used to identify the file
+   * properties.
+   *
+   * @param argument
+   *          The argument which will be used to identify the file properties.
+   */
+  void setFilePropertiesArgument(final StringArgument argument)
+  {
+    filePropertiesPathArgument = argument;
+  }
+
+
+
+  /**
+   * Sets the usage group description for the general argument group.
+   *
+   * @param description
+   *          for the general group
+   */
+  void setGeneralArgumentGroupDescription(final LocalizableMessage description)
+  {
+    this.generalArgGroup.setDescription(description);
+  }
+
+
+
+  /**
+   * Sets the usage group description for the input/output argument group.
+   *
+   * @param description
+   *          for the input/output group
+   */
+  void setInputOutputArgumentGroupDescription(
+      final LocalizableMessage description)
+  {
+    this.ioArgGroup.setDescription(description);
+  }
+
+
+
+  /**
+   * Sets the usage group description for the LDAP argument group.
+   *
+   * @param description
+   *          for the LDAP group
+   */
+  void setLdapArgumentGroupDescription(final LocalizableMessage description)
+  {
+    this.ldapArgGroup.setDescription(description);
+  }
+
+
+
+  /**
+   * Sets the provided argument which will be used to identify the file
+   * properties.
+   *
+   * @param argument
+   *          The argument which will be used to indicate if we have to look for
+   *          properties file.
+   */
+  void setNoPropertiesFileArgument(final BooleanArgument argument)
+  {
+    noPropertiesFileArgument = argument;
+  }
+
+
+
+  /**
+   * Sets the provided argument as one which will automatically trigger the
+   * output of usage information if it is provided on the command line and no
+   * further argument validation will be performed. Note that the caller will
+   * still need to add this argument to the parser with the
+   * <CODE>addArgument</CODE> method, and the argument should not be required
+   * and should not take a value. Also, the caller will still need to check for
+   * the presence of the usage argument after calling
+   * <CODE>parseArguments</CODE> to know that no further processing will be
+   * required.
+   *
+   * @param argument
+   *          The argument whose presence should automatically trigger the
+   *          display of usage information.
+   */
+  void setUsageArgument(final Argument argument)
+  {
+    usageArgument = argument;
+    usageOutputStream = System.out;
+  }
+
+
+
+  /**
+   * Sets the provided argument as one which will automatically trigger the
+   * output of usage information if it is provided on the command line and no
+   * further argument validation will be performed. Note that the caller will
+   * still need to add this argument to the parser with the
+   * <CODE>addArgument</CODE> method, and the argument should not be required
+   * and should not take a value. Also, the caller will still need to check for
+   * the presence of the usage argument after calling
+   * <CODE>parseArguments</CODE> to know that no further processing will be
+   * required.
+   *
+   * @param argument
+   *          The argument whose presence should automatically trigger the
+   *          display of usage information.
    * @param outputStream
    *          The output stream to which the usage information should be
    *          written.
-   * @throws IOException
-   *           If a problem occurs while attempting to write the usage
-   *           information to the provided output stream.
    */
-  void getUsage(OutputStream outputStream) throws IOException
+  void setUsageArgument(final Argument argument, final OutputStream outputStream)
   {
-    StringBuilder buffer = new StringBuilder();
-    getUsage(buffer);
-
-    outputStream.write(getBytes(buffer.toString()));
+    usageArgument = argument;
+    usageOutputStream = outputStream;
   }
 
 
 
   /**
-   * Indicates whether the version or the usage information has been
-   * displayed to the end user either by an explicit argument like "-H"
-   * or "--help", or by a built-in argument like "-?".
+   * Indicates whether the version or the usage information has been displayed
+   * to the end user either by an explicit argument like "-H" or "--help", or by
+   * a built-in argument like "-?".
    *
-   * @return {@code true} if the usage information has been displayed,
-   *         or {@code false} if not.
+   * @return {@code true} if the usage information has been displayed, or
+   *         {@code false} if not.
    */
   boolean usageOrVersionDisplayed()
   {
@@ -1633,25 +1682,139 @@
 
 
   /**
+   * Get the absolute path of the properties file.
+   *
+   * @param directory
+   *          The location in which we should look for properties file
+   * @return The absolute path of the properties file or null
+   */
+  private String findPropertiesFile(final String directory)
+  {
+    // Look for the tools properties file
+    final File f = new File(directory, DEFAULT_OPENDS_PROPERTIES_FILE_NAME
+        + DEFAULT_OPENDS_PROPERTIES_FILE_EXTENSION);
+    if (f.exists() && f.canRead())
+    {
+      return f.getAbsolutePath();
+    }
+    else
+    {
+      return null;
+    }
+  }
+
+
+
+  private void initGroups()
+  {
+    this.argumentGroups = new TreeSet<ArgumentGroup>();
+    this.argumentGroups.add(defaultArgGroup);
+    this.argumentGroups.add(ldapArgGroup);
+    this.argumentGroups.add(generalArgGroup);
+    this.argumentGroups.add(ioArgGroup);
+
+    try
+    {
+      versionArgument = new BooleanArgument(OPTION_LONG_PRODUCT_VERSION,
+          OPTION_SHORT_PRODUCT_VERSION, OPTION_LONG_PRODUCT_VERSION,
+          INFO_DESCRIPTION_PRODUCT_VERSION.get());
+      this.generalArgGroup.addArgument(versionArgument);
+    }
+    catch (final ArgumentException e)
+    {
+      // ignore
+    }
+  }
+
+
+
+  private boolean isGeneralArgument(final Argument arg)
+  {
+    boolean general = false;
+    if (arg != null)
+    {
+      final String longId = arg.getLongIdentifier();
+      general = OPTION_LONG_HELP.equals(longId)
+          || OPTION_LONG_PRODUCT_VERSION.equals(longId);
+    }
+    return general;
+  }
+
+
+
+  private boolean isInputOutputArgument(final Argument arg)
+  {
+    boolean io = false;
+    if (arg != null)
+    {
+      final String longId = arg.getLongIdentifier();
+      io = OPTION_LONG_VERBOSE.equals(longId)
+          || OPTION_LONG_QUIET.equals(longId)
+          || OPTION_LONG_NO_PROMPT.equals(longId)
+          || OPTION_LONG_PROP_FILE_PATH.equals(longId)
+          || OPTION_LONG_NO_PROP_FILE.equals(longId)
+          || OPTION_LONG_SCRIPT_FRIENDLY.equals(longId)
+          || OPTION_LONG_DONT_WRAP.equals(longId)
+          || OPTION_LONG_ENCODING.equals(longId)
+          || OPTION_LONG_BATCH_FILE_PATH.equals(longId);
+    }
+    return io;
+  }
+
+
+
+  private boolean isLdapConnectionArgument(final Argument arg)
+  {
+    boolean ldap = false;
+    if (arg != null)
+    {
+      final String longId = arg.getLongIdentifier();
+      ldap = OPTION_LONG_USE_SSL.equals(longId)
+          || OPTION_LONG_START_TLS.equals(longId)
+          || OPTION_LONG_HOST.equals(longId) || OPTION_LONG_PORT.equals(longId)
+          || OPTION_LONG_BINDDN.equals(longId)
+          || OPTION_LONG_BINDPWD.equals(longId)
+          || OPTION_LONG_BINDPWD_FILE.equals(longId)
+          || OPTION_LONG_SASLOPTION.equals(longId)
+          || OPTION_LONG_TRUSTALL.equals(longId)
+          || OPTION_LONG_TRUSTSTOREPATH.equals(longId)
+          || OPTION_LONG_TRUSTSTORE_PWD.equals(longId)
+          || OPTION_LONG_TRUSTSTORE_PWD_FILE.equals(longId)
+          || OPTION_LONG_KEYSTOREPATH.equals(longId)
+          || OPTION_LONG_KEYSTORE_PWD.equals(longId)
+          || OPTION_LONG_KEYSTORE_PWD_FILE.equals(longId)
+          || OPTION_LONG_CERT_NICKNAME.equals(longId)
+          || OPTION_LONG_REFERENCED_HOST_NAME.equals(longId)
+          || OPTION_LONG_ADMIN_UID.equals(longId)
+          || OPTION_LONG_REPORT_AUTHZ_ID.equals(longId)
+          || OPTION_LONG_USE_PW_POLICY_CTL.equals(longId)
+          || OPTION_LONG_USE_SASL_EXTERNAL.equals(longId)
+          || OPTION_LONG_PROTOCOL_VERSION.equals(longId);
+    }
+    return ldap;
+  }
+
+
+
+  /**
    * Appends argument usage information to the provided buffer.
    *
    * @param a
    *          The argument to handle.
    * @param buffer
-   *          The buffer to which the usage information should be
-   *          appended.
+   *          The buffer to which the usage information should be appended.
    */
-  private void printArgumentUsage(Argument a, StringBuilder buffer)
+  private void printArgumentUsage(final Argument a, final StringBuilder buffer)
   {
     // Write a line with the short and/or long identifiers that may be
     // used
     // for the argument.
     final int indentLength = INDENT.length();
-    Character shortID = a.getShortIdentifier();
-    String longID = a.getLongIdentifier();
+    final Character shortID = a.getShortIdentifier();
+    final String longID = a.getLongIdentifier();
     if (shortID != null)
     {
-      int currentLength = buffer.length();
+      final int currentLength = buffer.length();
 
       if (usageArgument.getName().equals(a.getName()))
       {
@@ -1669,7 +1832,7 @@
 
       if (longID != null)
       {
-        StringBuilder newBuffer = new StringBuilder();
+        final StringBuilder newBuffer = new StringBuilder();
         newBuffer.append(", --");
         newBuffer.append(longID);
 
@@ -1679,7 +1842,7 @@
           newBuffer.append(a.getValuePlaceholder());
         }
 
-        int lineLength = (buffer.length() - currentLength)
+        final int lineLength = (buffer.length() - currentLength)
             + newBuffer.length();
         if (lineLength > MAX_LENGTH)
         {
@@ -1720,8 +1883,8 @@
     // indent the description five characters and try our best to wrap
     // at or
     // before column 79 so it will be friendly to 80-column displays.
-    LocalizableMessage description = a.getDescription();
-    int descMaxLength = MAX_LENGTH - indentLength - 1;
+    final LocalizableMessage description = a.getDescription();
+    final int descMaxLength = MAX_LENGTH - indentLength - 1;
     if (description.length() <= descMaxLength)
     {
       buffer.append(INDENT);
@@ -1778,189 +1941,9 @@
         && (a.getDefaultValue().length() > 0))
     {
       buffer.append(INDENT);
-      buffer.append(INFO_ARGPARSER_USAGE_DEFAULT_VALUE.get(
-          a.getDefaultValue()).toString());
+      buffer.append(INFO_ARGPARSER_USAGE_DEFAULT_VALUE.get(a.getDefaultValue())
+          .toString());
       buffer.append(EOL);
     }
   }
-
-
-
-  /**
-   * Given an argument, returns an appropriate group. Arguments may be
-   * part of one of the special groups or the default group.
-   *
-   * @param argument
-   *          for which a group is requested
-   * @return argument group appropriate for <code>argument</code>
-   */
-  ArgumentGroup getStandardGroup(Argument argument)
-  {
-    ArgumentGroup group;
-    if (isInputOutputArgument(argument))
-    {
-      group = ioArgGroup;
-    }
-    else if (isGeneralArgument(argument))
-    {
-      group = generalArgGroup;
-    }
-    else if (isLdapConnectionArgument(argument))
-    {
-      group = ldapArgGroup;
-    }
-    else
-    {
-      group = defaultArgGroup;
-    }
-    return group;
-  }
-
-
-
-  /**
-   * Indicates whether or not argument group description headers should
-   * be printed.
-   *
-   * @return boolean where true means print the descriptions
-   */
-  boolean printUsageGroupHeaders()
-  {
-    // If there is only a single group then we won't print them.
-    int groupsContainingArgs = 0;
-    for (ArgumentGroup argGroup : argumentGroups)
-    {
-      if (argGroup.containsNonHiddenArguments())
-      {
-        groupsContainingArgs++;
-      }
-    }
-    return groupsContainingArgs > 1;
-  }
-
-
-
-  private void initGroups()
-  {
-    this.argumentGroups = new TreeSet<ArgumentGroup>();
-    this.argumentGroups.add(defaultArgGroup);
-    this.argumentGroups.add(ldapArgGroup);
-    this.argumentGroups.add(generalArgGroup);
-    this.argumentGroups.add(ioArgGroup);
-
-    try
-    {
-      versionArgument = new BooleanArgument(
-          OPTION_LONG_PRODUCT_VERSION, OPTION_SHORT_PRODUCT_VERSION,
-          OPTION_LONG_PRODUCT_VERSION, INFO_DESCRIPTION_PRODUCT_VERSION
-              .get());
-      this.generalArgGroup.addArgument(versionArgument);
-    }
-    catch (ArgumentException e)
-    {
-      // ignore
-    }
-  }
-
-
-
-  private boolean isInputOutputArgument(Argument arg)
-  {
-    boolean io = false;
-    if (arg != null)
-    {
-      String longId = arg.getLongIdentifier();
-      io = OPTION_LONG_VERBOSE.equals(longId)
-          || OPTION_LONG_QUIET.equals(longId)
-          || OPTION_LONG_NO_PROMPT.equals(longId)
-          || OPTION_LONG_PROP_FILE_PATH.equals(longId)
-          || OPTION_LONG_NO_PROP_FILE.equals(longId)
-          || OPTION_LONG_SCRIPT_FRIENDLY.equals(longId)
-          || OPTION_LONG_DONT_WRAP.equals(longId)
-          || OPTION_LONG_ENCODING.equals(longId)
-          || OPTION_LONG_BATCH_FILE_PATH.equals(longId);
-    }
-    return io;
-  }
-
-
-
-  private boolean isLdapConnectionArgument(Argument arg)
-  {
-    boolean ldap = false;
-    if (arg != null)
-    {
-      String longId = arg.getLongIdentifier();
-      ldap = OPTION_LONG_USE_SSL.equals(longId)
-          || OPTION_LONG_START_TLS.equals(longId)
-          || OPTION_LONG_HOST.equals(longId)
-          || OPTION_LONG_PORT.equals(longId)
-          || OPTION_LONG_BINDDN.equals(longId)
-          || OPTION_LONG_BINDPWD.equals(longId)
-          || OPTION_LONG_BINDPWD_FILE.equals(longId)
-          || OPTION_LONG_SASLOPTION.equals(longId)
-          || OPTION_LONG_TRUSTALL.equals(longId)
-          || OPTION_LONG_TRUSTSTOREPATH.equals(longId)
-          || OPTION_LONG_TRUSTSTORE_PWD.equals(longId)
-          || OPTION_LONG_TRUSTSTORE_PWD_FILE.equals(longId)
-          || OPTION_LONG_KEYSTOREPATH.equals(longId)
-          || OPTION_LONG_KEYSTORE_PWD.equals(longId)
-          || OPTION_LONG_KEYSTORE_PWD_FILE.equals(longId)
-          || OPTION_LONG_CERT_NICKNAME.equals(longId)
-          || OPTION_LONG_REFERENCED_HOST_NAME.equals(longId)
-          || OPTION_LONG_ADMIN_UID.equals(longId)
-          || OPTION_LONG_REPORT_AUTHZ_ID.equals(longId)
-          || OPTION_LONG_USE_PW_POLICY_CTL.equals(longId)
-          || OPTION_LONG_USE_SASL_EXTERNAL.equals(longId)
-          || OPTION_LONG_PROTOCOL_VERSION.equals(longId);
-    }
-    return ldap;
-  }
-
-
-
-  private boolean isGeneralArgument(Argument arg)
-  {
-    boolean general = false;
-    if (arg != null)
-    {
-      String longId = arg.getLongIdentifier();
-      general = OPTION_LONG_HELP.equals(longId)
-          || OPTION_LONG_PRODUCT_VERSION.equals(longId);
-    }
-    return general;
-  }
-
-
-
-  /**
-   * Returns whether the usage argument was provided or not. This method
-   * should be called after a call to parseArguments.
-   *
-   * @return <CODE>true</CODE> if the usage argument was provided and
-   *         <CODE>false</CODE> otherwise.
-   */
-  boolean isUsageArgumentPresent()
-  {
-    boolean isUsageArgumentPresent = false;
-    if (usageArgument != null)
-    {
-      isUsageArgumentPresent = usageArgument.isPresent();
-    }
-    return isUsageArgumentPresent;
-  }
-
-
-
-  /**
-   * Returns whether the version argument was provided or not. This
-   * method should be called after a call to parseArguments.
-   *
-   * @return <CODE>true</CODE> if the version argument was provided and
-   *         <CODE>false</CODE> otherwise.
-   */
-  boolean isVersionArgumentPresent()
-  {
-    return versionPresent;
-  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/ArgumentParserConnectionFactory.java b/sdk/src/com/sun/opends/sdk/tools/ArgumentParserConnectionFactory.java
index b7d5686..b3ba2d5 100644
--- a/sdk/src/com/sun/opends/sdk/tools/ArgumentParserConnectionFactory.java
+++ b/sdk/src/com/sun/opends/sdk/tools/ArgumentParserConnectionFactory.java
@@ -36,36 +36,28 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.net.InetAddress;
+import java.security.GeneralSecurityException;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.NoSuchAlgorithmException;
 import java.security.cert.CertificateException;
 import java.util.logging.Logger;
 
-import javax.net.ssl.KeyManager;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.TrustManager;
 import javax.net.ssl.X509KeyManager;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
+import javax.net.ssl.X509TrustManager;
 
 import org.opends.sdk.*;
-import org.opends.sdk.ldap.LDAPConnectionFactory;
-import org.opends.sdk.ldap.LDAPConnectionOptions;
-import org.opends.sdk.requests.BindRequest;
-import org.opends.sdk.requests.Requests;
-import org.opends.sdk.sasl.*;
-
-import com.sun.opends.sdk.util.SSLUtils;
-import com.sun.opends.sdk.util.StaticUtils;
+import org.opends.sdk.requests.*;
 
 
 
 /**
  * A connection factory designed for use with command line tools.
  */
-final class ArgumentParserConnectionFactory extends
-    AbstractConnectionFactory implements ConnectionFactory
+final class ArgumentParserConnectionFactory extends AbstractConnectionFactory
+    implements ConnectionFactory
 {
   /**
    * End Of Line.
@@ -91,7 +83,7 @@
   /**
    * The 'bindDN' global argument.
    */
-  private StringArgument bindDnArg = null;
+  private StringArgument bindNameArg = null;
 
   /**
    * The 'bindPasswordFile' global argument.
@@ -159,8 +151,8 @@
   private StringArgument saslOptionArg = null;
 
   /**
-   * Whether to request that the server return the authorization ID in
-   * the bind response.
+   * Whether to request that the server return the authorization ID in the bind
+   * response.
    */
   private final BooleanArgument reportAuthzID;
 
@@ -181,17 +173,17 @@
 
 
 
-  public ArgumentParserConnectionFactory(ArgumentParser argumentParser,
-      ConsoleApplication app) throws ArgumentException
+  public ArgumentParserConnectionFactory(final ArgumentParser argumentParser,
+      final ConsoleApplication app) throws ArgumentException
   {
     this(argumentParser, app, "cn=Directory Manager", 389, false);
   }
 
 
 
-  public ArgumentParserConnectionFactory(ArgumentParser argumentParser,
-      ConsoleApplication app, String defaultBindDN, int defaultPort,
-      boolean alwaysSSL) throws ArgumentException
+  public ArgumentParserConnectionFactory(final ArgumentParser argumentParser,
+      final ConsoleApplication app, final String defaultBindDN,
+      final int defaultPort, final boolean alwaysSSL) throws ArgumentException
   {
     this.app = app;
     useSSLArg = new BooleanArgument("useSSL", OPTION_SHORT_USE_SSL,
@@ -207,9 +199,8 @@
       useSSLArg.setPresent(true);
     }
 
-    useStartTLSArg = new BooleanArgument("startTLS",
-        OPTION_SHORT_START_TLS, OPTION_LONG_START_TLS,
-        INFO_DESCRIPTION_START_TLS.get());
+    useStartTLSArg = new BooleanArgument("startTLS", OPTION_SHORT_START_TLS,
+        OPTION_LONG_START_TLS, INFO_DESCRIPTION_START_TLS.get());
     useStartTLSArg.setPropertyName(OPTION_LONG_START_TLS);
     if (!alwaysSSL)
     {
@@ -221,13 +212,13 @@
     {
       defaultHostName = InetAddress.getLocalHost().getHostName();
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
       defaultHostName = "Unknown (" + e + ")";
     }
     hostNameArg = new StringArgument("host", OPTION_SHORT_HOST,
-        OPTION_LONG_HOST, false, false, true, INFO_HOST_PLACEHOLDER
-            .get(), defaultHostName, null, INFO_DESCRIPTION_HOST.get());
+        OPTION_LONG_HOST, false, false, true, INFO_HOST_PLACEHOLDER.get(),
+        defaultHostName, null, INFO_DESCRIPTION_HOST.get());
     hostNameArg.setPropertyName(OPTION_LONG_HOST);
     argumentParser.addLdapConnectionArgument(hostNameArg);
 
@@ -237,109 +228,100 @@
       portDescription = INFO_DESCRIPTION_ADMIN_PORT.get();
     }
 
-    portArg = new IntegerArgument("port", OPTION_SHORT_PORT,
-        OPTION_LONG_PORT, false, false, true, INFO_PORT_PLACEHOLDER
-            .get(), defaultPort, null, portDescription);
+    portArg = new IntegerArgument("port", OPTION_SHORT_PORT, OPTION_LONG_PORT,
+        false, false, true, INFO_PORT_PLACEHOLDER.get(), defaultPort, null,
+        portDescription);
     portArg.setPropertyName(OPTION_LONG_PORT);
     argumentParser.addLdapConnectionArgument(portArg);
 
-    bindDnArg = new StringArgument("bindDN", OPTION_SHORT_BINDDN,
-        OPTION_LONG_BINDDN, false, false, true, INFO_BINDDN_PLACEHOLDER
-            .get(), defaultBindDN, null, INFO_DESCRIPTION_BINDDN.get());
-    bindDnArg.setPropertyName(OPTION_LONG_BINDDN);
-    argumentParser.addLdapConnectionArgument(bindDnArg);
+    bindNameArg = new StringArgument("bindDN", OPTION_SHORT_BINDDN,
+        OPTION_LONG_BINDDN, false, false, true, INFO_BINDDN_PLACEHOLDER.get(),
+        defaultBindDN, null, INFO_DESCRIPTION_BINDDN.get());
+    bindNameArg.setPropertyName(OPTION_LONG_BINDDN);
+    argumentParser.addLdapConnectionArgument(bindNameArg);
 
-    bindPasswordArg = new StringArgument("bindPassword",
-        OPTION_SHORT_BINDPWD, OPTION_LONG_BINDPWD, false, false, true,
+    bindPasswordArg = new StringArgument("bindPassword", OPTION_SHORT_BINDPWD,
+        OPTION_LONG_BINDPWD, false, false, true,
         INFO_BINDPWD_PLACEHOLDER.get(), null, null,
         INFO_DESCRIPTION_BINDPASSWORD.get());
     bindPasswordArg.setPropertyName(OPTION_LONG_BINDPWD);
     argumentParser.addLdapConnectionArgument(bindPasswordArg);
 
     bindPasswordFileArg = new FileBasedArgument("bindPasswordFile",
-        OPTION_SHORT_BINDPWD_FILE, OPTION_LONG_BINDPWD_FILE, false,
-        false, INFO_BINDPWD_FILE_PLACEHOLDER.get(), null, null,
+        OPTION_SHORT_BINDPWD_FILE, OPTION_LONG_BINDPWD_FILE, false, false,
+        INFO_BINDPWD_FILE_PLACEHOLDER.get(), null, null,
         INFO_DESCRIPTION_BINDPASSWORDFILE.get());
     bindPasswordFileArg.setPropertyName(OPTION_LONG_BINDPWD_FILE);
     argumentParser.addLdapConnectionArgument(bindPasswordFileArg);
 
-    saslOptionArg = new StringArgument("sasloption",
-        OPTION_SHORT_SASLOPTION, OPTION_LONG_SASLOPTION, false, true,
-        true, INFO_SASL_OPTION_PLACEHOLDER.get(), null, null,
-        INFO_LDAP_CONN_DESCRIPTION_SASLOPTIONS.get());
+    saslOptionArg = new StringArgument("sasloption", OPTION_SHORT_SASLOPTION,
+        OPTION_LONG_SASLOPTION, false, true, true, INFO_SASL_OPTION_PLACEHOLDER
+            .get(), null, null, INFO_LDAP_CONN_DESCRIPTION_SASLOPTIONS.get());
     saslOptionArg.setPropertyName(OPTION_LONG_SASLOPTION);
     argumentParser.addLdapConnectionArgument(saslOptionArg);
 
-    trustAllArg = new BooleanArgument("trustAll",
-        OPTION_SHORT_TRUSTALL, OPTION_LONG_TRUSTALL,
-        INFO_DESCRIPTION_TRUSTALL.get());
+    trustAllArg = new BooleanArgument("trustAll", OPTION_SHORT_TRUSTALL,
+        OPTION_LONG_TRUSTALL, INFO_DESCRIPTION_TRUSTALL.get());
     trustAllArg.setPropertyName(OPTION_LONG_TRUSTALL);
     argumentParser.addLdapConnectionArgument(trustAllArg);
 
     trustStorePathArg = new StringArgument("trustStorePath",
-        OPTION_SHORT_TRUSTSTOREPATH, OPTION_LONG_TRUSTSTOREPATH, false,
-        false, true, INFO_TRUSTSTOREPATH_PLACEHOLDER.get(), null, null,
+        OPTION_SHORT_TRUSTSTOREPATH, OPTION_LONG_TRUSTSTOREPATH, false, false,
+        true, INFO_TRUSTSTOREPATH_PLACEHOLDER.get(), null, null,
         INFO_DESCRIPTION_TRUSTSTOREPATH.get());
     trustStorePathArg.setPropertyName(OPTION_LONG_TRUSTSTOREPATH);
     argumentParser.addLdapConnectionArgument(trustStorePathArg);
 
     trustStorePasswordArg = new StringArgument("trustStorePassword",
-        OPTION_SHORT_TRUSTSTORE_PWD, OPTION_LONG_TRUSTSTORE_PWD, false,
-        false, true, INFO_TRUSTSTORE_PWD_PLACEHOLDER.get(), null, null,
+        OPTION_SHORT_TRUSTSTORE_PWD, OPTION_LONG_TRUSTSTORE_PWD, false, false,
+        true, INFO_TRUSTSTORE_PWD_PLACEHOLDER.get(), null, null,
         INFO_DESCRIPTION_TRUSTSTOREPASSWORD.get());
     trustStorePasswordArg.setPropertyName(OPTION_LONG_TRUSTSTORE_PWD);
     argumentParser.addLdapConnectionArgument(trustStorePasswordArg);
 
-    trustStorePasswordFileArg = new FileBasedArgument(
-        "trustStorePasswordFile", OPTION_SHORT_TRUSTSTORE_PWD_FILE,
-        OPTION_LONG_TRUSTSTORE_PWD_FILE, false, false,
-        INFO_TRUSTSTORE_PWD_FILE_PLACEHOLDER.get(), null, null,
+    trustStorePasswordFileArg = new FileBasedArgument("trustStorePasswordFile",
+        OPTION_SHORT_TRUSTSTORE_PWD_FILE, OPTION_LONG_TRUSTSTORE_PWD_FILE,
+        false, false, INFO_TRUSTSTORE_PWD_FILE_PLACEHOLDER.get(), null, null,
         INFO_DESCRIPTION_TRUSTSTOREPASSWORD_FILE.get());
-    trustStorePasswordFileArg
-        .setPropertyName(OPTION_LONG_TRUSTSTORE_PWD_FILE);
+    trustStorePasswordFileArg.setPropertyName(OPTION_LONG_TRUSTSTORE_PWD_FILE);
     argumentParser.addLdapConnectionArgument(trustStorePasswordFileArg);
 
     keyStorePathArg = new StringArgument("keyStorePath",
-        OPTION_SHORT_KEYSTOREPATH, OPTION_LONG_KEYSTOREPATH, false,
-        false, true, INFO_KEYSTOREPATH_PLACEHOLDER.get(), null, null,
+        OPTION_SHORT_KEYSTOREPATH, OPTION_LONG_KEYSTOREPATH, false, false,
+        true, INFO_KEYSTOREPATH_PLACEHOLDER.get(), null, null,
         INFO_DESCRIPTION_KEYSTOREPATH.get());
     keyStorePathArg.setPropertyName(OPTION_LONG_KEYSTOREPATH);
     argumentParser.addLdapConnectionArgument(keyStorePathArg);
 
     keyStorePasswordArg = new StringArgument("keyStorePassword",
-        OPTION_SHORT_KEYSTORE_PWD, OPTION_LONG_KEYSTORE_PWD, false,
-        false, true, INFO_KEYSTORE_PWD_PLACEHOLDER.get(), null, null,
+        OPTION_SHORT_KEYSTORE_PWD, OPTION_LONG_KEYSTORE_PWD, false, false,
+        true, INFO_KEYSTORE_PWD_PLACEHOLDER.get(), null, null,
         INFO_DESCRIPTION_KEYSTOREPASSWORD.get());
     keyStorePasswordArg.setPropertyName(OPTION_LONG_KEYSTORE_PWD);
     argumentParser.addLdapConnectionArgument(keyStorePasswordArg);
 
-    keyStorePasswordFileArg = new FileBasedArgument(
-        "keystorePasswordFile", OPTION_SHORT_KEYSTORE_PWD_FILE,
-        OPTION_LONG_KEYSTORE_PWD_FILE, false, false,
-        INFO_KEYSTORE_PWD_FILE_PLACEHOLDER.get(), null, null,
+    keyStorePasswordFileArg = new FileBasedArgument("keystorePasswordFile",
+        OPTION_SHORT_KEYSTORE_PWD_FILE, OPTION_LONG_KEYSTORE_PWD_FILE, false,
+        false, INFO_KEYSTORE_PWD_FILE_PLACEHOLDER.get(), null, null,
         INFO_DESCRIPTION_KEYSTOREPASSWORD_FILE.get());
-    keyStorePasswordFileArg
-        .setPropertyName(OPTION_LONG_KEYSTORE_PWD_FILE);
+    keyStorePasswordFileArg.setPropertyName(OPTION_LONG_KEYSTORE_PWD_FILE);
     argumentParser.addLdapConnectionArgument(keyStorePasswordFileArg);
 
     certNicknameArg = new StringArgument("certNickname",
-        OPTION_SHORT_CERT_NICKNAME, OPTION_LONG_CERT_NICKNAME, false,
-        false, true, INFO_NICKNAME_PLACEHOLDER.get(), null, null,
+        OPTION_SHORT_CERT_NICKNAME, OPTION_LONG_CERT_NICKNAME, false, false,
+        true, INFO_NICKNAME_PLACEHOLDER.get(), null, null,
         INFO_DESCRIPTION_CERT_NICKNAME.get());
     certNicknameArg.setPropertyName(OPTION_LONG_CERT_NICKNAME);
     argumentParser.addLdapConnectionArgument(certNicknameArg);
 
     reportAuthzID = new BooleanArgument("reportauthzid", 'E',
-        OPTION_LONG_REPORT_AUTHZ_ID, INFO_DESCRIPTION_REPORT_AUTHZID
-            .get());
+        OPTION_LONG_REPORT_AUTHZ_ID, INFO_DESCRIPTION_REPORT_AUTHZID.get());
     reportAuthzID.setPropertyName(OPTION_LONG_REPORT_AUTHZ_ID);
     argumentParser.addArgument(reportAuthzID);
 
-    usePasswordPolicyControl = new BooleanArgument(
-        "usepwpolicycontrol", null, OPTION_LONG_USE_PW_POLICY_CTL,
-        INFO_DESCRIPTION_USE_PWP_CONTROL.get());
-    usePasswordPolicyControl
-        .setPropertyName(OPTION_LONG_USE_PW_POLICY_CTL);
+    usePasswordPolicyControl = new BooleanArgument("usepwpolicycontrol", null,
+        OPTION_LONG_USE_PW_POLICY_CTL, INFO_DESCRIPTION_USE_PWP_CONTROL.get());
+    usePasswordPolicyControl.setPropertyName(OPTION_LONG_USE_PW_POLICY_CTL);
     argumentParser.addArgument(usePasswordPolicyControl);
   }
 
@@ -348,8 +330,9 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public FutureResult<AsynchronousConnection> getAsynchronousConnection(
-      ResultHandler<AsynchronousConnection> handler)
+      final ResultHandler<AsynchronousConnection> handler)
   {
     return connFactory.getAsynchronousConnection(handler);
   }
@@ -363,7 +346,7 @@
     // Couldn't have at the same time bindPassword and bindPasswordFile
     if (bindPasswordArg.isPresent() && bindPasswordFileArg.isPresent())
     {
-      LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
+      final LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
           bindPasswordArg.getLongIdentifier(), bindPasswordFileArg
               .getLongIdentifier());
       throw new ArgumentException(message);
@@ -373,22 +356,21 @@
     // trustStore related arg
     if (trustAllArg.isPresent() && trustStorePathArg.isPresent())
     {
-      LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
+      final LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
           trustAllArg.getLongIdentifier(), trustStorePathArg
               .getLongIdentifier());
       throw new ArgumentException(message);
     }
     if (trustAllArg.isPresent() && trustStorePasswordArg.isPresent())
     {
-      LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
+      final LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
           trustAllArg.getLongIdentifier(), trustStorePasswordArg
               .getLongIdentifier());
       throw new ArgumentException(message);
     }
-    if (trustAllArg.isPresent()
-        && trustStorePasswordFileArg.isPresent())
+    if (trustAllArg.isPresent() && trustStorePasswordFileArg.isPresent())
     {
-      LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
+      final LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
           trustAllArg.getLongIdentifier(), trustStorePasswordFileArg
               .getLongIdentifier());
       throw new ArgumentException(message);
@@ -399,19 +381,19 @@
     if (trustStorePasswordArg.isPresent()
         && trustStorePasswordFileArg.isPresent())
     {
-      LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
-          trustStorePasswordArg.getLongIdentifier(),
-          trustStorePasswordFileArg.getLongIdentifier());
+      final LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
+          trustStorePasswordArg.getLongIdentifier(), trustStorePasswordFileArg
+              .getLongIdentifier());
       throw new ArgumentException(message);
     }
 
     if (trustStorePathArg.isPresent())
     {
       // Check that the path exists and is readable
-      String value = trustStorePathArg.getValue();
+      final String value = trustStorePathArg.getValue();
       if (!canRead(trustStorePathArg.getValue()))
       {
-        LocalizableMessage message = ERR_CANNOT_READ_TRUSTSTORE
+        final LocalizableMessage message = ERR_CANNOT_READ_TRUSTSTORE
             .get(value);
         throw new ArgumentException(message);
       }
@@ -420,11 +402,10 @@
     if (keyStorePathArg.isPresent())
     {
       // Check that the path exists and is readable
-      String value = keyStorePathArg.getValue();
+      final String value = keyStorePathArg.getValue();
       if (!canRead(trustStorePathArg.getValue()))
       {
-        LocalizableMessage message = ERR_CANNOT_READ_KEYSTORE
-            .get(value);
+        final LocalizableMessage message = ERR_CANNOT_READ_KEYSTORE.get(value);
         throw new ArgumentException(message);
       }
     }
@@ -433,9 +414,8 @@
     // useSSLArg
     if (useStartTLSArg.isPresent() && useSSLArg.isPresent())
     {
-      LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
-          useStartTLSArg.getLongIdentifier(), useSSLArg
-              .getLongIdentifier());
+      final LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get(
+          useStartTLSArg.getLongIdentifier(), useSSLArg.getLongIdentifier());
       throw new ArgumentException(message);
     }
 
@@ -455,276 +435,57 @@
 
         if (sslContext == null)
         {
-          TrustManager trustManager = getTrustManager();
+          final TrustManager trustManager = getTrustManager();
 
-          KeyManager keyManager = null;
-          X509KeyManager akm = getKeyManager(keyStorePathArg.getValue());
+          X509KeyManager keyManager = null;
+          final X509KeyManager akm = getKeyManager(keyStorePathArg.getValue());
 
-          if (keyManager != null && clientAlias != null)
+          if (akm != null && clientAlias != null)
           {
-            keyManager = new SelectableCertificateKeyManager(akm,
-                clientAlias);
+            keyManager = KeyManagers.useSingleCertificate(clientAlias, akm);
           }
-          sslContext = SSLUtils.getSSLContext(trustManager, keyManager);
+
+          sslContext = new SSLContextBuilder().setTrustManager(trustManager)
+              .setKeyManager(keyManager).getSSLContext();
         }
       }
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
-      throw new ArgumentException(ERR_LDAP_CONN_CANNOT_INITIALIZE_SSL
-          .get(e.toString()), e);
+      throw new ArgumentException(ERR_LDAP_CONN_CANNOT_INITIALIZE_SSL.get(e
+          .toString()), e);
     }
 
     if (sslContext != null)
     {
-      LDAPConnectionOptions options = LDAPConnectionOptions
-          .defaultOptions().setSSLContext(sslContext).setUseStartTLS(
-              useStartTLSArg.isPresent());
-      connFactory = new LDAPConnectionFactory(hostNameArg.getValue(),
-          port, options);
+      final LDAPOptions options = new LDAPOptions().setSSLContext(sslContext)
+          .setUseStartTLS(useStartTLSArg.isPresent());
+      connFactory = new LDAPConnectionFactory(hostNameArg.getValue(), port,
+          options);
     }
     else
     {
-      connFactory = new LDAPConnectionFactory(hostNameArg.getValue(),
-          port);
+      connFactory = new LDAPConnectionFactory(hostNameArg.getValue(), port);
     }
 
     try
     {
       bindRequest = getBindRequest();
     }
-    catch (CLIException e)
+    catch (final CLIException e)
     {
       throw new ArgumentException(LocalizableMessage
           .raw("Error reading input: " + e.toString()));
     }
     if (bindRequest != null)
     {
-      connFactory = new AuthenticatedConnectionFactory(connFactory,
-          bindRequest).setRebindAllowed(true);
+      connFactory = new AuthenticatedConnectionFactory(connFactory, bindRequest)
+          .setRebindAllowed(true);
     }
   }
 
 
 
-  private BindRequest getBindRequest() throws CLIException,
-      ArgumentException
-  {
-    String mech = null;
-    for (String s : saslOptionArg.getValues())
-    {
-      if (s.startsWith(SASL_PROPERTY_MECH))
-      {
-        mech = parseSASLOptionValue(s);
-        break;
-      }
-    }
-
-    if (mech == null)
-    {
-      if (bindDnArg.isPresent() || bindPasswordFileArg.isPresent()
-          || bindPasswordArg.isPresent())
-      {
-        return Requests
-            .newSimpleBindRequest(getBindDN(), getPassword());
-      }
-      return null;
-    }
-
-    if (mech.equals(DigestMD5SASLBindRequest.SASL_MECHANISM_DIGEST_MD5))
-    {
-      return new DigestMD5SASLBindRequest(
-          getAuthID(DigestMD5SASLBindRequest.SASL_MECHANISM_DIGEST_MD5),
-          getAuthzID(), getPassword(), getRealm());
-    }
-    if (mech.equals(CRAMMD5SASLBindRequest.SASL_MECHANISM_CRAM_MD5))
-    {
-      return new CRAMMD5SASLBindRequest(
-          getAuthID(CRAMMD5SASLBindRequest.SASL_MECHANISM_CRAM_MD5),
-          getPassword());
-    }
-    if (mech.equals(GSSAPISASLBindRequest.SASL_MECHANISM_GSSAPI))
-    {
-      try
-      {
-        Subject subject = GSSAPISASLBindRequest.Kerberos5Login(
-            getAuthID(GSSAPISASLBindRequest.SASL_MECHANISM_GSSAPI),
-            getPassword(), getRealm(), getKDC());
-        return new GSSAPISASLBindRequest(subject, getAuthzID());
-      }
-      catch (LoginException e)
-      {
-        LocalizableMessage message = ERR_LDAPAUTH_GSSAPI_LOCAL_AUTHENTICATION_FAILED
-            .get(StaticUtils.getExceptionMessage(e));
-        throw new ArgumentException(message, e);
-      }
-    }
-    if (mech.equals(ExternalSASLBindRequest.SASL_MECHANISM_EXTERNAL))
-    {
-      if (sslContext == null)
-      {
-        LocalizableMessage message = ERR_TOOL_SASLEXTERNAL_NEEDS_SSL_OR_TLS
-            .get();
-        throw new ArgumentException(message);
-      }
-      if (!keyStorePathArg.isPresent() && getKeyStore() == null)
-      {
-        LocalizableMessage message = ERR_TOOL_SASLEXTERNAL_NEEDS_KEYSTORE
-            .get();
-        throw new ArgumentException(message);
-      }
-      return new ExternalSASLBindRequest(getAuthzID());
-    }
-    if (mech.equals(PlainSASLBindRequest.SASL_MECHANISM_PLAIN))
-    {
-      return new PlainSASLBindRequest(
-          getAuthID(PlainSASLBindRequest.SASL_MECHANISM_PLAIN),
-          getAuthzID(), getPassword());
-    }
-
-    throw new ArgumentException(ERR_LDAPAUTH_UNSUPPORTED_SASL_MECHANISM
-        .get(mech));
-  }
-
-
-
-  private DN getBindDN() throws CLIException, ArgumentException
-  {
-    String value = "";
-    if (bindDnArg.isPresent())
-    {
-      value = bindDnArg.getValue();
-    }
-    else if (app.isInteractive())
-    {
-      value = app.readInput(LocalizableMessage.raw("Bind DN:"),
-          bindDnArg.getDefaultValue() == null ? value : bindDnArg
-              .getDefaultValue());
-    }
-
-    try
-    {
-      return DN.valueOf(value);
-    }
-    catch (LocalizedIllegalArgumentException e)
-    {
-      throw new ArgumentException(e.getMessageObject());
-    }
-  }
-
-
-
-  private String getAuthID(String mech) throws CLIException,
-      ArgumentException
-  {
-    String value = null;
-    for (String s : saslOptionArg.getValues())
-    {
-      if (s.startsWith(SASL_PROPERTY_AUTHID))
-      {
-        value = parseSASLOptionValue(s);
-        break;
-      }
-    }
-    if (value == null && bindDnArg.isPresent())
-    {
-      value = "dn: " + bindDnArg.getValue();
-    }
-    if (value == null && app.isInteractive())
-    {
-      value = app.readInput(LocalizableMessage
-          .raw("Authentication ID:"),
-          bindDnArg.getDefaultValue() == null ? null : "dn: "
-              + bindDnArg.getDefaultValue());
-    }
-    if (value == null)
-    {
-      LocalizableMessage message = ERR_LDAPAUTH_SASL_AUTHID_REQUIRED
-          .get(mech);
-      throw new ArgumentException(message);
-    }
-    return value;
-  }
-
-
-
-  private String getAuthzID() throws CLIException, ArgumentException
-  {
-    String value = null;
-    for (String s : saslOptionArg.getValues())
-    {
-      if (s.startsWith(SASL_PROPERTY_AUTHZID))
-      {
-        value = parseSASLOptionValue(s);
-        break;
-      }
-    }
-    return value;
-  }
-
-
-
-  /**
-   * Get the password which has to be used for the command. If no
-   * password was specified, return null.
-   *
-   * @return The password stored into the specified file on by the
-   *         command line argument, or null it if not specified.
-   */
-  private ByteString getPassword() throws CLIException
-  {
-    String value = "";
-    if (bindPasswordArg.isPresent())
-    {
-      value = bindPasswordArg.getValue();
-    }
-    else if (bindPasswordFileArg.isPresent())
-    {
-      value = bindPasswordFileArg.getValue();
-    }
-    if (value.length() == 0 && app.isInteractive())
-    {
-      value = app.readLineOfInput(LocalizableMessage
-          .raw("Bind Password:"));
-    }
-
-    return ByteString.valueOf(value);
-  }
-
-
-
-  private String getRealm() throws ArgumentException, CLIException
-  {
-    String value = null;
-    for (String s : saslOptionArg.getValues())
-    {
-      if (s.startsWith(SASL_PROPERTY_REALM))
-      {
-        value = parseSASLOptionValue(s);
-        break;
-      }
-    }
-    return value;
-  }
-
-
-
-  private String getKDC() throws ArgumentException, CLIException
-  {
-    String value = null;
-    for (String s : saslOptionArg.getValues())
-    {
-      if (s.startsWith(SASL_PROPERTY_KDC))
-      {
-        value = parseSASLOptionValue(s);
-        break;
-      }
-    }
-    return value;
-  }
-
-
-
   /**
    * Returns <CODE>true</CODE> if we can read on the provided path and
    * <CODE>false</CODE> otherwise.
@@ -734,52 +495,167 @@
    * @return <CODE>true</CODE> if we can read on the provided path and
    *         <CODE>false</CODE> otherwise.
    */
-  private boolean canRead(String path)
+  private boolean canRead(final String path)
   {
     boolean canRead;
-    File file = new File(path);
+    final File file = new File(path);
     canRead = file.exists() && file.canRead();
     return canRead;
   }
 
 
 
-  /**
-   * Retrieves a <CODE>TrustManager</CODE> object that may be used for
-   * interactions requiring access to a trust manager.
-   *
-   * @return A set of <CODE>TrustManager</CODE> objects that may be used
-   *         for interactions requiring access to a trust manager.
-   * @throws KeyStoreException
-   *           If a problem occurs while interacting with the trust
-   *           store.
-   */
-  private TrustManager getTrustManager() throws KeyStoreException,
-      IOException, NoSuchAlgorithmException, CertificateException
+  private String getAuthID(final String mech) throws CLIException,
+      ArgumentException
   {
-    if (trustAllArg.isPresent())
+    String value = null;
+    for (final String s : saslOptionArg.getValues())
     {
-      return new TrustAllTrustManager();
+      if (s.startsWith(SASL_PROPERTY_AUTHID))
+      {
+        value = parseSASLOptionValue(s);
+        break;
+      }
+    }
+    if (value == null && bindNameArg.isPresent())
+    {
+      value = "dn: " + bindNameArg.getValue();
+    }
+    if (value == null && app.isInteractive())
+    {
+      value = app.readInput(LocalizableMessage.raw("Authentication ID:"),
+          bindNameArg.getDefaultValue() == null ? null : "dn: "
+              + bindNameArg.getDefaultValue());
+    }
+    if (value == null)
+    {
+      final LocalizableMessage message = ERR_LDAPAUTH_SASL_AUTHID_REQUIRED
+          .get(mech);
+      throw new ArgumentException(message);
+    }
+    return value;
+  }
+
+
+
+  private String getAuthzID() throws CLIException, ArgumentException
+  {
+    String value = null;
+    for (final String s : saslOptionArg.getValues())
+    {
+      if (s.startsWith(SASL_PROPERTY_AUTHZID))
+      {
+        value = parseSASLOptionValue(s);
+        break;
+      }
+    }
+    return value;
+  }
+
+
+
+  private String getBindName() throws CLIException
+  {
+    String value = "";
+    if (bindNameArg.isPresent())
+    {
+      value = bindNameArg.getValue();
+    }
+    else if (app.isInteractive())
+    {
+      value = app.readInput(LocalizableMessage.raw("Bind name:"), bindNameArg
+          .getDefaultValue() == null ? value : bindNameArg.getDefaultValue());
     }
 
-    TrustStoreTrustManager tm = null;
-    if (trustStorePathArg.isPresent()
-        && trustStorePathArg.getValue().length() > 0)
+    return value;
+  }
+
+
+
+  private BindRequest getBindRequest() throws CLIException, ArgumentException
+  {
+    String mech = null;
+    for (final String s : saslOptionArg.getValues())
     {
-      tm = new TrustStoreTrustManager(trustStorePathArg.getValue(),
-          getTrustStorePIN(), hostNameArg.getValue(), true);
-    }
-    else if (getTrustStore() != null)
-    {
-      tm = new TrustStoreTrustManager(getTrustStore(),
-          getTrustStorePIN(), hostNameArg.getValue(), true);
+      if (s.startsWith(SASL_PROPERTY_MECH))
+      {
+        mech = parseSASLOptionValue(s);
+        break;
+      }
     }
 
-    if (app != null && !app.isQuiet())
+    if (mech == null)
     {
-      return new PromptingTrustManager(app, tm);
+      if (bindNameArg.isPresent() || bindPasswordFileArg.isPresent()
+          || bindPasswordArg.isPresent())
+      {
+        return Requests.newSimpleBindRequest(getBindName(), getPassword());
+      }
+      return null;
     }
-    return null;
+
+    if (mech.equals(DigestMD5SASLBindRequest.SASL_MECHANISM_NAME))
+    {
+      return Requests.newDigestMD5SASLBindRequest(
+          getAuthID(DigestMD5SASLBindRequest.SASL_MECHANISM_NAME),
+          ByteString.valueOf(getPassword())).setAuthorizationID(getAuthzID())
+          .setRealm(getRealm());
+    }
+    if (mech.equals(CRAMMD5SASLBindRequest.SASL_MECHANISM_NAME))
+    {
+      return Requests.newCRAMMD5SASLBindRequest(
+          getAuthID(CRAMMD5SASLBindRequest.SASL_MECHANISM_NAME), ByteString
+              .valueOf(getPassword()));
+    }
+    if (mech.equals(GSSAPISASLBindRequest.SASL_MECHANISM_NAME))
+    {
+      return Requests.newGSSAPISASLBindRequest(
+          getAuthID(GSSAPISASLBindRequest.SASL_MECHANISM_NAME),
+          ByteString.valueOf(getPassword())).setKDCAddress(getKDC()).setRealm(
+          getRealm()).setAuthorizationID(getAuthzID());
+    }
+    if (mech.equals(ExternalSASLBindRequest.SASL_MECHANISM_NAME))
+    {
+      if (sslContext == null)
+      {
+        final LocalizableMessage message = ERR_TOOL_SASLEXTERNAL_NEEDS_SSL_OR_TLS
+            .get();
+        throw new ArgumentException(message);
+      }
+      if (!keyStorePathArg.isPresent() && getKeyStore() == null)
+      {
+        final LocalizableMessage message = ERR_TOOL_SASLEXTERNAL_NEEDS_KEYSTORE
+            .get();
+        throw new ArgumentException(message);
+      }
+      return Requests.newExternalSASLBindRequest().setAuthorizationID(
+          getAuthzID());
+    }
+    if (mech.equals(PlainSASLBindRequest.SASL_MECHANISM_NAME))
+    {
+      return Requests.newPlainSASLBindRequest(
+          getAuthID(PlainSASLBindRequest.SASL_MECHANISM_NAME),
+          ByteString.valueOf(getPassword())).setAuthorizationID(getAuthzID());
+    }
+
+    throw new ArgumentException(ERR_LDAPAUTH_UNSUPPORTED_SASL_MECHANISM
+        .get(mech));
+  }
+
+
+
+  private String getKDC() throws ArgumentException, CLIException
+  {
+    String value = null;
+    for (final String s : saslOptionArg.getValues())
+    {
+      if (s.startsWith(SASL_PROPERTY_KDC))
+      {
+        value = parseSASLOptionValue(s);
+        break;
+      }
+    }
+    return value;
   }
 
 
@@ -790,8 +666,8 @@
    *
    * @param keyStoreFile
    *          The path to the file containing the key store data.
-   * @return A set of <CODE>KeyManager</CODE> objects that may be used
-   *         for interactions requiring access to a key manager.
+   * @return A set of <CODE>KeyManager</CODE> objects that may be used for
+   *         interactions requiring access to a key manager.
    * @throws java.security.KeyStoreException
    *           If a problem occurs while interacting with the key store.
    */
@@ -811,15 +687,15 @@
       return null;
     }
 
-    String keyStorePass = getKeyStorePIN();
+    final String keyStorePass = getKeyStorePIN();
     char[] keyStorePIN = null;
     if (keyStorePass != null)
     {
       keyStorePIN = keyStorePass.toCharArray();
     }
 
-    FileInputStream fos = new FileInputStream(keyStoreFile);
-    KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+    final FileInputStream fos = new FileInputStream(keyStoreFile);
+    final KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
     keystore.load(fos, keyStorePIN);
     fos.close();
 
@@ -829,6 +705,19 @@
 
 
   /**
+   * Read the KeyStore from the JSSE system property.
+   *
+   * @return The path to the key store file.
+   */
+
+  private String getKeyStore()
+  {
+    return System.getProperty("javax.net.ssl.keyStore");
+  }
+
+
+
+  /**
    * Read the KeyStore PIN from the JSSE system property.
    *
    * @return The PIN that should be used to access the key store.
@@ -855,6 +744,105 @@
 
 
   /**
+   * Get the password which has to be used for the command. If no password was
+   * specified, return null.
+   *
+   * @return The password stored into the specified file on by the command line
+   *         argument, or null it if not specified.
+   */
+  private String getPassword() throws CLIException
+  {
+    String value = "";
+    if (bindPasswordArg.isPresent())
+    {
+      value = bindPasswordArg.getValue();
+    }
+    else if (bindPasswordFileArg.isPresent())
+    {
+      value = bindPasswordFileArg.getValue();
+    }
+    if (value.length() == 0 && app.isInteractive())
+    {
+      value = app.readLineOfInput(LocalizableMessage.raw("Bind Password:"));
+    }
+
+    return value;
+  }
+
+
+
+  private String getRealm() throws ArgumentException, CLIException
+  {
+    String value = null;
+    for (final String s : saslOptionArg.getValues())
+    {
+      if (s.startsWith(SASL_PROPERTY_REALM))
+      {
+        value = parseSASLOptionValue(s);
+        break;
+      }
+    }
+    return value;
+  }
+
+
+
+  /**
+   * Retrieves a <CODE>TrustManager</CODE> object that may be used for
+   * interactions requiring access to a trust manager.
+   *
+   * @return A set of <CODE>TrustManager</CODE> objects that may be used for
+   *         interactions requiring access to a trust manager.
+   * @throws GeneralSecurityException
+   *           If a problem occurs while interacting with the trust store.
+   */
+  private TrustManager getTrustManager() throws IOException,
+      GeneralSecurityException
+  {
+    if (trustAllArg.isPresent())
+    {
+      return TrustManagers.trustAll();
+    }
+
+    X509TrustManager tm = null;
+    if (trustStorePathArg.isPresent()
+        && trustStorePathArg.getValue().length() > 0)
+    {
+      tm = TrustManagers.checkValidityDates(TrustManagers.checkHostName(
+          hostNameArg.getValue(), TrustManagers.checkUsingTrustStore(
+              trustStorePathArg.getValue(), getTrustStorePIN(), null)));
+    }
+    else if (getTrustStore() != null)
+    {
+      tm = TrustManagers.checkValidityDates(TrustManagers.checkHostName(
+          hostNameArg.getValue(), TrustManagers.checkUsingTrustStore(
+              getTrustStore(), getTrustStorePIN(), null)));
+    }
+
+    if (app != null && !app.isQuiet())
+    {
+      return new PromptingTrustManager(app, tm);
+    }
+
+    return null;
+  }
+
+
+
+  /**
+   * Read the TrustStore from the JSSE system property.
+   *
+   * @return The path to the trust store file.
+   */
+
+  private String getTrustStore()
+  {
+    return System.getProperty("javax.net.ssl.trustStore");
+  }
+
+
+
+  /**
    * Read the TrustStore PIN from the JSSE system property.
    *
    * @return The PIN that should be used to access the trust store.
@@ -880,39 +868,13 @@
 
 
 
-  /**
-   * Read the KeyStore from the JSSE system property.
-   *
-   * @return The path to the key store file.
-   */
-
-  private String getKeyStore()
-  {
-    return System.getProperty("javax.net.ssl.keyStore");
-  }
-
-
-
-  /**
-   * Read the TrustStore from the JSSE system property.
-   *
-   * @return The path to the trust store file.
-   */
-
-  private String getTrustStore()
-  {
-    return System.getProperty("javax.net.ssl.trustStore");
-  }
-
-
-
-  private String parseSASLOptionValue(String option)
+  private String parseSASLOptionValue(final String option)
       throws ArgumentException
   {
-    int equalPos = option.indexOf('=');
+    final int equalPos = option.indexOf('=');
     if (equalPos <= 0)
     {
-      LocalizableMessage message = ERR_LDAP_CONN_CANNOT_PARSE_SASL_OPTION
+      final LocalizableMessage message = ERR_LDAP_CONN_CANNOT_PARSE_SASL_OPTION
           .get(option);
       throw new ArgumentException(message);
     }
diff --git a/sdk/src/com/sun/opends/sdk/tools/AuthenticatedConnectionFactory.java b/sdk/src/com/sun/opends/sdk/tools/AuthenticatedConnectionFactory.java
index af0a786..9f1460a 100644
--- a/sdk/src/com/sun/opends/sdk/tools/AuthenticatedConnectionFactory.java
+++ b/sdk/src/com/sun/opends/sdk/tools/AuthenticatedConnectionFactory.java
@@ -33,10 +33,7 @@
 
 import org.opends.sdk.*;
 import org.opends.sdk.requests.*;
-import org.opends.sdk.responses.BindResult;
-import org.opends.sdk.responses.CompareResult;
-import org.opends.sdk.responses.Result;
-import org.opends.sdk.responses.SearchResultEntry;
+import org.opends.sdk.responses.*;
 import org.opends.sdk.schema.Schema;
 
 import com.sun.opends.sdk.util.FutureResultTransformer;
@@ -46,137 +43,35 @@
 
 
 /**
- * An authenticated connection factory can be used to create
- * pre-authenticated connections to a Directory Server.
+ * An authenticated connection factory can be used to create pre-authenticated
+ * connections to a Directory Server.
  * <p>
- * The connections returned by an authenticated connection factory
- * support all operations with the exception of Bind requests. Attempts
- * to perform a Bind will result in an {@code
- * UnsupportedOperationException}.
+ * The connections returned by an authenticated connection factory support all
+ * operations with the exception of Bind requests. Attempts to perform a Bind
+ * will result in an {@code UnsupportedOperationException}.
  * <p>
- * In addition, the returned connections support retrieval of the
- * {@code BindResult} returned from the initial Bind request, or last
- * rebind.
+ * In addition, the returned connections support retrieval of the {@code
+ * BindResult} returned from the initial Bind request, or last rebind.
  * <p>
  * Support for connection re-authentication is provided through the
- * {@link #setRebindAllowed} method which, if set to {@code true},
- * causes subsequent connections created using the factory to support
- * the {@code rebind} method.
+ * {@link #setRebindAllowed} method which, if set to {@code true}, causes
+ * subsequent connections created using the factory to support the {@code
+ * rebind} method.
  * <p>
- * If the Bind request fails for some reason (e.g. invalid credentials),
- * then the connection attempt will fail and an {@code
- * ErrorResultException} will be thrown.
+ * If the Bind request fails for some reason (e.g. invalid credentials), then
+ * the connection attempt will fail and an {@code ErrorResultException} will be
+ * thrown.
  */
-final class AuthenticatedConnectionFactory extends
-    AbstractConnectionFactory implements ConnectionFactory
+final class AuthenticatedConnectionFactory extends AbstractConnectionFactory
+    implements ConnectionFactory
 {
 
-  private final BindRequest request;
-
-  private final ConnectionFactory parentFactory;
-
-  private boolean allowRebinds = false;
-
-
-
   /**
-   * An authenticated synchronous connection supports all operations
-   * except Bind operations.
+   * An authenticated asynchronous connection supports all operations except
+   * Bind operations.
    */
-  public static final class AuthenticatedConnection extends
-      SynchronousConnection
-  {
-    private final AuthenticatedAsynchronousConnection connection;
-
-
-
-    private AuthenticatedConnection(
-        AuthenticatedAsynchronousConnection connection)
-    {
-      super(connection);
-      this.connection = connection;
-    }
-
-
-
-    /**
-     * Bind operations are not supported by pre-authenticated
-     * connections. This method will always throw {@code
-     * UnsupportedOperationException}.
-     */
-    public BindResult bind(BindRequest request)
-        throws UnsupportedOperationException
-    {
-      throw new UnsupportedOperationException();
-    }
-
-
-
-    /**
-     * Bind operations are not supported by pre-authenticated
-     * connections. This method will always throw {@code
-     * UnsupportedOperationException}.
-     */
-    public BindResult bind(String name, String password)
-        throws UnsupportedOperationException
-    {
-      throw new UnsupportedOperationException();
-    }
-
-
-
-    /**
-     * Re-authenticates to the Directory Server using the bind request
-     * associated with this connection. If re-authentication fails for
-     * some reason then this connection will be automatically closed.
-     *
-     * @return The result of the operation.
-     * @throws ErrorResultException
-     *           If the result code indicates that the request failed
-     *           for some reason.
-     * @throws InterruptedException
-     *           If the current thread was interrupted while waiting.
-     * @throws UnsupportedOperationException
-     *           If this connection does not support rebind operations.
-     * @throws IllegalStateException
-     *           If this connection has already been closed, i.e. if
-     *           {@code isClosed() == true}.
-     */
-    public BindResult rebind() throws ErrorResultException,
-        InterruptedException, UnsupportedOperationException,
-        IllegalStateException
-    {
-
-      if (connection.request == null)
-      {
-        throw new UnsupportedOperationException();
-      }
-      return super.bind(connection.request);
-    }
-
-
-
-    /**
-     * Returns an unmodifiable view of the Bind result which was
-     * returned from the server after authentication.
-     *
-     * @return The Bind result which was returned from the server after
-     *         authentication.
-     */
-    public BindResult getAuthenticatedBindResult()
-    {
-      return connection.getAuthenticatedBindResult();
-    }
-  }
-
-
-
-  /**
-   * An authenticated asynchronous connection supports all operations
-   * except Bind operations.
-   */
-  public static final class AuthenticatedAsynchronousConnection
-      implements AsynchronousConnection
+  public static final class AuthenticatedAsynchronousConnection implements
+      AsynchronousConnection
   {
 
     private final BindRequest request;
@@ -188,8 +83,8 @@
 
 
     private AuthenticatedAsynchronousConnection(
-        AsynchronousConnection connection, BindRequest request,
-        BindResult result)
+        final AsynchronousConnection connection, final BindRequest request,
+        final BindResult result)
     {
       this.connection = connection;
       this.request = request;
@@ -198,31 +93,17 @@
 
 
 
-    /**
-     * Returns an unmodifiable view of the Bind result which was
-     * returned from the server after authentication.
-     *
-     * @return The Bind result which was returned from the server after
-     *         authentication.
-     */
-    public BindResult getAuthenticatedBindResult()
-    {
-      return result;
-    }
-
-
-
-    public void abandon(AbandonRequest request)
+    public FutureResult<Void> abandon(final AbandonRequest request)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
-      connection.abandon(request);
+      return connection.abandon(request);
     }
 
 
 
-    public FutureResult<Result> add(AddRequest request,
-        ResultHandler<Result> handler)
+    public FutureResult<Result> add(final AddRequest request,
+        final ResultHandler<Result> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -231,8 +112,20 @@
 
 
 
+    public FutureResult<Result> add(final AddRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection
+          .add(request, resultHandler, intermediateResponseHandler);
+    }
+
+
+
     public void addConnectionEventListener(
-        ConnectionEventListener listener) throws IllegalStateException,
+        final ConnectionEventListener listener) throws IllegalStateException,
         NullPointerException
     {
       connection.addConnectionEventListener(listener);
@@ -241,12 +134,11 @@
 
 
     /**
-     * Bind operations are not supported by pre-authenticated
-     * connections. This method will always throw {@code
-     * UnsupportedOperationException}.
+     * Bind operations are not supported by pre-authenticated connections. This
+     * method will always throw {@code UnsupportedOperationException}.
      */
-    public FutureResult<BindResult> bind(BindRequest request,
-        ResultHandler<? super BindResult> handler)
+    public FutureResult<BindResult> bind(final BindRequest request,
+        final ResultHandler<? super BindResult> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -255,9 +147,14 @@
 
 
 
-    public boolean isValid()
+    public FutureResult<BindResult> bind(final BindRequest request,
+        final ResultHandler<? super BindResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
     {
-      return connection.isValid();
+      return connection.bind(request, resultHandler,
+          intermediateResponseHandler);
     }
 
 
@@ -269,7 +166,7 @@
 
 
 
-    public void close(UnbindRequest request, String reason)
+    public void close(final UnbindRequest request, final String reason)
         throws NullPointerException
     {
       connection.close(request, reason);
@@ -277,8 +174,8 @@
 
 
 
-    public FutureResult<CompareResult> compare(CompareRequest request,
-        ResultHandler<? super CompareResult> handler)
+    public FutureResult<CompareResult> compare(final CompareRequest request,
+        final ResultHandler<? super CompareResult> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -287,8 +184,20 @@
 
 
 
-    public FutureResult<Result> delete(DeleteRequest request,
-        ResultHandler<Result> handler)
+    public FutureResult<CompareResult> compare(final CompareRequest request,
+        final ResultHandler<? super CompareResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.compare(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public FutureResult<Result> delete(final DeleteRequest request,
+        final ResultHandler<Result> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -297,8 +206,20 @@
 
 
 
-    public <R extends Result> FutureResult<R> extendedRequest(
-        ExtendedRequest<R> request, ResultHandler<? super R> handler)
+    public FutureResult<Result> delete(final DeleteRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.delete(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+        final ExtendedRequest<R> request, final ResultHandler<? super R> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -307,8 +228,62 @@
 
 
 
-    public FutureResult<Result> modify(ModifyRequest request,
-        ResultHandler<Result> handler)
+    public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+        final ExtendedRequest<R> request,
+        final ResultHandler<? super R> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.extendedRequest(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    /**
+     * Returns an unmodifiable view of the Bind result which was returned from
+     * the server after authentication.
+     *
+     * @return The Bind result which was returned from the server after
+     *         authentication.
+     */
+    public BindResult getAuthenticatedBindResult()
+    {
+      return result;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Connection getSynchronousConnection()
+    {
+      return new SynchronousConnection(connection);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean isClosed()
+    {
+      return connection.isClosed();
+    }
+
+
+
+    public boolean isValid()
+    {
+      return connection.isValid();
+    }
+
+
+
+    public FutureResult<Result> modify(final ModifyRequest request,
+        final ResultHandler<Result> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -317,8 +292,20 @@
 
 
 
-    public FutureResult<Result> modifyDN(ModifyDNRequest request,
-        ResultHandler<Result> handler)
+    public FutureResult<Result> modify(final ModifyRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.modify(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+        final ResultHandler<Result> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -327,24 +314,85 @@
 
 
 
+    public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.modifyDN(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<SearchResultEntry> readEntry(final DN name,
+        final Collection<String> attributeDescriptions,
+        final ResultHandler<? super SearchResultEntry> resultHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.readEntry(name, attributeDescriptions, resultHandler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<RootDSE> readRootDSE(
+        final ResultHandler<RootDSE> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      return connection.readRootDSE(handler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<Schema> readSchema(final DN name,
+        final ResultHandler<Schema> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      return connection.readSchema(name, handler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<Schema> readSchemaForEntry(final DN name,
+        final ResultHandler<Schema> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      return connection.readSchemaForEntry(name, handler);
+    }
+
+
+
     /**
      * Re-authenticates to the Directory Server using the bind request
-     * associated with this connection. If re-authentication fails for
-     * some reason then this connection will be automatically closed.
+     * associated with this connection. If re-authentication fails for some
+     * reason then this connection will be automatically closed.
      *
      * @param handler
-     *          A result handler which can be used to asynchronously
-     *          process the operation result when it is received, may be
-     *          {@code null}.
+     *          A result handler which can be used to asynchronously process the
+     *          operation result when it is received, may be {@code null}.
      * @return A future representing the result of the operation.
      * @throws UnsupportedOperationException
      *           If this connection does not support rebind operations.
      * @throws IllegalStateException
-     *           If this connection has already been closed, i.e. if
-     *           {@code isClosed() == true}.
+     *           If this connection has already been closed, i.e. if {@code
+     *           isClosed() == true}.
      */
     public FutureResult<BindResult> rebind(
-        ResultHandler<? super BindResult> handler)
+        final ResultHandler<? super BindResult> handler)
         throws UnsupportedOperationException, IllegalStateException
     {
       if (request == null)
@@ -356,10 +404,10 @@
       // state.
       final ResultHandler<? super BindResult> clientHandler = handler;
 
-      ResultHandler<BindResult> handlerWrapper = new ResultHandler<BindResult>()
+      final ResultHandler<BindResult> handlerWrapper = new ResultHandler<BindResult>()
       {
 
-        public void handleErrorResult(ErrorResultException error)
+        public void handleErrorResult(final ErrorResultException error)
         {
           // This connection is now unauthenticated so prevent
           // further use.
@@ -373,7 +421,7 @@
 
 
 
-        public void handleResult(BindResult result)
+        public void handleResult(final BindResult result)
         {
           // Save the result.
           AuthenticatedAsynchronousConnection.this.result = result;
@@ -392,58 +440,33 @@
 
 
     public void removeConnectionEventListener(
-        ConnectionEventListener listener) throws NullPointerException
+        final ConnectionEventListener listener) throws NullPointerException
     {
       connection.removeConnectionEventListener(listener);
     }
 
 
 
-    public FutureResult<Result> search(SearchRequest request,
-        ResultHandler<Result> resultHandler,
-        SearchResultHandler searchResulthandler)
+    public FutureResult<Result> search(final SearchRequest request,
+        final ResultHandler<Result> resultHandler,
+        final SearchResultHandler searchResulthandler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
-      return connection.search(request, resultHandler,
-          searchResulthandler);
+      return connection.search(request, resultHandler, searchResulthandler);
     }
 
 
 
-    /**
-     * {@inheritDoc}
-     */
-    public boolean isClosed()
-    {
-      return connection.isClosed();
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<RootDSE> readRootDSE(
-        ResultHandler<RootDSE> handler)
-        throws UnsupportedOperationException, IllegalStateException
-    {
-      return connection.readRootDSE(handler);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<SearchResultEntry> readEntry(DN name,
-        Collection<String> attributeDescriptions,
-        ResultHandler<? super SearchResultEntry> resultHandler)
+    public FutureResult<Result> search(final SearchRequest request,
+        final ResultHandler<Result> resultHandler,
+        final SearchResultHandler searchResulthandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
-      return connection.readEntry(name, attributeDescriptions,
-          resultHandler);
+      return connection.search(request, resultHandler, searchResulthandler,
+          intermediateResponseHandler);
     }
 
 
@@ -452,63 +475,106 @@
      * {@inheritDoc}
      */
     public FutureResult<SearchResultEntry> searchSingleEntry(
-        SearchRequest request,
-        ResultHandler<? super SearchResultEntry> resultHandler)
+        final SearchRequest request,
+        final ResultHandler<? super SearchResultEntry> resultHandler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
       return connection.searchSingleEntry(request, resultHandler);
     }
 
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<Schema> readSchemaForEntry(DN name,
-        ResultHandler<Schema> handler)
-        throws UnsupportedOperationException, IllegalStateException
-    {
-      return connection.readSchemaForEntry(name, handler);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<Schema> readSchema(DN name,
-        ResultHandler<Schema> handler)
-        throws UnsupportedOperationException, IllegalStateException
-    {
-      return connection.readSchema(name, handler);
-    }
-
   }
 
 
 
   /**
-   * Creates a new authenticated connection factory which will obtain
-   * connections using the provided connection factory and immediately
-   * perform the provided Bind request.
-   *
-   * @param factory
-   *          The connection factory to use for connecting to the
-   *          Directory Server.
-   * @param request
-   *          The Bind request to use for authentication.
-   * @throws NullPointerException
-   *           If {@code factory} or {@code request} was {@code null}.
+   * An authenticated synchronous connection supports all operations except Bind
+   * operations.
    */
-  public AuthenticatedConnectionFactory(ConnectionFactory factory,
-      BindRequest request) throws NullPointerException
+  public static final class AuthenticatedConnection extends
+      SynchronousConnection
   {
-    Validator.ensureNotNull(factory, request);
-    this.parentFactory = factory;
+    private final AuthenticatedAsynchronousConnection connection;
 
-    // FIXME: should do a defensive copy.
-    this.request = request;
+
+
+    private AuthenticatedConnection(
+        final AuthenticatedAsynchronousConnection connection)
+    {
+      super(connection);
+      this.connection = connection;
+    }
+
+
+
+    /**
+     * Bind operations are not supported by pre-authenticated connections. This
+     * method will always throw {@code UnsupportedOperationException}.
+     */
+    @Override
+    public BindResult bind(final BindRequest request)
+        throws UnsupportedOperationException
+    {
+      throw new UnsupportedOperationException();
+    }
+
+
+
+    /**
+     * Bind operations are not supported by pre-authenticated connections. This
+     * method will always throw {@code UnsupportedOperationException}.
+     */
+    @Override
+    public BindResult bind(final String name, final String password)
+        throws UnsupportedOperationException
+    {
+      throw new UnsupportedOperationException();
+    }
+
+
+
+    /**
+     * Returns an unmodifiable view of the Bind result which was returned from
+     * the server after authentication.
+     *
+     * @return The Bind result which was returned from the server after
+     *         authentication.
+     */
+    public BindResult getAuthenticatedBindResult()
+    {
+      return connection.getAuthenticatedBindResult();
+    }
+
+
+
+    /**
+     * Re-authenticates to the Directory Server using the bind request
+     * associated with this connection. If re-authentication fails for some
+     * reason then this connection will be automatically closed.
+     *
+     * @return The result of the operation.
+     * @throws ErrorResultException
+     *           If the result code indicates that the request failed for some
+     *           reason.
+     * @throws InterruptedException
+     *           If the current thread was interrupted while waiting.
+     * @throws UnsupportedOperationException
+     *           If this connection does not support rebind operations.
+     * @throws IllegalStateException
+     *           If this connection has already been closed, i.e. if {@code
+     *           isClosed() == true}.
+     */
+    public BindResult rebind() throws ErrorResultException,
+        InterruptedException, UnsupportedOperationException,
+        IllegalStateException
+    {
+
+      if (connection.request == null)
+      {
+        throw new UnsupportedOperationException();
+      }
+      return super.bind(connection.request);
+    }
   }
 
 
@@ -525,16 +591,17 @@
 
 
 
-    private FutureResultImpl(BindRequest request,
-        ResultHandler<AsynchronousConnection> handler)
+    private FutureResultImpl(final BindRequest request,
+        final ResultHandler<AsynchronousConnection> handler)
     {
       this.bindRequest = request;
       this.futureBindResult = new FutureResultTransformer<BindResult, AsynchronousConnection>(
           handler)
       {
 
+        @Override
         protected ErrorResultException transformErrorResult(
-            ErrorResultException errorResult)
+            final ErrorResultException errorResult)
         {
           // Ensure that the connection is closed.
           try
@@ -542,7 +609,7 @@
             connection.close();
             connection = null;
           }
-          catch (Exception e)
+          catch (final Exception e)
           {
             // Ignore.
           }
@@ -551,8 +618,9 @@
 
 
 
+        @Override
         protected AuthenticatedAsynchronousConnection transformResult(
-            BindResult result) throws ErrorResultException
+            final BindResult result) throws ErrorResultException
         {
           // FIXME: should make the result unmodifiable.
           return new AuthenticatedAsynchronousConnection(connection,
@@ -564,9 +632,10 @@
           futureBindResult)
       {
 
+        @Override
         protected FutureResult<? extends BindResult> chainResult(
-            AsynchronousConnection innerResult,
-            ResultHandler<? super BindResult> handler)
+            final AsynchronousConnection innerResult,
+            final ResultHandler<? super BindResult> handler)
             throws ErrorResultException
         {
           connection = innerResult;
@@ -580,38 +649,61 @@
 
 
 
+  private final BindRequest request;
+
+  private final ConnectionFactory parentFactory;
+
+  private boolean allowRebinds = false;
+
+
+
   /**
-   * Specifies whether or not rebind requests are to be supported by
-   * connections created by this authenticated connection factory.
-   * <p>
-   * Rebind requests are invoked using the connection's {@code rebind}
-   * method which will throw an {@code UnsupportedOperationException} if
-   * rebinds are not supported (the default).
+   * Creates a new authenticated connection factory which will obtain
+   * connections using the provided connection factory and immediately perform
+   * the provided Bind request.
    *
-   * @param allowRebinds
-   *          {@code true} if the {@code rebind} operation is to be
-   *          supported, otherwise {@code false}.
-   * @return A reference to this connection factory.
+   * @param factory
+   *          The connection factory to use for connecting to the Directory
+   *          Server.
+   * @param request
+   *          The Bind request to use for authentication.
+   * @throws NullPointerException
+   *           If {@code factory} or {@code request} was {@code null}.
    */
-  public AuthenticatedConnectionFactory setRebindAllowed(
-      boolean allowRebinds)
+  public AuthenticatedConnectionFactory(final ConnectionFactory factory,
+      final BindRequest request) throws NullPointerException
   {
-    this.allowRebinds = allowRebinds;
-    return this;
+    Validator.ensureNotNull(factory, request);
+    this.parentFactory = factory;
+
+    // FIXME: should do a defensive copy.
+    this.request = request;
+  }
+
+
+
+  @Override
+  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      final ResultHandler<AsynchronousConnection> handler)
+  {
+    final FutureResultImpl future = new FutureResultImpl(request, handler);
+    future.futureConnectionResult.setFutureResult(parentFactory
+        .getAsynchronousConnection(future.futureConnectionResult));
+    return future.futureBindResult;
   }
 
 
 
   /**
-   * Indicates whether or not rebind requests are to be supported by
-   * connections created by this authenticated connection factory.
+   * Indicates whether or not rebind requests are to be supported by connections
+   * created by this authenticated connection factory.
    * <p>
-   * Rebind requests are invoked using the connection's {@code rebind}
-   * method which will throw an {@code UnsupportedOperationException} if
-   * rebinds are not supported (the default).
+   * Rebind requests are invoked using the connection's {@code rebind} method
+   * which will throw an {@code UnsupportedOperationException} if rebinds are
+   * not supported (the default).
    *
-   * @return allowRebinds {@code true} if the {@code rebind} operation
-   *         is to be supported, otherwise {@code false}.
+   * @return allowRebinds {@code true} if the {@code rebind} operation is to be
+   *         supported, otherwise {@code false}.
    */
   public boolean isRebindAllowed()
   {
@@ -620,22 +712,24 @@
 
 
 
-  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
-      ResultHandler<AsynchronousConnection> handler)
+  /**
+   * Specifies whether or not rebind requests are to be supported by connections
+   * created by this authenticated connection factory.
+   * <p>
+   * Rebind requests are invoked using the connection's {@code rebind} method
+   * which will throw an {@code UnsupportedOperationException} if rebinds are
+   * not supported (the default).
+   *
+   * @param allowRebinds
+   *          {@code true} if the {@code rebind} operation is to be supported,
+   *          otherwise {@code false}.
+   * @return A reference to this connection factory.
+   */
+  public AuthenticatedConnectionFactory setRebindAllowed(
+      final boolean allowRebinds)
   {
-    FutureResultImpl future = new FutureResultImpl(request, handler);
-    future.futureConnectionResult.setFutureResult(parentFactory
-        .getAsynchronousConnection(future.futureConnectionResult));
-    return future.futureBindResult;
-  }
-
-
-
-  public AuthenticatedConnection getConnection()
-      throws ErrorResultException
-  {
-    return new AuthenticatedConnection(
-        (AuthenticatedAsynchronousConnection) blockingGetAsynchronousConnection());
+    this.allowRebinds = allowRebinds;
+    return this;
   }
 
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/BooleanArgument.java b/sdk/src/com/sun/opends/sdk/tools/BooleanArgument.java
index de6d27f..a3a6f6e 100644
--- a/sdk/src/com/sun/opends/sdk/tools/BooleanArgument.java
+++ b/sdk/src/com/sun/opends/sdk/tools/BooleanArgument.java
@@ -28,20 +28,19 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_BOOLEANARG_NO_VALUE_ALLOWED;
 
 import org.opends.sdk.LocalizableMessage;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class defines an argument type that will be used to represent
- * Boolean values. These arguments will never take values from the
- * command line but and will never be required. If the argument is
- * provided, then it will be considered true, and if not then it will be
- * considered false. As such, the default value will always be "false".
+ * This class defines an argument type that will be used to represent Boolean
+ * values. These arguments will never take values from the command line but and
+ * will never be required. If the argument is provided, then it will be
+ * considered true, and if not then it will be considered false. As such, the
+ * default value will always be "false".
  */
 final class BooleanArgument extends Argument
 {
@@ -49,53 +48,25 @@
    * Creates a new Boolean argument with the provided information.
    *
    * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
+   *          The generic name that should be used to refer to this argument.
    * @param shortIdentifier
    *          The single-character identifier for this argument, or
    *          <CODE>null</CODE> if there is none.
    * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
    * @param description
    *          LocalizableMessage for the description of this argument.
    * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
    */
-  public BooleanArgument(String name, Character shortIdentifier,
-      String longIdentifier, LocalizableMessage description)
+  public BooleanArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final LocalizableMessage description)
       throws ArgumentException
   {
-    super(name, shortIdentifier, longIdentifier, false, false, false,
-        null, String.valueOf(false), null, description);
-  }
-
-
-
-  /**
-   * Indicates whether the provided value is acceptable for use in this
-   * argument.
-   *
-   * @param valueString
-   *          The value for which to make the determination.
-   * @param invalidReason
-   *          A buffer into which the invalid reason may be written if
-   *          the value is not acceptable.
-   * @return <CODE>true</CODE> if the value is acceptable, or
-   *         <CODE>false</CODE> if it is not.
-   */
-  public boolean valueIsAcceptable(String valueString,
-      LocalizableMessageBuilder invalidReason)
-  {
-    // This argument type should never have a value, so any value
-    // provided will
-    // be unacceptable.
-
-    invalidReason
-        .append(ERR_BOOLEANARG_NO_VALUE_ALLOWED.get(getName()));
-
-    return false;
+    super(name, shortIdentifier, longIdentifier, false, false, false, null,
+        String.valueOf(false), null, description);
   }
 
 
@@ -103,7 +74,8 @@
   /**
    * {@inheritDoc}
    */
-  final public void addValue(String valueString)
+  @Override
+  final public void addValue(final String valueString)
   {
     if (valueString != null)
     {
@@ -118,9 +90,37 @@
   /**
    * {@inheritDoc}
    */
-  final public void setPresent(boolean isPresent)
+  @Override
+  final public void setPresent(final boolean isPresent)
   {
     addValue(String.valueOf(isPresent));
   }
 
+
+
+  /**
+   * Indicates whether the provided value is acceptable for use in this
+   * argument.
+   *
+   * @param valueString
+   *          The value for which to make the determination.
+   * @param invalidReason
+   *          A buffer into which the invalid reason may be written if the value
+   *          is not acceptable.
+   * @return <CODE>true</CODE> if the value is acceptable, or <CODE>false</CODE>
+   *         if it is not.
+   */
+  @Override
+  public boolean valueIsAcceptable(final String valueString,
+      final LocalizableMessageBuilder invalidReason)
+  {
+    // This argument type should never have a value, so any value
+    // provided will
+    // be unacceptable.
+
+    invalidReason.append(ERR_BOOLEANARG_NO_VALUE_ALLOWED.get(getName()));
+
+    return false;
+  }
+
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/CLIException.java b/sdk/src/com/sun/opends/sdk/tools/CLIException.java
index 44ab05b..8239c57 100755
--- a/sdk/src/com/sun/opends/sdk/tools/CLIException.java
+++ b/sdk/src/com/sun/opends/sdk/tools/CLIException.java
@@ -28,7 +28,6 @@
 
 
 
-
 import org.opends.sdk.LocalizableException;
 import org.opends.sdk.LocalizableMessage;
 
@@ -37,25 +36,23 @@
 
 
 /**
- * Thrown to indicate that a problem occurred when interacting with the
- * client. For example, if input provided by the client was invalid.
+ * Thrown to indicate that a problem occurred when interacting with the client.
+ * For example, if input provided by the client was invalid.
  */
 @SuppressWarnings("serial")
-final class CLIException extends Exception implements
-    LocalizableException
+final class CLIException extends Exception implements LocalizableException
 {
 
   /**
-   * Adapts any exception that may have occurred whilst reading input
-   * from the console.
+   * Adapts any exception that may have occurred whilst reading input from the
+   * console.
    *
    * @param cause
-   *          The exception that occurred whilst reading input from the
-   *          console.
-   * @return Returns a new CLI exception describing a problem that
-   *         occurred whilst reading input from the console.
+   *          The exception that occurred whilst reading input from the console.
+   * @return Returns a new CLI exception describing a problem that occurred
+   *         whilst reading input from the console.
    */
-  static CLIException adaptInputException(Throwable cause)
+  static CLIException adaptInputException(final Throwable cause)
   {
     return new CLIException(Messages.ERR_CONSOLE_INPUT_ERROR.get(cause
         .getMessage()), cause);
@@ -63,13 +60,17 @@
 
 
 
+  private final LocalizableMessage message;
+
+
+
   /**
    * Creates a new CLI exception with the provided message.
    *
    * @param message
    *          The message explaining the problem that occurred.
    */
-  CLIException(LocalizableMessage message)
+  CLIException(final LocalizableMessage message)
   {
     super(message.toString());
     this.message = message;
@@ -85,7 +86,7 @@
    * @param cause
    *          The cause of this exception.
    */
-  CLIException(LocalizableMessage message, Throwable cause)
+  CLIException(final LocalizableMessage message, final Throwable cause)
   {
     super(message.toString(), cause);
     this.message = message;
@@ -93,10 +94,6 @@
 
 
 
-  private final LocalizableMessage message;
-
-
-
   public LocalizableMessage getMessageObject()
   {
     return message;
diff --git a/sdk/src/com/sun/opends/sdk/tools/ConsoleApplication.java b/sdk/src/com/sun/opends/sdk/tools/ConsoleApplication.java
index 06f77e2..077c02a 100755
--- a/sdk/src/com/sun/opends/sdk/tools/ConsoleApplication.java
+++ b/sdk/src/com/sun/opends/sdk/tools/ConsoleApplication.java
@@ -28,8 +28,11 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.tools.Utils.*;
+import static com.sun.opends.sdk.messages.Messages.INFO_ERROR_EMPTY_RESPONSE;
+import static com.sun.opends.sdk.messages.Messages.INFO_MENU_PROMPT_RETURN_TO_CONTINUE;
+import static com.sun.opends.sdk.messages.Messages.INFO_PROMPT_SINGLE_DEFAULT;
+import static com.sun.opends.sdk.tools.Utils.MAX_LINE_WIDTH;
+import static com.sun.opends.sdk.tools.Utils.wrapText;
 
 import java.io.*;
 import java.util.logging.Level;
@@ -39,10 +42,9 @@
 
 
 
-
 /**
- * This class provides an abstract base class which can be used as the
- * basis of a console-based application.
+ * This class provides an abstract base class which can be used as the basis of
+ * a console-based application.
  */
 abstract class ConsoleApplication
 {
@@ -51,13 +53,12 @@
     /**
      * The singleton instance for this class.
      */
-    private static final NullOutputStream instance = new NullOutputStream();
+    private static final NullOutputStream INSTANCE = new NullOutputStream();
 
     /**
      * The singleton print stream tied to the null output stream.
      */
-    private static final PrintStream printStream = new PrintStream(
-        instance);
+    private static final PrintStream PRINT_STREAM = new PrintStream(INSTANCE);
 
 
 
@@ -68,7 +69,7 @@
      */
     static PrintStream printStream()
     {
-      return printStream;
+      return PRINT_STREAM;
     }
 
 
@@ -86,6 +87,7 @@
     /**
      * Closes the output stream. This has no effect.
      */
+    @Override
     public void close()
     {
       // No implementation is required.
@@ -96,6 +98,7 @@
     /**
      * Flushes the output stream. This has no effect.
      */
+    @Override
     public void flush()
     {
       // No implementation is required.
@@ -104,13 +107,13 @@
 
 
     /**
-     * Writes the provided data to this output stream. This has no
-     * effect.
+     * Writes the provided data to this output stream. This has no effect.
      *
      * @param b
      *          The byte array containing the data to be written.
      */
-    public void write(byte[] b)
+    @Override
+    public void write(final byte[] b)
     {
       // No implementation is required.
     }
@@ -118,8 +121,7 @@
 
 
     /**
-     * Writes the provided data to this output stream. This has no
-     * effect.
+     * Writes the provided data to this output stream. This has no effect.
      *
      * @param b
      *          The byte array containing the data to be written.
@@ -128,7 +130,8 @@
      * @param len
      *          The number of bytes to be written.
      */
-    public void write(byte[] b, int off, int len)
+    @Override
+    public void write(final byte[] b, final int off, final int len)
     {
       // No implementation is required.
     }
@@ -136,13 +139,13 @@
 
 
     /**
-     * Writes the provided byte to this output stream. This has no
-     * effect.
+     * Writes the provided byte to this output stream. This has no effect.
      *
      * @param b
      *          The byte to be written.
      */
-    public void write(int b)
+    @Override
+    public void write(final int b)
     {
       // No implementation is required.
     }
@@ -171,7 +174,8 @@
      * {@inheritDoc}
      */
     @Override
-    public int read(char[] cbuf, int off, int len) throws IOException
+    public int read(final char[] cbuf, final int off, final int len)
+        throws IOException
     {
       return -1;
     }
@@ -202,7 +206,8 @@
    * @param err
    *          The application error stream.
    */
-  ConsoleApplication(InputStream in, OutputStream out, OutputStream err)
+  ConsoleApplication(final InputStream in, final OutputStream out,
+      final OutputStream err)
   {
     this.in = in;
     if (in != null)
@@ -286,19 +291,17 @@
   /**
    * Indicates whether or not the user has requested advanced mode.
    *
-   * @return Returns <code>true</code> if the user has requested
-   *         advanced mode.
+   * @return Returns <code>true</code> if the user has requested advanced mode.
    */
   abstract boolean isAdvancedMode();
 
 
 
   /**
-   * Indicates whether or not the user has requested interactive
-   * behavior.
+   * Indicates whether or not the user has requested interactive behavior.
    *
-   * @return Returns <code>true</code> if the user has requested
-   *         interactive behavior.
+   * @return Returns <code>true</code> if the user has requested interactive
+   *         behavior.
    */
   abstract boolean isInteractive();
 
@@ -306,13 +309,12 @@
 
   /**
    * Indicates whether or not this console application is running in its
-   * menu-driven mode. This can be used to dictate whether output should
-   * go to the error stream or not. In addition, it may also dictate
-   * whether or not sub-menus should display a cancel option as well as
-   * a quit option.
+   * menu-driven mode. This can be used to dictate whether output should go to
+   * the error stream or not. In addition, it may also dictate whether or not
+   * sub-menus should display a cancel option as well as a quit option.
    *
-   * @return Returns <code>true</code> if this console application is
-   *         running in its menu-driven mode.
+   * @return Returns <code>true</code> if this console application is running in
+   *         its menu-driven mode.
    */
   abstract boolean isMenuDrivenMode();
 
@@ -321,19 +323,17 @@
   /**
    * Indicates whether or not the user has requested quiet output.
    *
-   * @return Returns <code>true</code> if the user has requested quiet
-   *         output.
+   * @return Returns <code>true</code> if the user has requested quiet output.
    */
   abstract boolean isQuiet();
 
 
 
   /**
-   * Indicates whether or not the user has requested script-friendly
-   * output.
+   * Indicates whether or not the user has requested script-friendly output.
    *
-   * @return Returns <code>true</code> if the user has requested
-   *         script-friendly output.
+   * @return Returns <code>true</code> if the user has requested script-friendly
+   *         output.
    */
   abstract boolean isScriptFriendly();
 
@@ -342,28 +342,26 @@
   /**
    * Indicates whether or not the user has requested verbose output.
    *
-   * @return Returns <code>true</code> if the user has requested verbose
-   *         output.
+   * @return Returns <code>true</code> if the user has requested verbose output.
    */
   abstract boolean isVerbose();
 
 
 
   /**
-   * Interactively prompts the user to press return to continue. This
-   * method should be called in situations where a user needs to be
-   * given a chance to read some documentation before continuing
-   * (continuing may cause the documentation to be scrolled out of
-   * view).
+   * Interactively prompts the user to press return to continue. This method
+   * should be called in situations where a user needs to be given a chance to
+   * read some documentation before continuing (continuing may cause the
+   * documentation to be scrolled out of view).
    */
   final void pressReturnToContinue()
   {
-    LocalizableMessage msg = INFO_MENU_PROMPT_RETURN_TO_CONTINUE.get();
+    final LocalizableMessage msg = INFO_MENU_PROMPT_RETURN_TO_CONTINUE.get();
     try
     {
       readLineOfInput(msg);
     }
-    catch (CLIException e)
+    catch (final CLIException e)
     {
       // Ignore the exception - applications don't care.
     }
@@ -372,6 +370,19 @@
 
 
   /**
+   * Displays a message to the error stream.
+   *
+   * @param msg
+   *          The message.
+   */
+  final void print(final LocalizableMessage msg)
+  {
+    err.print(wrapText(msg, MAX_LINE_WIDTH));
+  }
+
+
+
+  /**
    * Displays a blank line to the error stream.
    */
   final void println()
@@ -387,7 +398,7 @@
    * @param msg
    *          The message.
    */
-  final void println(LocalizableMessage msg)
+  final void println(final LocalizableMessage msg)
   {
     err.println(wrapText(msg, MAX_LINE_WIDTH));
   }
@@ -395,21 +406,23 @@
 
 
   /**
-   * Displays a message to the error stream.
+   * Displays a message to the error stream indented by the specified number of
+   * columns.
    *
    * @param msg
    *          The message.
+   * @param indent
+   *          The number of columns to indent.
    */
-  final void print(LocalizableMessage msg)
+  final void println(final LocalizableMessage msg, final int indent)
   {
-    err.print(wrapText(msg, MAX_LINE_WIDTH));
+    err.println(wrapText(msg, MAX_LINE_WIDTH, indent));
   }
 
 
 
   /**
-   * Displays a blank line to the output stream if we are not in quiet
-   * mode.
+   * Displays a blank line to the output stream if we are not in quiet mode.
    */
   final void printlnProgress()
   {
@@ -422,13 +435,12 @@
 
 
   /**
-   * Displays a message to the output stream if we are not in quiet
-   * mode.
+   * Displays a message to the output stream if we are not in quiet mode.
    *
    * @param msg
    *          The message.
    */
-  final void printProgress(LocalizableMessage msg)
+  final void printProgress(final LocalizableMessage msg)
   {
     if (!isQuiet())
     {
@@ -439,28 +451,12 @@
 
 
   /**
-   * Displays a message to the error stream indented by the specified
-   * number of columns.
-   *
-   * @param msg
-   *          The message.
-   * @param indent
-   *          The number of columns to indent.
-   */
-  final void println(LocalizableMessage msg, int indent)
-  {
-    err.println(wrapText(msg, MAX_LINE_WIDTH, indent));
-  }
-
-
-
-  /**
    * Displays a message to the error stream if verbose mode is enabled.
    *
    * @param msg
    *          The verbose message.
    */
-  final void printVerboseMessage(LocalizableMessage msg)
+  final void printVerboseMessage(final LocalizableMessage msg)
   {
     if (isVerbose() || isInteractive())
     {
@@ -471,73 +467,31 @@
 
 
   /**
-   * Interactively retrieves a line of input from the console.
-   *
-   * @param prompt
-   *          The prompt.
-   * @return Returns the line of input, or <code>null</code> if the end
-   *         of input has been reached.
-   * @throws CLIException
-   *           If the line of input could not be retrieved for some
-   *           reason.
-   */
-  final String readLineOfInput(LocalizableMessage prompt) throws CLIException
-  {
-    if (prompt != null)
-    {
-      err.print(wrapText(prompt, MAX_LINE_WIDTH));
-      err.print(" ");
-    }
-    try
-    {
-      String s = reader.readLine();
-      if (s == null)
-      {
-        throw CLIException.adaptInputException(new EOFException(
-            "End of input"));
-      }
-      else
-      {
-        return s;
-      }
-    }
-    catch (IOException e)
-    {
-      throw CLIException.adaptInputException(e);
-    }
-  }
-
-
-
-  /**
-   * Commodity method that interactively prompts (on error output) the
-   * user to provide a string value. Any non-empty string will be
-   * allowed (the empty string will indicate that the default should be
-   * used, if there is one).
+   * Commodity method that interactively prompts (on error output) the user to
+   * provide a string value. Any non-empty string will be allowed (the empty
+   * string will indicate that the default should be used, if there is one).
    *
    * @param prompt
    *          The prompt to present to the user.
    * @param defaultValue
-   *          The default value to assume if the user presses ENTER
-   *          without typing anything, or <CODE>null</CODE> if there
-   *          should not be a default and the user must explicitly
-   *          provide a value.
+   *          The default value to assume if the user presses ENTER without
+   *          typing anything, or <CODE>null</CODE> if there should not be a
+   *          default and the user must explicitly provide a value.
    * @throws CLIException
-   *           If the line of input could not be retrieved for some
-   *           reason.
+   *           If the line of input could not be retrieved for some reason.
    * @return The string value read from the user.
    */
-  final String readInput(LocalizableMessage prompt, String defaultValue)
+  final String readInput(LocalizableMessage prompt, final String defaultValue)
       throws CLIException
   {
     while (true)
     {
       if (defaultValue != null)
       {
-        prompt = INFO_PROMPT_SINGLE_DEFAULT.get(prompt.toString(),
-            defaultValue);
+        prompt = INFO_PROMPT_SINGLE_DEFAULT
+            .get(prompt.toString(), defaultValue);
       }
-      String response = readLineOfInput(prompt);
+      final String response = readLineOfInput(prompt);
 
       if ("".equals(response))
       {
@@ -560,36 +514,73 @@
 
 
   /**
-   * Commodity method that interactively prompts (on error output) the
-   * user to provide a string value. Any non-empty string will be
-   * allowed (the empty string will indicate that the default should be
-   * used, if there is one). If an error occurs a message will be logged
-   * to the provided logger.
+   * Commodity method that interactively prompts (on error output) the user to
+   * provide a string value. Any non-empty string will be allowed (the empty
+   * string will indicate that the default should be used, if there is one). If
+   * an error occurs a message will be logged to the provided logger.
    *
    * @param prompt
    *          The prompt to present to the user.
    * @param defaultValue
-   *          The default value to assume if the user presses ENTER
-   *          without typing anything, or <CODE>null</CODE> if there
-   *          should not be a default and the user must explicitly
-   *          provide a value.
+   *          The default value to assume if the user presses ENTER without
+   *          typing anything, or <CODE>null</CODE> if there should not be a
+   *          default and the user must explicitly provide a value.
    * @param logger
    *          the Logger to be used to log the error message.
    * @return The string value read from the user.
    */
-  final String readInput(LocalizableMessage prompt, String defaultValue,
-      Logger logger)
+  final String readInput(final LocalizableMessage prompt,
+      final String defaultValue, final Logger logger)
   {
     String s = defaultValue;
     try
     {
       s = readInput(prompt, defaultValue);
     }
-    catch (CLIException ce)
+    catch (final CLIException ce)
     {
       logger.log(Level.WARNING, "Error reading input: " + ce, ce);
     }
     return s;
   }
 
+
+
+  /**
+   * Interactively retrieves a line of input from the console.
+   *
+   * @param prompt
+   *          The prompt.
+   * @return Returns the line of input, or <code>null</code> if the end of input
+   *         has been reached.
+   * @throws CLIException
+   *           If the line of input could not be retrieved for some reason.
+   */
+  final String readLineOfInput(final LocalizableMessage prompt)
+      throws CLIException
+  {
+    if (prompt != null)
+    {
+      err.print(wrapText(prompt, MAX_LINE_WIDTH));
+      err.print(" ");
+    }
+    try
+    {
+      final String s = reader.readLine();
+      if (s == null)
+      {
+        throw CLIException
+            .adaptInputException(new EOFException("End of input"));
+      }
+      else
+      {
+        return s;
+      }
+    }
+    catch (final IOException e)
+    {
+      throw CLIException.adaptInputException(e);
+    }
+  }
+
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/DataSource.java b/sdk/src/com/sun/opends/sdk/tools/DataSource.java
index 5e6dd9a..4c4438f 100644
--- a/sdk/src/com/sun/opends/sdk/tools/DataSource.java
+++ b/sdk/src/com/sun/opends/sdk/tools/DataSource.java
@@ -45,43 +45,57 @@
 {
   private static interface IDataSource
   {
-    public Object getData();
-
-
-
     public IDataSource duplicate();
+
+
+
+    public Object getData();
   }
 
 
 
-  private static class RandomNumberDataSource implements IDataSource
+  private static class IncrementLineFileDataSource implements IDataSource
   {
-    private final Random random;
-    private final int offset;
-    private final int range;
+    private final List<String> lines;
+    private int next;
 
 
 
-    public RandomNumberDataSource(long seed, int low, int high)
+    public IncrementLineFileDataSource(final String file) throws IOException
     {
-      random = new Random(seed);
-      offset = low;
-      range = high - low;
+      lines = new ArrayList<String>();
+      final BufferedReader in = new BufferedReader(new FileReader(file));
+      String line;
+      while ((line = in.readLine()) != null)
+      {
+        lines.add(line);
+      }
     }
 
 
 
-    public Object getData()
+    private IncrementLineFileDataSource(final List<String> lines)
     {
-      return random.nextInt(range) + offset;
+      this.lines = lines;
     }
 
 
 
     public IDataSource duplicate()
     {
-      // There is no state info so threads can just share one instance.
-      return this;
+      return new IncrementLineFileDataSource(lines);
+    }
+
+
+
+    public Object getData()
+    {
+      if (next == lines.size())
+      {
+        next = 0;
+      }
+
+      return lines.get(next++);
     }
   }
 
@@ -95,7 +109,7 @@
 
 
 
-    public IncrementNumberDataSource(int low, int high)
+    public IncrementNumberDataSource(final int low, final int high)
     {
       this.low = this.next = low;
       this.high = high;
@@ -103,6 +117,13 @@
 
 
 
+    public IDataSource duplicate()
+    {
+      return new IncrementNumberDataSource(low, high);
+    }
+
+
+
     public Object getData()
     {
       if (next == high)
@@ -113,13 +134,6 @@
 
       return next++;
     }
-
-
-
-    public IDataSource duplicate()
-    {
-      return new IncrementNumberDataSource(low, high);
-    }
   }
 
 
@@ -131,12 +145,12 @@
 
 
 
-    public RandomLineFileDataSource(long seed, String file)
+    public RandomLineFileDataSource(final long seed, final String file)
         throws IOException
     {
       lines = new ArrayList<String>();
       random = new Random(seed);
-      BufferedReader in = new BufferedReader(new FileReader(file));
+      final BufferedReader in = new BufferedReader(new FileReader(file));
       String line;
       while ((line = in.readLine()) != null)
       {
@@ -146,70 +160,55 @@
 
 
 
-    public Object getData()
-    {
-      return lines.get(random.nextInt(lines.size()));
-    }
-
-
-
     public IDataSource duplicate()
     {
       return this;
     }
-  }
-
-
-
-  private static class IncrementLineFileDataSource implements
-      IDataSource
-  {
-    private final List<String> lines;
-    private int next;
-
-
-
-    public IncrementLineFileDataSource(String file) throws IOException
-    {
-      lines = new ArrayList<String>();
-      BufferedReader in = new BufferedReader(new FileReader(file));
-      String line;
-      while ((line = in.readLine()) != null)
-      {
-        lines.add(line);
-      }
-    }
-
-
-
-    private IncrementLineFileDataSource(List<String> lines)
-    {
-      this.lines = lines;
-    }
 
 
 
     public Object getData()
     {
-      if (next == lines.size())
-      {
-        next = 0;
-      }
+      return lines.get(random.nextInt(lines.size()));
+    }
+  }
 
-      return lines.get(next++);
+
+
+  private static class RandomNumberDataSource implements IDataSource
+  {
+    private final Random random;
+    private final int offset;
+    private final int range;
+
+
+
+    public RandomNumberDataSource(final long seed, final int low, final int high)
+    {
+      random = new Random(seed);
+      offset = low;
+      range = high - low;
     }
 
 
 
     public IDataSource duplicate()
     {
-      return new IncrementLineFileDataSource(lines);
+      // There is no state info so threads can just share one instance.
+      return this;
+    }
+
+
+
+    public Object getData()
+    {
+      return random.nextInt(range) + offset;
     }
   }
 
 
 
-  private static class RandomStringDataSource implements IDataSource
+  private static final class RandomStringDataSource implements IDataSource
   {
     private final Random random;
     private final int length;
@@ -217,19 +216,20 @@
 
 
 
-    private RandomStringDataSource(int seed, int length, String charSet)
+    private RandomStringDataSource(final int seed, final int length,
+        final String charSet)
     {
       this.length = length;
-      Set<Character> chars = new HashSet<Character>();
+      final Set<Character> chars = new HashSet<Character>();
       for (int i = 0; i < charSet.length(); i++)
       {
-        char c = charSet.charAt(i);
+        final char c = charSet.charAt(i);
         if (c == '[')
         {
           i += 1;
-          char start = charSet.charAt(i);
+          final char start = charSet.charAt(i);
           i += 2;
-          char end = charSet.charAt(i);
+          final char end = charSet.charAt(i);
           i += 1;
           for (int j = start; j <= end; j++)
           {
@@ -247,74 +247,208 @@
 
 
 
+    public IDataSource duplicate()
+    {
+      return this;
+    }
+
+
+
     public Object getData()
     {
-      char[] str = new char[length];
+      final char[] str = new char[length];
       for (int i = 0; i < length; i++)
       {
         str[i] = charSet[random.nextInt(charSet.length)];
       }
       return new String(str);
     }
-
-
-
-    public IDataSource duplicate()
-    {
-      return this;
-    }
   }
 
 
 
-  private static class StaticDataSource implements IDataSource
+  private static final class StaticDataSource implements IDataSource
   {
     private final Object data;
 
 
 
-    private StaticDataSource(Object data)
+    private StaticDataSource(final Object data)
     {
       this.data = data;
     }
 
 
 
-    public Object getData()
-    {
-      return data;
-    }
-
-
-
     public IDataSource duplicate()
     {
       // There is no state info so threads can just share one instance.
       return this;
     }
+
+
+
+    public Object getData()
+    {
+      return data;
+    }
   }
 
-  private IDataSource impl;
+
+
+  /**
+   * Returns Generated data from the specified data sources. Generated data will
+   * be placed in the specified data array. If the data array is null or smaller
+   * than the number of data sources, one will be allocated.
+   *
+   * @param dataSources
+   *          Data sources that will generate arguments referenced by the format
+   *          specifiers in the format string.
+   * @param data
+   *          The array where genereated data will be placed to format the
+   *          string.
+   * @return A formatted string
+   */
+  public static Object[] generateData(final DataSource[] dataSources,
+      Object[] data)
+  {
+    if (data == null || data.length < dataSources.length)
+    {
+      data = new Object[dataSources.length];
+    }
+    for (int i = 0; i < dataSources.length; i++)
+    {
+      data[i] = dataSources[i].getData();
+    }
+    return data;
+  }
 
 
 
-  private DataSource(IDataSource impl)
+  /**
+   * Parses a list of source definitions into an array of data source objects. A
+   * data source is defined as follows: - rand({min},{max}) generates a random
+   * integer between the min and max. - rand({filename}) retrieves a random line
+   * from a file. - inc({min},{max}) returns incremental integer between the min
+   * and max. - inc({filename}) retrieves lines in order from a file. - {number}
+   * always return the integer as given. - {string} always return the string as
+   * given.
+   *
+   * @param sources
+   *          The list of source definitions to parse.
+   * @return The array of parsed data sources.
+   * @throws IOException
+   *           If an exception occurs while reading a file.
+   */
+  public static DataSource[] parse(final List<String> sources)
+      throws IOException
+  {
+    Validator.ensureNotNull(sources);
+    final DataSource[] dataSources = new DataSource[sources.size()];
+    for (int i = 0; i < sources.size(); i++)
+    {
+      final String dataSourceDef = sources.get(i);
+      if (dataSourceDef.startsWith("rand(") && dataSourceDef.endsWith(")"))
+      {
+        final int lparenPos = dataSourceDef.indexOf("(");
+        final int commaPos = dataSourceDef.indexOf(",");
+        final int rparenPos = dataSourceDef.indexOf(")");
+        if (commaPos < 0)
+        {
+          // This is a file name
+          dataSources[i] = new DataSource(new RandomLineFileDataSource(0,
+              dataSourceDef.substring(lparenPos + 1, rparenPos)));
+        }
+        else
+        {
+          // This range of integers
+          final int low = Integer.parseInt(dataSourceDef.substring(
+              lparenPos + 1, commaPos));
+          final int high = Integer.parseInt(dataSourceDef.substring(
+              commaPos + 1, rparenPos));
+          dataSources[i] = new DataSource(new RandomNumberDataSource(Thread
+              .currentThread().getId(), low, high));
+        }
+      }
+      else if (dataSourceDef.startsWith("randstr(")
+          && dataSourceDef.endsWith(")"))
+      {
+        final int lparenPos = dataSourceDef.indexOf("(");
+        final int commaPos = dataSourceDef.indexOf(",");
+        final int rparenPos = dataSourceDef.indexOf(")");
+        int length;
+        String charSet;
+        if (commaPos < 0)
+        {
+          length = Integer.parseInt(dataSourceDef.substring(lparenPos + 1,
+              rparenPos));
+          charSet = "[A-Z][a-z][0-9]";
+        }
+        else
+        {
+          // length and charSet
+          length = Integer.parseInt(dataSourceDef.substring(lparenPos + 1,
+              commaPos));
+          charSet = dataSourceDef.substring(commaPos + 1, rparenPos);
+        }
+        dataSources[i] = new DataSource(new RandomStringDataSource(0, length,
+            charSet));
+
+      }
+      else if (dataSourceDef.startsWith("inc(") && dataSourceDef.endsWith(")"))
+      {
+        final int lparenPos = dataSourceDef.indexOf("(");
+        final int commaPos = dataSourceDef.indexOf(",");
+        final int rparenPos = dataSourceDef.indexOf(")");
+        if (commaPos < 0)
+        {
+          // This is a file name
+          dataSources[i] = new DataSource(new IncrementLineFileDataSource(
+              dataSourceDef.substring(lparenPos + 1, rparenPos)));
+        }
+        else
+        {
+          final int low = Integer.parseInt(dataSourceDef.substring(
+              lparenPos + 1, commaPos));
+          final int high = Integer.parseInt(dataSourceDef.substring(
+              commaPos + 1, rparenPos));
+          dataSources[i] = new DataSource(new IncrementNumberDataSource(low,
+              high));
+        }
+      }
+      else
+      {
+        try
+        {
+          dataSources[i] = new DataSource(new StaticDataSource(Integer
+              .parseInt(dataSourceDef)));
+        }
+        catch (final NumberFormatException nfe)
+        {
+          dataSources[i] = new DataSource(new StaticDataSource(dataSourceDef));
+        }
+      }
+    }
+
+    return dataSources;
+  }
+
+
+
+  private final IDataSource impl;
+
+
+
+  private DataSource(final IDataSource impl)
   {
     this.impl = impl;
   }
 
 
 
-  public Object getData()
-  {
-    return impl.getData();
-  }
-
-
-
   public DataSource duplicate()
   {
-    IDataSource dup = impl.duplicate();
+    final IDataSource dup = impl.duplicate();
     if (dup == impl)
     {
       return this;
@@ -327,155 +461,8 @@
 
 
 
-  /**
-   * Parses a list of source definitions into an array of data source
-   * objects. A data source is defined as follows: - rand({min},{max})
-   * generates a random integer between the min and max. -
-   * rand({filename}) retrieves a random line from a file. -
-   * inc({min},{max}) returns incremental integer between the min and
-   * max. - inc({filename}) retrieves lines in order from a file. -
-   * {number} always return the integer as given. - {string} always
-   * return the string as given.
-   * 
-   * @param sources
-   *          The list of source definitions to parse.
-   * @return The array of parsed data sources.
-   * @throws IOException
-   *           If an exception occurs while reading a file.
-   */
-  public static DataSource[] parse(List<String> sources)
-      throws IOException
+  public Object getData()
   {
-    Validator.ensureNotNull(sources);
-    DataSource[] dataSources = new DataSource[sources.size()];
-    for (int i = 0; i < sources.size(); i++)
-    {
-      String dataSourceDef = sources.get(i);
-      if (dataSourceDef.startsWith("rand(")
-          && dataSourceDef.endsWith(")"))
-      {
-        int lparenPos = dataSourceDef.indexOf("(");
-        int commaPos = dataSourceDef.indexOf(",");
-        int rparenPos = dataSourceDef.indexOf(")");
-        if (commaPos < 0)
-        {
-          // This is a file name
-          dataSources[i] =
-              new DataSource(new RandomLineFileDataSource(0,
-                  dataSourceDef.substring(lparenPos + 1, rparenPos)));
-        }
-        else
-        {
-          // This range of integers
-          int low =
-              Integer.parseInt(dataSourceDef.substring(lparenPos + 1,
-                  commaPos));
-          int high =
-              Integer.parseInt(dataSourceDef.substring(commaPos + 1,
-                  rparenPos));
-          dataSources[i] =
-              new DataSource(new RandomNumberDataSource(0, low, high));
-        }
-      }
-      else if (dataSourceDef.startsWith("randstr(")
-          && dataSourceDef.endsWith(")"))
-      {
-        int lparenPos = dataSourceDef.indexOf("(");
-        int commaPos = dataSourceDef.indexOf(",");
-        int rparenPos = dataSourceDef.indexOf(")");
-        int length;
-        String charSet;
-        if (commaPos < 0)
-        {
-          length =
-              Integer.parseInt(dataSourceDef.substring(lparenPos + 1,
-                  rparenPos));
-          charSet = "[A-Z][a-z][0-9]";
-        }
-        else
-        {
-          // length and charSet
-          length =
-              Integer.parseInt(dataSourceDef.substring(lparenPos + 1,
-                  commaPos));
-          charSet = dataSourceDef.substring(commaPos + 1, rparenPos);
-        }
-        dataSources[i] =
-            new DataSource(new RandomStringDataSource(0, length,
-                charSet));
-
-      }
-      else if (dataSourceDef.startsWith("inc(")
-          && dataSourceDef.endsWith(")"))
-      {
-        int lparenPos = dataSourceDef.indexOf("(");
-        int commaPos = dataSourceDef.indexOf(",");
-        int rparenPos = dataSourceDef.indexOf(")");
-        if (commaPos < 0)
-        {
-          // This is a file name
-          dataSources[i] =
-              new DataSource(new IncrementLineFileDataSource(
-                  dataSourceDef.substring(lparenPos + 1, rparenPos)));
-        }
-        else
-        {
-          int low =
-              Integer.parseInt(dataSourceDef.substring(lparenPos + 1,
-                  commaPos));
-          int high =
-              Integer.parseInt(dataSourceDef.substring(commaPos + 1,
-                  rparenPos));
-          dataSources[i] =
-              new DataSource(new IncrementNumberDataSource(low, high));
-        }
-      }
-      else
-      {
-        try
-        {
-          dataSources[i] =
-              new DataSource(new StaticDataSource(Integer
-                  .parseInt(dataSourceDef)));
-        }
-        catch (NumberFormatException nfe)
-        {
-          dataSources[i] =
-              new DataSource(new StaticDataSource(dataSourceDef));
-        }
-      }
-    }
-
-    return dataSources;
-  }
-
-
-
-  /**
-   * Returns Generated data from the specified data sources. Generated
-   * data will be placed in the specified data array. If the data array
-   * is null or smaller than the number of data sources, one will be
-   * allocated.
-   * 
-   * @param dataSources
-   *          Data sources that will generate arguments referenced by
-   *          the format specifiers in the format string.
-   * @param data
-   *          The array where genereated data will be placed to format
-   *          the string.
-   * @return A formatted string
-   */
-  public static Object[] generateData(DataSource[] dataSources,
-      Object[] data)
-  {
-    if (data == null || data.length < dataSources.length)
-    {
-      data = new Object[dataSources.length];
-    }
-    for (int i = 0; i < dataSources.length; i++)
-    {
-      data[i] = dataSources[i].getData();
-    }
-    return data;
+    return impl.getData();
   }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/DistrustAllTrustManager.java b/sdk/src/com/sun/opends/sdk/tools/DistrustAllTrustManager.java
deleted file mode 100644
index aed7cca..0000000
--- a/sdk/src/com/sun/opends/sdk/tools/DistrustAllTrustManager.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2008 Sun Microsystems, Inc.
- */
-
-package com.sun.opends.sdk.tools;
-
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.X509TrustManager;
-
-/**
- * An X509TrustManager which trusts everything.
- */
-final class DistrustAllTrustManager implements X509TrustManager {
-
-  /**
-   * {@inheritDoc}
-   */
-  public void checkClientTrusted(X509Certificate[] chain, String authType)
-  throws CertificateException
-  {
-    throw new CertificateException();
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public void checkServerTrusted(X509Certificate[] chain, String authType)
-  throws CertificateException
-  {
-    throw new CertificateException();
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public X509Certificate[] getAcceptedIssuers()
-  {
-    return new X509Certificate[0];
-  }
-}
-
diff --git a/sdk/src/com/sun/opends/sdk/tools/FileBasedArgument.java b/sdk/src/com/sun/opends/sdk/tools/FileBasedArgument.java
index c476bf2..0c333c9 100644
--- a/sdk/src/com/sun/opends/sdk/tools/FileBasedArgument.java
+++ b/sdk/src/com/sun/opends/sdk/tools/FileBasedArgument.java
@@ -29,7 +29,7 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -41,28 +41,27 @@
 
 
 
-
 /**
- * This class defines an argument whose value will be read from a file
- * rather than actually specified on the command-line. When a value is
- * specified on the command line, it will be treated as the path to the
- * file containing the actual value rather than the value itself. <BR>
+ * This class defines an argument whose value will be read from a file rather
+ * than actually specified on the command-line. When a value is specified on the
+ * command line, it will be treated as the path to the file containing the
+ * actual value rather than the value itself. <BR>
  * <BR>
- * Note that if if no filename is provided on the command line but a
- * default value is specified programatically or if the default value is
- * read from a specified property, then that default value will be taken
- * as the actual value rather than a filename. <BR>
+ * Note that if if no filename is provided on the command line but a default
+ * value is specified programatically or if the default value is read from a
+ * specified property, then that default value will be taken as the actual value
+ * rather than a filename. <BR>
  * <BR>
- * Also note that this argument type assumes that the entire value for
- * the argument is on a single line in the specified file. If the file
- * contains multiple lines, then only the first line will be read.
+ * Also note that this argument type assumes that the entire value for the
+ * argument is on a single line in the specified file. If the file contains
+ * multiple lines, then only the first line will be read.
  */
 final class FileBasedArgument extends Argument
 {
   // The mapping between filenames specified and the first lines read
   // from those
   // files.
-  private LinkedHashMap<String, String> namesToValues;
+  private final LinkedHashMap<String, String> namesToValues;
 
 
 
@@ -70,86 +69,45 @@
    * Creates a new file-based argument with the provided information.
    *
    * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
+   *          The generic name that should be used to refer to this argument.
    * @param shortIdentifier
    *          The single-character identifier for this argument, or
    *          <CODE>null</CODE> if there is none.
    * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
    * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
-   * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
-   * @param description
-   *          LocalizableMessage for the description of this argument.
-   * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
-   */
-  public FileBasedArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired,
-      LocalizableMessage valuePlaceholder, LocalizableMessage description)
-      throws ArgumentException
-  {
-    super(name, shortIdentifier, longIdentifier, isRequired, false,
-        true, valuePlaceholder, null, null, description);
-
-    namesToValues = new LinkedHashMap<String, String>();
-  }
-
-
-
-  /**
-   * Creates a new file-based argument with the provided information.
-   *
-   * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
-   * @param shortIdentifier
-   *          The single-character identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
+   *          Indicates whether this argument must be specified on the command
+   *          line.
    * @param isMultiValued
-   *          Indicates whether this argument may be specified more than
-   *          once to provide multiple values.
+   *          Indicates whether this argument may be specified more than once to
+   *          provide multiple values.
    * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
    * @param defaultValue
-   *          The default value that should be used for this argument if
-   *          none is provided in a properties file or on the command
-   *          line. This may be <CODE>null</CODE> if there is no generic
-   *          default.
+   *          The default value that should be used for this argument if none is
+   *          provided in a properties file or on the command line. This may be
+   *          <CODE>null</CODE> if there is no generic default.
    * @param propertyName
-   *          The name of the property in a property file that may be
-   *          used to override the default value but will be overridden
-   *          by a command-line argument.
+   *          The name of the property in a property file that may be used to
+   *          override the default value but will be overridden by a
+   *          command-line argument.
    * @param description
    *          LocalizableMessage for the description of this argument.
    * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
    */
-  public FileBasedArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean isMultiValued,
-      LocalizableMessage valuePlaceholder, String defaultValue,
-      String propertyName, LocalizableMessage description)
-      throws ArgumentException
+  public FileBasedArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final boolean isMultiValued, final LocalizableMessage valuePlaceholder,
+      final String defaultValue, final String propertyName,
+      final LocalizableMessage description) throws ArgumentException
   {
-    super(name, shortIdentifier, longIdentifier, isRequired,
-        isMultiValued, true, valuePlaceholder, defaultValue,
-        propertyName, description);
+    super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued,
+        true, valuePlaceholder, defaultValue, propertyName, description);
 
     namesToValues = new LinkedHashMap<String, String>();
   }
@@ -157,11 +115,71 @@
 
 
   /**
-   * Retrieves a map between the filenames specified on the command line
-   * and the first lines read from those files.
+   * Creates a new file-based argument with the provided information.
    *
-   * @return A map between the filenames specified on the command line
-   *         and the first lines read from those files.
+   * @param name
+   *          The generic name that should be used to refer to this argument.
+   * @param shortIdentifier
+   *          The single-character identifier for this argument, or
+   *          <CODE>null</CODE> if there is none.
+   * @param longIdentifier
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
+   * @param isRequired
+   *          Indicates whether this argument must be specified on the command
+   *          line.
+   * @param valuePlaceholder
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
+   * @param description
+   *          LocalizableMessage for the description of this argument.
+   * @throws ArgumentException
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
+   */
+  public FileBasedArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final LocalizableMessage valuePlaceholder,
+      final LocalizableMessage description) throws ArgumentException
+  {
+    super(name, shortIdentifier, longIdentifier, isRequired, false, true,
+        valuePlaceholder, null, null, description);
+
+    namesToValues = new LinkedHashMap<String, String>();
+  }
+
+
+
+  /**
+   * Adds a value to the set of values for this argument. This should only be
+   * called if the value is allowed by the <CODE>valueIsAcceptable</CODE>
+   * method. Note that in this case, correct behavior depends on a previous
+   * successful call to <CODE>valueIsAcceptable</CODE> so that the value read
+   * from the file may be stored in the name-to-value hash and used in place of
+   * the filename here.
+   *
+   * @param valueString
+   *          The string representation of the value to add to this argument.
+   */
+  @Override
+  public void addValue(final String valueString)
+  {
+    final String actualValue = namesToValues.get(valueString);
+    if (actualValue != null)
+    {
+      super.addValue(actualValue);
+    }
+  }
+
+
+
+  /**
+   * Retrieves a map between the filenames specified on the command line and the
+   * first lines read from those files.
+   *
+   * @return A map between the filenames specified on the command line and the
+   *         first lines read from those files.
    */
   public LinkedHashMap<String, String> getNameToValueMap()
   {
@@ -177,13 +195,14 @@
    * @param valueString
    *          The value for which to make the determination.
    * @param invalidReason
-   *          A buffer into which the invalid reason may be written if
-   *          the value is not acceptable.
-   * @return <CODE>true</CODE> if the value is acceptable, or
-   *         <CODE>false</CODE> if it is not.
+   *          A buffer into which the invalid reason may be written if the value
+   *          is not acceptable.
+   * @return <CODE>true</CODE> if the value is acceptable, or <CODE>false</CODE>
+   *         if it is not.
    */
-  public boolean valueIsAcceptable(String valueString,
-      LocalizableMessageBuilder invalidReason)
+  @Override
+  public boolean valueIsAcceptable(final String valueString,
+      final LocalizableMessageBuilder invalidReason)
   {
     // First, make sure that the specified file exists.
     File valueFile;
@@ -197,10 +216,10 @@
         return false;
       }
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
-      invalidReason.append(ERR_FILEARG_CANNOT_VERIFY_FILE_EXISTENCE
-          .get(valueString, getName(), getExceptionMessage(e)));
+      invalidReason.append(ERR_FILEARG_CANNOT_VERIFY_FILE_EXISTENCE.get(
+          valueString, getName(), getExceptionMessage(e)));
       return false;
     }
 
@@ -210,10 +229,10 @@
     {
       reader = new BufferedReader(new FileReader(valueFile));
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
-      invalidReason.append(ERR_FILEARG_CANNOT_OPEN_FILE.get(
-          valueString, getName(), getExceptionMessage(e)));
+      invalidReason.append(ERR_FILEARG_CANNOT_OPEN_FILE.get(valueString,
+          getName(), getExceptionMessage(e)));
       return false;
     }
 
@@ -223,10 +242,10 @@
     {
       line = reader.readLine();
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
-      invalidReason.append(ERR_FILEARG_CANNOT_READ_FILE.get(
-          valueString, getName(), getExceptionMessage(e)));
+      invalidReason.append(ERR_FILEARG_CANNOT_READ_FILE.get(valueString,
+          getName(), getExceptionMessage(e)));
       return false;
     }
     finally
@@ -235,7 +254,7 @@
       {
         reader.close();
       }
-      catch (Exception e)
+      catch (final Exception e)
       {
       }
     }
@@ -244,8 +263,7 @@
     if (line == null)
     {
 
-      invalidReason.append(ERR_FILEARG_EMPTY_FILE.get(valueString,
-          getName()));
+      invalidReason.append(ERR_FILEARG_EMPTY_FILE.get(valueString, getName()));
       return false;
     }
 
@@ -257,28 +275,4 @@
     namesToValues.put(valueString, line);
     return true;
   }
-
-
-
-  /**
-   * Adds a value to the set of values for this argument. This should
-   * only be called if the value is allowed by the
-   * <CODE>valueIsAcceptable</CODE> method. Note that in this case,
-   * correct behavior depends on a previous successful call to
-   * <CODE>valueIsAcceptable</CODE> so that the value read from the file
-   * may be stored in the name-to-value hash and used in place of the
-   * filename here.
-   *
-   * @param valueString
-   *          The string representation of the value to add to this
-   *          argument.
-   */
-  public void addValue(String valueString)
-  {
-    String actualValue = namesToValues.get(valueString);
-    if (actualValue != null)
-    {
-      super.addValue(actualValue);
-    }
-  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/HostnameMismatchCertificateException.java b/sdk/src/com/sun/opends/sdk/tools/HostnameMismatchCertificateException.java
deleted file mode 100644
index 29012df..0000000
--- a/sdk/src/com/sun/opends/sdk/tools/HostnameMismatchCertificateException.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-package com.sun.opends.sdk.tools;
-
-
-
-import java.security.cert.CertificateException;
-
-
-
-/**
- * The certificate's subject DN's value and the host name we tried to
- * connect to do not match.
- */
-@SuppressWarnings("serial")
-final class HostnameMismatchCertificateException extends
-    CertificateException
-{
-  private String expectedHostname;
-
-  private String certificateHostname;
-
-
-
-  HostnameMismatchCertificateException(String expectedHostname,
-      String certificateHostname)
-  {
-    this.expectedHostname = expectedHostname;
-    this.certificateHostname = certificateHostname;
-  }
-
-
-
-  HostnameMismatchCertificateException(String msg,
-      String expectedHostname, String certificateHostname)
-  {
-    super(msg);
-    this.expectedHostname = expectedHostname;
-    this.certificateHostname = certificateHostname;
-  }
-
-
-
-  String getExpectedHostname()
-  {
-    return expectedHostname;
-  }
-
-
-
-  void setExpectedHostname(String expectedHostname)
-  {
-    this.expectedHostname = expectedHostname;
-  }
-
-
-
-  String getCertificateHostname()
-  {
-    return certificateHostname;
-  }
-
-
-
-  void setCertificateHostname(String certificateHostname)
-  {
-    this.certificateHostname = certificateHostname;
-  }
-}
diff --git a/sdk/src/com/sun/opends/sdk/tools/IntegerArgument.java b/sdk/src/com/sun/opends/sdk/tools/IntegerArgument.java
index 57d8a68..9681ddf 100644
--- a/sdk/src/com/sun/opends/sdk/tools/IntegerArgument.java
+++ b/sdk/src/com/sun/opends/sdk/tools/IntegerArgument.java
@@ -28,32 +28,34 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ARG_CANNOT_DECODE_AS_INT;
+import static com.sun.opends.sdk.messages.Messages.ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND;
+import static com.sun.opends.sdk.messages.Messages.ERR_INTARG_VALUE_ABOVE_UPPER_BOUND;
+import static com.sun.opends.sdk.messages.Messages.ERR_INTARG_VALUE_BELOW_LOWER_BOUND;
 
 import org.opends.sdk.LocalizableMessage;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class defines an argument type that will only accept integer
- * values, and potentially only those in a given range.
+ * This class defines an argument type that will only accept integer values, and
+ * potentially only those in a given range.
  */
 final class IntegerArgument extends Argument
 {
   // Indicates whether a lower bound will be enforced for this argument.
-  private boolean hasLowerBound;
+  private final boolean hasLowerBound;
 
   // Indicates whether an upper bound will be enforced for this
   // argument.
-  private boolean hasUpperBound;
+  private final boolean hasUpperBound;
 
   // The lower bound that will be enforced for this argument.
-  private double lowerBound;
+  private final double lowerBound;
 
   // The upper bound that will be enforced for this argument.
-  private double upperBound;
+  private final double upperBound;
 
 
 
@@ -61,36 +63,364 @@
    * Creates a new integer argument with the provided information.
    *
    * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
+   *          The generic name that should be used to refer to this argument.
    * @param shortIdentifier
    *          The single-character identifier for this argument, or
    *          <CODE>null</CODE> if there is none.
    * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
    * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
+   *          Indicates whether this argument must be specified on the command
+   *          line.
+   * @param isMultiValued
+   *          Indicates whether this argument may be specified more than once to
+   *          provide multiple values.
    * @param needsValue
    *          Indicates whether this argument requires a value.
    * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
+   * @param defaultValue
+   *          The default value that should be used for this argument if none is
+   *          provided in a properties file or on the command line. This may be
+   *          <CODE>null</CODE> if there is no generic default.
+   * @param propertyName
+   *          The name of the property in a property file that may be used to
+   *          override the default value but will be overridden by a
+   *          command-line argument.
+   * @param hasLowerBound
+   *          Indicates whether a lower bound should be enforced for values of
+   *          this argument.
+   * @param lowerBound
+   *          The lower bound that should be enforced for values of this
+   *          argument.
+   * @param hasUpperBound
+   *          Indicates whether an upperbound should be enforced for values of
+   *          this argument.
+   * @param upperBound
+   *          The upper bound that should be enforced for values of this
+   *          argument.
    * @param description
    *          LocalizableMessage for the description of this argument.
    * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
    */
-  public IntegerArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean needsValue,
-      LocalizableMessage valuePlaceholder, LocalizableMessage description)
+  public IntegerArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final boolean isMultiValued, final boolean needsValue,
+      final LocalizableMessage valuePlaceholder, final double defaultValue,
+      final String propertyName, final boolean hasLowerBound,
+      final double lowerBound, final boolean hasUpperBound,
+      final double upperBound, final LocalizableMessage description)
       throws ArgumentException
   {
-    super(name, shortIdentifier, longIdentifier, isRequired, false,
-        needsValue, valuePlaceholder, null, null, description);
+    super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued,
+        needsValue, valuePlaceholder, String.valueOf(defaultValue),
+        propertyName, description);
+
+    this.hasLowerBound = hasLowerBound;
+    this.hasUpperBound = hasUpperBound;
+    this.lowerBound = lowerBound;
+    this.upperBound = upperBound;
+
+    if (hasLowerBound && hasUpperBound && (lowerBound > upperBound))
+    {
+      final LocalizableMessage message = ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND
+          .get(name, lowerBound, upperBound);
+      throw new ArgumentException(message);
+    }
+  }
+
+
+
+  /**
+   * Creates a new integer argument with the provided information.
+   *
+   * @param name
+   *          The generic name that should be used to refer to this argument.
+   * @param shortIdentifier
+   *          The single-character identifier for this argument, or
+   *          <CODE>null</CODE> if there is none.
+   * @param longIdentifier
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
+   * @param isRequired
+   *          Indicates whether this argument must be specified on the command
+   *          line.
+   * @param isMultiValued
+   *          Indicates whether this argument may be specified more than once to
+   *          provide multiple values.
+   * @param needsValue
+   *          Indicates whether this argument requires a value.
+   * @param valuePlaceholder
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
+   * @param defaultValue
+   *          The default value that should be used for this argument if none is
+   *          provided in a properties file or on the command line. This may be
+   *          <CODE>null</CODE> if there is no generic default.
+   * @param propertyName
+   *          The name of the property in a property file that may be used to
+   *          override the default value but will be overridden by a
+   *          command-line argument.
+   * @param description
+   *          LocalizableMessage for the description of this argument.
+   * @throws ArgumentException
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
+   */
+  public IntegerArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final boolean isMultiValued, final boolean needsValue,
+      final LocalizableMessage valuePlaceholder, final double defaultValue,
+      final String propertyName, final LocalizableMessage description)
+      throws ArgumentException
+  {
+    super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued,
+        needsValue, valuePlaceholder, String.format("%f", defaultValue),
+        propertyName, description);
+
+    hasLowerBound = false;
+    hasUpperBound = false;
+    lowerBound = Integer.MIN_VALUE;
+    upperBound = Integer.MAX_VALUE;
+  }
+
+
+
+  /**
+   * Creates a new integer argument with the provided information.
+   *
+   * @param name
+   *          The generic name that should be used to refer to this argument.
+   * @param shortIdentifier
+   *          The single-character identifier for this argument, or
+   *          <CODE>null</CODE> if there is none.
+   * @param longIdentifier
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
+   * @param isRequired
+   *          Indicates whether this argument must be specified on the command
+   *          line.
+   * @param isMultiValued
+   *          Indicates whether this argument may be specified more than once to
+   *          provide multiple values.
+   * @param needsValue
+   *          Indicates whether this argument requires a value.
+   * @param valuePlaceholder
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
+   * @param defaultValue
+   *          The default value that should be used for this argument if none is
+   *          provided in a properties file or on the command line. This may be
+   *          <CODE>null</CODE> if there is no generic default.
+   * @param propertyName
+   *          The name of the property in a property file that may be used to
+   *          override the default value but will be overridden by a
+   *          command-line argument.
+   * @param hasLowerBound
+   *          Indicates whether a lower bound should be enforced for values of
+   *          this argument.
+   * @param lowerBound
+   *          The lower bound that should be enforced for values of this
+   *          argument.
+   * @param hasUpperBound
+   *          Indicates whether an upperbound should be enforced for values of
+   *          this argument.
+   * @param upperBound
+   *          The upper bound that should be enforced for values of this
+   *          argument.
+   * @param description
+   *          LocalizableMessage for the description of this argument.
+   * @throws ArgumentException
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
+   */
+  public IntegerArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final boolean isMultiValued, final boolean needsValue,
+      final LocalizableMessage valuePlaceholder, final int defaultValue,
+      final String propertyName, final boolean hasLowerBound,
+      final double lowerBound, final boolean hasUpperBound,
+      final double upperBound, final LocalizableMessage description)
+      throws ArgumentException
+  {
+    super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued,
+        needsValue, valuePlaceholder, String.valueOf(defaultValue),
+        propertyName, description);
+
+    this.hasLowerBound = hasLowerBound;
+    this.hasUpperBound = hasUpperBound;
+    this.lowerBound = lowerBound;
+    this.upperBound = upperBound;
+
+    if (hasLowerBound && hasUpperBound && (lowerBound > upperBound))
+    {
+      final LocalizableMessage message = ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND
+          .get(name, lowerBound, upperBound);
+      throw new ArgumentException(message);
+    }
+  }
+
+
+
+  /**
+   * Creates a new integer argument with the provided information.
+   *
+   * @param name
+   *          The generic name that should be used to refer to this argument.
+   * @param shortIdentifier
+   *          The single-character identifier for this argument, or
+   *          <CODE>null</CODE> if there is none.
+   * @param longIdentifier
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
+   * @param isRequired
+   *          Indicates whether this argument must be specified on the command
+   *          line.
+   * @param isMultiValued
+   *          Indicates whether this argument may be specified more than once to
+   *          provide multiple values.
+   * @param needsValue
+   *          Indicates whether this argument requires a value.
+   * @param valuePlaceholder
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
+   * @param defaultValue
+   *          The default value that should be used for this argument if none is
+   *          provided in a properties file or on the command line. This may be
+   *          <CODE>null</CODE> if there is no generic default.
+   * @param propertyName
+   *          The name of the property in a property file that may be used to
+   *          override the default value but will be overridden by a
+   *          command-line argument.
+   * @param description
+   *          LocalizableMessage for the description of this argument.
+   * @throws ArgumentException
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
+   */
+  public IntegerArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final boolean isMultiValued, final boolean needsValue,
+      final LocalizableMessage valuePlaceholder, final int defaultValue,
+      final String propertyName, final LocalizableMessage description)
+      throws ArgumentException
+  {
+    super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued,
+        needsValue, valuePlaceholder, String.valueOf(defaultValue),
+        propertyName, description);
+
+    hasLowerBound = false;
+    hasUpperBound = false;
+    lowerBound = Integer.MIN_VALUE;
+    upperBound = Integer.MAX_VALUE;
+  }
+
+
+
+  /**
+   * Creates a new integer argument with the provided information.
+   *
+   * @param name
+   *          The generic name that should be used to refer to this argument.
+   * @param shortIdentifier
+   *          The single-character identifier for this argument, or
+   *          <CODE>null</CODE> if there is none.
+   * @param longIdentifier
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
+   * @param isRequired
+   *          Indicates whether this argument must be specified on the command
+   *          line.
+   * @param needsValue
+   *          Indicates whether this argument requires a value.
+   * @param valuePlaceholder
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
+   * @param hasLowerBound
+   *          Indicates whether a lower bound should be enforced for values of
+   *          this argument.
+   * @param lowerBound
+   *          The lower bound that should be enforced for values of this
+   *          argument.
+   * @param hasUpperBound
+   *          Indicates whether an upperbound should be enforced for values of
+   *          this argument.
+   * @param upperBound
+   *          The upper bound that should be enforced for values of this
+   *          argument.
+   * @param description
+   *          LocalizableMessage for the description of this argument.
+   * @throws ArgumentException
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
+   */
+  public IntegerArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final boolean needsValue, final LocalizableMessage valuePlaceholder,
+      final boolean hasLowerBound, final double lowerBound,
+      final boolean hasUpperBound, final double upperBound,
+      final LocalizableMessage description) throws ArgumentException
+  {
+    super(name, shortIdentifier, longIdentifier, isRequired, false, needsValue,
+        valuePlaceholder, null, null, description);
+
+    this.hasLowerBound = hasLowerBound;
+    this.hasUpperBound = hasUpperBound;
+    this.lowerBound = lowerBound;
+    this.upperBound = upperBound;
+
+    if (hasLowerBound && hasUpperBound && (lowerBound > upperBound))
+    {
+      final LocalizableMessage message = ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND
+          .get(name, lowerBound, upperBound);
+      throw new ArgumentException(message);
+    }
+  }
+
+
+
+  /**
+   * Creates a new integer argument with the provided information.
+   *
+   * @param name
+   *          The generic name that should be used to refer to this argument.
+   * @param shortIdentifier
+   *          The single-character identifier for this argument, or
+   *          <CODE>null</CODE> if there is none.
+   * @param longIdentifier
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
+   * @param isRequired
+   *          Indicates whether this argument must be specified on the command
+   *          line.
+   * @param needsValue
+   *          Indicates whether this argument requires a value.
+   * @param valuePlaceholder
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
+   * @param description
+   *          LocalizableMessage for the description of this argument.
+   * @throws ArgumentException
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
+   */
+  public IntegerArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final boolean needsValue, final LocalizableMessage valuePlaceholder,
+      final LocalizableMessage description) throws ArgumentException
+  {
+    super(name, shortIdentifier, longIdentifier, isRequired, false, needsValue,
+        valuePlaceholder, null, null, description);
 
     hasLowerBound = false;
     hasUpperBound = false;
@@ -101,359 +431,9 @@
 
 
   /**
-   * Creates a new integer argument with the provided information.
+   * Retrieves the lower bound that may be enforced for values of this argument.
    *
-   * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
-   * @param shortIdentifier
-   *          The single-character identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
-   * @param needsValue
-   *          Indicates whether this argument requires a value.
-   * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
-   * @param hasLowerBound
-   *          Indicates whether a lower bound should be enforced for
-   *          values of this argument.
-   * @param lowerBound
-   *          The lower bound that should be enforced for values of this
-   *          argument.
-   * @param hasUpperBound
-   *          Indicates whether an upperbound should be enforced for
-   *          values of this argument.
-   * @param upperBound
-   *          The upper bound that should be enforced for values of this
-   *          argument.
-   * @param description
-   *          LocalizableMessage for the description of this argument.
-   * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
-   */
-  public IntegerArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean needsValue,
-      LocalizableMessage valuePlaceholder, boolean hasLowerBound,
-      double lowerBound, boolean hasUpperBound, double upperBound,
-      LocalizableMessage description) throws ArgumentException
-  {
-    super(name, shortIdentifier, longIdentifier, isRequired, false,
-        needsValue, valuePlaceholder, null, null, description);
-
-    this.hasLowerBound = hasLowerBound;
-    this.hasUpperBound = hasUpperBound;
-    this.lowerBound = lowerBound;
-    this.upperBound = upperBound;
-
-    if (hasLowerBound && hasUpperBound && (lowerBound > upperBound))
-    {
-      LocalizableMessage message =
-          ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND.get(name,
-              lowerBound, upperBound);
-      throw new ArgumentException(message);
-    }
-  }
-
-
-
-  /**
-   * Creates a new integer argument with the provided information.
-   *
-   * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
-   * @param shortIdentifier
-   *          The single-character identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
-   * @param isMultiValued
-   *          Indicates whether this argument may be specified more than
-   *          once to provide multiple values.
-   * @param needsValue
-   *          Indicates whether this argument requires a value.
-   * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
-   * @param defaultValue
-   *          The default value that should be used for this argument if
-   *          none is provided in a properties file or on the command
-   *          line. This may be <CODE>null</CODE> if there is no generic
-   *          default.
-   * @param propertyName
-   *          The name of the property in a property file that may be
-   *          used to override the default value but will be overridden
-   *          by a command-line argument.
-   * @param description
-   *          LocalizableMessage for the description of this argument.
-   * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
-   */
-  public IntegerArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean isMultiValued,
-      boolean needsValue, LocalizableMessage valuePlaceholder, int defaultValue,
-      String propertyName, LocalizableMessage description)
-      throws ArgumentException
-  {
-    super(name, shortIdentifier, longIdentifier, isRequired,
-        isMultiValued, needsValue, valuePlaceholder, String
-            .valueOf(defaultValue), propertyName, description);
-
-    hasLowerBound = false;
-    hasUpperBound = false;
-    lowerBound = Integer.MIN_VALUE;
-    upperBound = Integer.MAX_VALUE;
-  }
-
-
-
-  /**
-   * Creates a new integer argument with the provided information.
-   *
-   * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
-   * @param shortIdentifier
-   *          The single-character identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
-   * @param isMultiValued
-   *          Indicates whether this argument may be specified more than
-   *          once to provide multiple values.
-   * @param needsValue
-   *          Indicates whether this argument requires a value.
-   * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
-   * @param defaultValue
-   *          The default value that should be used for this argument if
-   *          none is provided in a properties file or on the command
-   *          line. This may be <CODE>null</CODE> if there is no generic
-   *          default.
-   * @param propertyName
-   *          The name of the property in a property file that may be
-   *          used to override the default value but will be overridden
-   *          by a command-line argument.
-   * @param description
-   *          LocalizableMessage for the description of this argument.
-   * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
-   */
-  public IntegerArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean isMultiValued,
-      boolean needsValue, LocalizableMessage valuePlaceholder,
-      double defaultValue, String propertyName, LocalizableMessage description)
-      throws ArgumentException
-  {
-    super(name, shortIdentifier, longIdentifier, isRequired,
-        isMultiValued, needsValue, valuePlaceholder, String.format(
-            "%f", defaultValue), propertyName, description);
-
-    hasLowerBound = false;
-    hasUpperBound = false;
-    lowerBound = Integer.MIN_VALUE;
-    upperBound = Integer.MAX_VALUE;
-  }
-
-
-
-  /**
-   * Creates a new integer argument with the provided information.
-   *
-   * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
-   * @param shortIdentifier
-   *          The single-character identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
-   * @param isMultiValued
-   *          Indicates whether this argument may be specified more than
-   *          once to provide multiple values.
-   * @param needsValue
-   *          Indicates whether this argument requires a value.
-   * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
-   * @param defaultValue
-   *          The default value that should be used for this argument if
-   *          none is provided in a properties file or on the command
-   *          line. This may be <CODE>null</CODE> if there is no generic
-   *          default.
-   * @param propertyName
-   *          The name of the property in a property file that may be
-   *          used to override the default value but will be overridden
-   *          by a command-line argument.
-   * @param hasLowerBound
-   *          Indicates whether a lower bound should be enforced for
-   *          values of this argument.
-   * @param lowerBound
-   *          The lower bound that should be enforced for values of this
-   *          argument.
-   * @param hasUpperBound
-   *          Indicates whether an upperbound should be enforced for
-   *          values of this argument.
-   * @param upperBound
-   *          The upper bound that should be enforced for values of this
-   *          argument.
-   * @param description
-   *          LocalizableMessage for the description of this argument.
-   * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
-   */
-  public IntegerArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean isMultiValued,
-      boolean needsValue, LocalizableMessage valuePlaceholder, int defaultValue,
-      String propertyName, boolean hasLowerBound, double lowerBound,
-      boolean hasUpperBound, double upperBound, LocalizableMessage description)
-      throws ArgumentException
-  {
-    super(name, shortIdentifier, longIdentifier, isRequired,
-        isMultiValued, needsValue, valuePlaceholder, String
-            .valueOf(defaultValue), propertyName, description);
-
-    this.hasLowerBound = hasLowerBound;
-    this.hasUpperBound = hasUpperBound;
-    this.lowerBound = lowerBound;
-    this.upperBound = upperBound;
-
-    if (hasLowerBound && hasUpperBound && (lowerBound > upperBound))
-    {
-      LocalizableMessage message =
-          ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND.get(name,
-              lowerBound, upperBound);
-      throw new ArgumentException(message);
-    }
-  }
-
-
-
-  /**
-   * Creates a new integer argument with the provided information.
-   *
-   * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
-   * @param shortIdentifier
-   *          The single-character identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
-   * @param isMultiValued
-   *          Indicates whether this argument may be specified more than
-   *          once to provide multiple values.
-   * @param needsValue
-   *          Indicates whether this argument requires a value.
-   * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
-   * @param defaultValue
-   *          The default value that should be used for this argument if
-   *          none is provided in a properties file or on the command
-   *          line. This may be <CODE>null</CODE> if there is no generic
-   *          default.
-   * @param propertyName
-   *          The name of the property in a property file that may be
-   *          used to override the default value but will be overridden
-   *          by a command-line argument.
-   * @param hasLowerBound
-   *          Indicates whether a lower bound should be enforced for
-   *          values of this argument.
-   * @param lowerBound
-   *          The lower bound that should be enforced for values of this
-   *          argument.
-   * @param hasUpperBound
-   *          Indicates whether an upperbound should be enforced for
-   *          values of this argument.
-   * @param upperBound
-   *          The upper bound that should be enforced for values of this
-   *          argument.
-   * @param description
-   *          LocalizableMessage for the description of this argument.
-   * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
-   */
-  public IntegerArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean isMultiValued,
-      boolean needsValue, LocalizableMessage valuePlaceholder,
-      double defaultValue, String propertyName, boolean hasLowerBound,
-      double lowerBound, boolean hasUpperBound, double upperBound,
-      LocalizableMessage description) throws ArgumentException
-  {
-    super(name, shortIdentifier, longIdentifier, isRequired,
-        isMultiValued, needsValue, valuePlaceholder, String
-            .valueOf(defaultValue), propertyName, description);
-
-    this.hasLowerBound = hasLowerBound;
-    this.hasUpperBound = hasUpperBound;
-    this.lowerBound = lowerBound;
-    this.upperBound = upperBound;
-
-    if (hasLowerBound && hasUpperBound && (lowerBound > upperBound))
-    {
-      LocalizableMessage message =
-          ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND.get(name,
-              lowerBound, upperBound);
-      throw new ArgumentException(message);
-    }
-  }
-
-
-
-  /**
-   * Indicates whether a lower bound should be enforced for values of
-   * this argument.
-   *
-   * @return <CODE>true</CODE> if a lower bound should be enforced for
-   *         values of this argument, or <CODE>false</CODE> if not.
-   */
-  public boolean hasLowerBound()
-  {
-    return hasLowerBound;
-  }
-
-
-
-  /**
-   * Retrieves the lower bound that may be enforced for values of this
-   * argument.
-   *
-   * @return The lower bound that may be enforced for values of this
-   *         argument.
+   * @return The lower bound that may be enforced for values of this argument.
    */
   public double getLowerBound()
   {
@@ -463,29 +443,41 @@
 
 
   /**
-   * Indicates whether a upper bound should be enforced for values of
-   * this argument.
+   * Retrieves the upper bound that may be enforced for values of this argument.
    *
-   * @return <CODE>true</CODE> if a upper bound should be enforced for
-   *         values of this argument, or <CODE>false</CODE> if not.
+   * @return The upper bound that may be enforced for values of this argument.
    */
-  public boolean hasUpperBound()
+  public double getUpperBound()
   {
-    return hasUpperBound;
+    return upperBound;
   }
 
 
 
   /**
-   * Retrieves the upper bound that may be enforced for values of this
+   * Indicates whether a lower bound should be enforced for values of this
    * argument.
    *
-   * @return The upper bound that may be enforced for values of this
-   *         argument.
+   * @return <CODE>true</CODE> if a lower bound should be enforced for values of
+   *         this argument, or <CODE>false</CODE> if not.
    */
-  public double getUpperBound()
+  public boolean hasLowerBound()
   {
-    return upperBound;
+    return hasLowerBound;
+  }
+
+
+
+  /**
+   * Indicates whether a upper bound should be enforced for values of this
+   * argument.
+   *
+   * @return <CODE>true</CODE> if a upper bound should be enforced for values of
+   *         this argument, or <CODE>false</CODE> if not.
+   */
+  public boolean hasUpperBound()
+  {
+    return hasUpperBound;
   }
 
 
@@ -497,13 +489,14 @@
    * @param valueString
    *          The value for which to make the determination.
    * @param invalidReason
-   *          A buffer into which the invalid reason may be written if
-   *          the value is not acceptable.
-   * @return <CODE>true</CODE> if the value is acceptable, or
-   *         <CODE>false</CODE> if it is not.
+   *          A buffer into which the invalid reason may be written if the value
+   *          is not acceptable.
+   * @return <CODE>true</CODE> if the value is acceptable, or <CODE>false</CODE>
+   *         if it is not.
    */
-  public boolean valueIsAcceptable(String valueString,
-      LocalizableMessageBuilder invalidReason)
+  @Override
+  public boolean valueIsAcceptable(final String valueString,
+      final LocalizableMessageBuilder invalidReason)
   {
     // First, the value must be decodable as an integer.
     double intValue;
@@ -511,10 +504,10 @@
     {
       intValue = Double.parseDouble(valueString);
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
-      invalidReason.append(ERR_ARG_CANNOT_DECODE_AS_INT.get(
-          valueString, getName()));
+      invalidReason.append(ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString,
+          getName()));
       return false;
     }
 
@@ -523,8 +516,8 @@
     // to it.
     if (hasLowerBound && (intValue < lowerBound))
     {
-      invalidReason.append(ERR_INTARG_VALUE_BELOW_LOWER_BOUND.get(
-          getName(), intValue, lowerBound));
+      invalidReason.append(ERR_INTARG_VALUE_BELOW_LOWER_BOUND.get(getName(),
+          intValue, lowerBound));
       return false;
     }
 
@@ -534,8 +527,8 @@
     if (hasUpperBound && (intValue > upperBound))
     {
 
-      invalidReason.append(ERR_INTARG_VALUE_ABOVE_UPPER_BOUND.get(
-          getName(), intValue, upperBound));
+      invalidReason.append(ERR_INTARG_VALUE_ABOVE_UPPER_BOUND.get(getName(),
+          intValue, upperBound));
       return false;
     }
 
diff --git a/sdk/src/com/sun/opends/sdk/tools/LDAPCompare.java b/sdk/src/com/sun/opends/sdk/tools/LDAPCompare.java
index 6b13a6c..380462e 100644
--- a/sdk/src/com/sun/opends/sdk/tools/LDAPCompare.java
+++ b/sdk/src/com/sun/opends/sdk/tools/LDAPCompare.java
@@ -31,15 +31,15 @@
 
 import static com.sun.opends.sdk.messages.Messages.*;
 import static com.sun.opends.sdk.tools.ToolConstants.*;
-import static com.sun.opends.sdk.tools.Utils.*;
+import static com.sun.opends.sdk.tools.Utils.filterExitCode;
 
 import java.io.*;
 import java.util.ArrayList;
 
 import org.opends.sdk.*;
-import org.opends.sdk.controls.AssertionControl;
+import org.opends.sdk.controls.AssertionRequestControl;
 import org.opends.sdk.controls.Control;
-import org.opends.sdk.controls.ProxiedAuthV2Control;
+import org.opends.sdk.controls.ProxiedAuthV2RequestControl;
 import org.opends.sdk.requests.CompareRequest;
 import org.opends.sdk.requests.Requests;
 import org.opends.sdk.responses.Responses;
@@ -50,15 +50,10 @@
 
 
 /**
- * A tool that can be used to issue Compare requests to the Directory
- * Server.
+ * A tool that can be used to issue Compare requests to the Directory Server.
  */
 public final class LDAPCompare extends ConsoleApplication
 {
-  private BooleanArgument verbose;
-
-
-
   /**
    * The main method for LDAPModify tool.
    *
@@ -66,24 +61,24 @@
    *          The command-line arguments provided to this program.
    */
 
-  public static void main(String[] args)
+  public static void main(final String[] args)
   {
-    int retCode = mainCompare(args, System.in, System.out, System.err);
+    final int retCode = mainCompare(args, System.in, System.out, System.err);
     System.exit(filterExitCode(retCode));
   }
 
 
 
   /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the LDAPModify tool.
+   * Parses the provided command-line arguments and uses that information to run
+   * the LDAPModify tool.
    *
    * @param args
    *          The command-line arguments provided to this program.
    * @return The error code.
    */
 
-  static int mainCompare(String[] args)
+  static int mainCompare(final String[] args)
   {
     return mainCompare(args, System.in, System.out, System.err);
   }
@@ -91,33 +86,37 @@
 
 
   /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the LDAPModify tool.
+   * Parses the provided command-line arguments and uses that information to run
+   * the LDAPModify tool.
    *
    * @param args
-   *          The command-line arguments provided to this program.
-   *          specified, the number of matching entries should be
-   *          returned or not.
+   *          The command-line arguments provided to this program. specified,
+   *          the number of matching entries should be returned or not.
    * @param inStream
-   *          The input stream to use for standard input, or
-   *          <CODE>null</CODE> if standard input is not needed.
+   *          The input stream to use for standard input, or <CODE>null</CODE>
+   *          if standard input is not needed.
    * @param outStream
-   *          The output stream to use for standard output, or
-   *          <CODE>null</CODE> if standard output is not needed.
+   *          The output stream to use for standard output, or <CODE>null</CODE>
+   *          if standard output is not needed.
    * @param errStream
-   *          The output stream to use for standard error, or
-   *          <CODE>null</CODE> if standard error is not needed.
+   *          The output stream to use for standard error, or <CODE>null</CODE>
+   *          if standard error is not needed.
    * @return The error code.
    */
-  static int mainCompare(String[] args, InputStream inStream,
-      OutputStream outStream, OutputStream errStream)
+  static int mainCompare(final String[] args, final InputStream inStream,
+      final OutputStream outStream, final OutputStream errStream)
   {
     return new LDAPCompare(inStream, outStream, errStream).run(args);
   }
 
 
 
-  private LDAPCompare(InputStream in, OutputStream out, OutputStream err)
+  private BooleanArgument verbose;
+
+
+
+  private LDAPCompare(final InputStream in, final OutputStream out,
+      final OutputStream err)
   {
     super(in, out, err);
 
@@ -125,15 +124,159 @@
 
 
 
-  private int run(String[] args)
+  /**
+   * Indicates whether or not the user has requested advanced mode.
+   *
+   * @return Returns <code>true</code> if the user has requested advanced mode.
+   */
+  @Override
+  public boolean isAdvancedMode()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested interactive behavior.
+   *
+   * @return Returns <code>true</code> if the user has requested interactive
+   *         behavior.
+   */
+  @Override
+  public boolean isInteractive()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not this console application is running in its
+   * menu-driven mode. This can be used to dictate whether output should go to
+   * the error stream or not. In addition, it may also dictate whether or not
+   * sub-menus should display a cancel option as well as a quit option.
+   *
+   * @return Returns <code>true</code> if this console application is running in
+   *         its menu-driven mode.
+   */
+  @Override
+  public boolean isMenuDrivenMode()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested quiet output.
+   *
+   * @return Returns <code>true</code> if the user has requested quiet output.
+   */
+  @Override
+  public boolean isQuiet()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested script-friendly output.
+   *
+   * @return Returns <code>true</code> if the user has requested script-friendly
+   *         output.
+   */
+  @Override
+  public boolean isScriptFriendly()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested verbose output.
+   *
+   * @return Returns <code>true</code> if the user has requested verbose output.
+   */
+  @Override
+  public boolean isVerbose()
+  {
+    return verbose.isPresent();
+  }
+
+
+
+  private int executeCompare(final CompareRequest request,
+      final Connection connection)
+  {
+    println(INFO_PROCESSING_COMPARE_OPERATION.get(request
+        .getAttributeDescription().toString(), request
+        .getAssertionValueAsString(), request.getName().toString()));
+    if (connection != null)
+    {
+      try
+      {
+        Result result;
+        try
+        {
+          result = connection.compare(request);
+        }
+        catch (final InterruptedException e)
+        {
+          // This shouldn't happen because there are no other threads to
+          // interrupt this one.
+          result = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
+              .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
+          throw ErrorResultException.wrap(result);
+        }
+
+        if (result.getResultCode() == ResultCode.COMPARE_FALSE)
+        {
+          println(INFO_COMPARE_OPERATION_RESULT_FALSE.get(request.getName()
+              .toString()));
+        }
+        else
+        {
+
+          println(INFO_COMPARE_OPERATION_RESULT_TRUE.get(request.getName()
+              .toString()));
+        }
+      }
+      catch (final ErrorResultException ere)
+      {
+        final LocalizableMessage msg = INFO_OPERATION_FAILED.get("COMPARE");
+        println(msg);
+        final Result r = ere.getResult();
+        println(ERR_TOOL_RESULT_CODE.get(r.getResultCode().intValue(), r
+            .getResultCode().toString()));
+        if ((r.getDiagnosticMessage() != null)
+            && (r.getDiagnosticMessage().length() > 0))
+        {
+          println(LocalizableMessage.raw(r.getDiagnosticMessage()));
+        }
+        if (r.getMatchedDN() != null && r.getMatchedDN().length() > 0)
+        {
+          println(ERR_TOOL_MATCHED_DN.get(r.getMatchedDN()));
+        }
+        return r.getResultCode().intValue();
+      }
+    }
+    return ResultCode.SUCCESS.intValue();
+  }
+
+
+
+  private int run(final String[] args)
   {
     // Create the command-line argument parser for use with this
     // program.
-    LocalizableMessage toolDescription = INFO_LDAPCOMPARE_TOOL_DESCRIPTION.get();
-    ArgumentParser argParser =
-        new ArgumentParser(LDAPCompare.class.getName(),
-            toolDescription, false, true, 1, 0,
-            "attribute:value [DN ...]");
+    final LocalizableMessage toolDescription = INFO_LDAPCOMPARE_TOOL_DESCRIPTION
+        .get();
+    final ArgumentParser argParser = new ArgumentParser(LDAPCompare.class
+        .getName(), toolDescription, false, true, 1, 0,
+        "attribute:value [DN ...]");
     ArgumentParserConnectionFactory connectionFactory;
 
     BooleanArgument continueOnError;
@@ -150,97 +293,84 @@
 
     try
     {
-      connectionFactory =
-          new ArgumentParserConnectionFactory(argParser, this);
-      propertiesFileArgument =
-          new StringArgument("propertiesFilePath", null,
-              OPTION_LONG_PROP_FILE_PATH, false, false, true,
-              INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null,
-              INFO_DESCRIPTION_PROP_FILE_PATH.get());
+      connectionFactory = new ArgumentParserConnectionFactory(argParser, this);
+      propertiesFileArgument = new StringArgument("propertiesFilePath", null,
+          OPTION_LONG_PROP_FILE_PATH, false, false, true,
+          INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_PROP_FILE_PATH.get());
       argParser.addArgument(propertiesFileArgument);
       argParser.setFilePropertiesArgument(propertiesFileArgument);
 
-      noPropertiesFileArgument =
-          new BooleanArgument("noPropertiesFileArgument", null,
-              OPTION_LONG_NO_PROP_FILE, INFO_DESCRIPTION_NO_PROP_FILE
-                  .get());
+      noPropertiesFileArgument = new BooleanArgument(
+          "noPropertiesFileArgument", null, OPTION_LONG_NO_PROP_FILE,
+          INFO_DESCRIPTION_NO_PROP_FILE.get());
       argParser.addArgument(noPropertiesFileArgument);
       argParser.setNoPropertiesFileArgument(noPropertiesFileArgument);
 
-      filename =
-          new StringArgument("filename", OPTION_SHORT_FILENAME,
-              OPTION_LONG_FILENAME, false, false, true,
-              INFO_FILE_PLACEHOLDER.get(), null, null,
-              INFO_LDAPMODIFY_DESCRIPTION_FILENAME.get());
+      filename = new StringArgument("filename", OPTION_SHORT_FILENAME,
+          OPTION_LONG_FILENAME, false, false, true,
+          INFO_FILE_PLACEHOLDER.get(), null, null,
+          INFO_LDAPMODIFY_DESCRIPTION_FILENAME.get());
       filename.setPropertyName(OPTION_LONG_FILENAME);
       argParser.addArgument(filename);
 
-      proxyAuthzID =
-          new StringArgument("proxy_authzid", OPTION_SHORT_PROXYAUTHID,
-              OPTION_LONG_PROXYAUTHID, false, false, true,
-              INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
-              INFO_DESCRIPTION_PROXY_AUTHZID.get());
+      proxyAuthzID = new StringArgument("proxy_authzid",
+          OPTION_SHORT_PROXYAUTHID, OPTION_LONG_PROXYAUTHID, false, false,
+          true, INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_PROXY_AUTHZID.get());
       proxyAuthzID.setPropertyName(OPTION_LONG_PROXYAUTHID);
       argParser.addArgument(proxyAuthzID);
 
-      assertionFilter =
-          new StringArgument("assertionfilter", null,
-              OPTION_LONG_ASSERTION_FILE, false, false, true,
-              INFO_ASSERTION_FILTER_PLACEHOLDER.get(), null, null,
-              INFO_DESCRIPTION_ASSERTION_FILTER.get());
+      assertionFilter = new StringArgument("assertionfilter", null,
+          OPTION_LONG_ASSERTION_FILE, false, false, true,
+          INFO_ASSERTION_FILTER_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_ASSERTION_FILTER.get());
       assertionFilter.setPropertyName(OPTION_LONG_ASSERTION_FILE);
       argParser.addArgument(assertionFilter);
 
-      controlStr =
-          new StringArgument("control", 'J', "control", false, true,
-              true, INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
-              INFO_DESCRIPTION_CONTROLS.get());
+      controlStr = new StringArgument("control", 'J', "control", false, true,
+          true, INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_CONTROLS.get());
       controlStr.setPropertyName("control");
       argParser.addArgument(controlStr);
 
-      version =
-          new IntegerArgument("version", OPTION_SHORT_PROTOCOL_VERSION,
-              OPTION_LONG_PROTOCOL_VERSION, false, false, true,
-              INFO_PROTOCOL_VERSION_PLACEHOLDER.get(), 3, null,
-              INFO_DESCRIPTION_VERSION.get());
+      version = new IntegerArgument("version", OPTION_SHORT_PROTOCOL_VERSION,
+          OPTION_LONG_PROTOCOL_VERSION, false, false, true,
+          INFO_PROTOCOL_VERSION_PLACEHOLDER.get(), 3, null,
+          INFO_DESCRIPTION_VERSION.get());
       version.setPropertyName(OPTION_LONG_PROTOCOL_VERSION);
       argParser.addArgument(version);
 
-      encodingStr =
-          new StringArgument("encoding", 'i', "encoding", false, false,
-              true, INFO_ENCODING_PLACEHOLDER.get(), null, null,
-              INFO_DESCRIPTION_ENCODING.get());
+      encodingStr = new StringArgument("encoding", 'i', "encoding", false,
+          false, true, INFO_ENCODING_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_ENCODING.get());
       encodingStr.setPropertyName("encoding");
       argParser.addArgument(encodingStr);
 
-      continueOnError =
-          new BooleanArgument("continueOnError", 'c',
-              "continueOnError", INFO_DESCRIPTION_CONTINUE_ON_ERROR
-                  .get());
+      continueOnError = new BooleanArgument("continueOnError", 'c',
+          "continueOnError", INFO_DESCRIPTION_CONTINUE_ON_ERROR.get());
       continueOnError.setPropertyName("continueOnError");
       argParser.addArgument(continueOnError);
 
-      noop =
-          new BooleanArgument("no-op", OPTION_SHORT_DRYRUN,
-              OPTION_LONG_DRYRUN, INFO_DESCRIPTION_NOOP.get());
+      noop = new BooleanArgument("no-op", OPTION_SHORT_DRYRUN,
+          OPTION_LONG_DRYRUN, INFO_DESCRIPTION_NOOP.get());
       noop.setPropertyName(OPTION_LONG_DRYRUN);
       argParser.addArgument(noop);
 
-      verbose =
-          new BooleanArgument("verbose", 'v', "verbose",
-              INFO_DESCRIPTION_VERBOSE.get());
+      verbose = new BooleanArgument("verbose", 'v', "verbose",
+          INFO_DESCRIPTION_VERBOSE.get());
       verbose.setPropertyName("verbose");
       argParser.addArgument(verbose);
 
-      showUsage =
-          new BooleanArgument("showUsage", OPTION_SHORT_HELP,
-              OPTION_LONG_HELP, INFO_DESCRIPTION_SHOWUSAGE.get());
+      showUsage = new BooleanArgument("showUsage", OPTION_SHORT_HELP,
+          OPTION_LONG_HELP, INFO_DESCRIPTION_SHOWUSAGE.get());
       argParser.addArgument(showUsage);
       argParser.setUsageArgument(showUsage, getOutputStream());
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
+      final LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae
+          .getMessage());
       println(message);
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
@@ -251,9 +381,10 @@
       argParser.parseArguments(args);
       connectionFactory.validate();
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
+      final LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae
+          .getMessage());
       println(message);
       println(argParser.getUsageMessage());
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -268,7 +399,7 @@
 
     try
     {
-      int versionNumber = version.getIntValue();
+      final int versionNumber = version.getIntValue();
       if (versionNumber != 2 && versionNumber != 3)
       {
         println(ERR_DESCRIPTION_INVALID_VERSION.get(String
@@ -276,29 +407,28 @@
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      println(ERR_DESCRIPTION_INVALID_VERSION.get(String
-          .valueOf(version.getValue())));
+      println(ERR_DESCRIPTION_INVALID_VERSION.get(String.valueOf(version
+          .getValue())));
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
 
-    ArrayList<String> dnStrings = new ArrayList<String>();
-    ArrayList<String> attrAndDNStrings =
-        argParser.getTrailingArguments();
+    final ArrayList<String> dnStrings = new ArrayList<String>();
+    final ArrayList<String> attrAndDNStrings = argParser.getTrailingArguments();
 
     if (attrAndDNStrings.isEmpty())
     {
-      LocalizableMessage message = ERR_LDAPCOMPARE_NO_ATTR.get();
+      final LocalizableMessage message = ERR_LDAPCOMPARE_NO_ATTR.get();
       println(message);
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
 
     // First element should be an attribute string.
-    String attributeString = attrAndDNStrings.remove(0);
+    final String attributeString = attrAndDNStrings.remove(0);
 
     // Rest are DN strings
-    for (String s : attrAndDNStrings)
+    for (final String s : attrAndDNStrings)
     {
       dnStrings.add(s);
     }
@@ -319,32 +449,31 @@
     }
 
     // parse the attribute string
-    int idx = attributeString.indexOf(":");
+    final int idx = attributeString.indexOf(":");
     if (idx == -1)
     {
-      LocalizableMessage message =
-          ERR_LDAPCOMPARE_INVALID_ATTR_STRING.get(attributeString);
+      final LocalizableMessage message = ERR_LDAPCOMPARE_INVALID_ATTR_STRING
+          .get(attributeString);
       println(message);
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
-    String attributeType = attributeString.substring(0, idx);
+    final String attributeType = attributeString.substring(0, idx);
     ByteString attributeVal;
-    String remainder =
-        attributeString.substring(idx + 1, attributeString.length());
+    final String remainder = attributeString.substring(idx + 1, attributeString
+        .length());
     if (remainder.length() > 0)
     {
-      char nextChar = remainder.charAt(0);
+      final char nextChar = remainder.charAt(0);
       if (nextChar == ':')
       {
-        String base64 = remainder.substring(1, remainder.length());
+        final String base64 = remainder.substring(1, remainder.length());
         try
         {
           attributeVal = Base64.decode(base64);
         }
-        catch (LocalizedIllegalArgumentException e)
+        catch (final LocalizedIllegalArgumentException e)
         {
-          println(INFO_COMPARE_CANNOT_BASE64_DECODE_ASSERTION_VALUE
-              .get());
+          println(INFO_COMPARE_CANNOT_BASE64_DECODE_ASSERTION_VALUE.get());
           return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
       }
@@ -352,14 +481,13 @@
       {
         try
         {
-          String filePath = remainder.substring(1, remainder.length());
-          attributeVal =
-              ByteString.wrap(Utils.readBytesFromFile(filePath));
+          final String filePath = remainder.substring(1, remainder.length());
+          attributeVal = ByteString.wrap(Utils.readBytesFromFile(filePath));
         }
-        catch (Exception e)
+        catch (final Exception e)
         {
-          println(INFO_COMPARE_CANNOT_READ_ASSERTION_VALUE_FROM_FILE
-              .get(String.valueOf(e)));
+          println(INFO_COMPARE_CANNOT_READ_ASSERTION_VALUE_FROM_FILE.get(String
+              .valueOf(e)));
           return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
       }
@@ -373,22 +501,22 @@
       attributeVal = ByteString.valueOf(remainder);
     }
 
-    CompareRequest compare =
-        Requests.newCompareRequest("", attributeType, attributeVal);
+    final CompareRequest compare = Requests.newCompareRequest("",
+        attributeType, attributeVal);
 
     if (controlStr.isPresent())
     {
-      for (String ctrlString : controlStr.getValues())
+      for (final String ctrlString : controlStr.getValues())
       {
         try
         {
-          Control ctrl = Utils.getControl(ctrlString);
+          final Control ctrl = Utils.getControl(ctrlString);
           compare.addControl(ctrl);
         }
-        catch (DecodeException de)
+        catch (final DecodeException de)
         {
-          LocalizableMessage message =
-              ERR_TOOL_INVALID_CONTROL_STRING.get(ctrlString);
+          final LocalizableMessage message = ERR_TOOL_INVALID_CONTROL_STRING
+              .get(ctrlString);
           println(message);
           ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
@@ -397,29 +525,29 @@
 
     if (proxyAuthzID.isPresent())
     {
-      Control proxyControl =
-          new ProxiedAuthV2Control(proxyAuthzID.getValue());
+      final Control proxyControl = ProxiedAuthV2RequestControl
+          .newControl(proxyAuthzID.getValue());
       compare.addControl(proxyControl);
     }
 
     if (assertionFilter.isPresent())
     {
-      String filterString = assertionFilter.getValue();
+      final String filterString = assertionFilter.getValue();
       Filter filter;
       try
       {
         filter = Filter.valueOf(filterString);
 
         // FIXME -- Change this to the correct OID when the official one
-        // is
-        // assigned.
-        Control assertionControl = new AssertionControl(true, filter);
+        // is assigned.
+        final Control assertionControl = AssertionRequestControl.newControl(
+            true, filter);
         compare.addControl(assertionControl);
       }
-      catch (LocalizedIllegalArgumentException le)
+      catch (final LocalizedIllegalArgumentException le)
       {
-        LocalizableMessage message =
-            ERR_LDAP_ASSERTION_INVALID_FILTER.get(le.getMessage());
+        final LocalizableMessage message = ERR_LDAP_ASSERTION_INVALID_FILTER
+            .get(le.getMessage());
         println(message);
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
@@ -437,10 +565,10 @@
       {
         rdr = new BufferedReader(new FileReader(filename.getValue()));
       }
-      catch (FileNotFoundException t)
+      catch (final FileNotFoundException t)
       {
-        println(ERR_LDAPCOMPARE_ERROR_READING_FILE.get(filename
-            .getValue(), t.toString()));
+        println(ERR_LDAPCOMPARE_ERROR_READING_FILE.get(filename.getValue(), t
+            .toString()));
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
     }
@@ -452,11 +580,18 @@
       {
         connection = connectionFactory.getConnection();
       }
-      catch (ErrorResultException ere)
+      catch (final ErrorResultException ere)
       {
         println(LocalizableMessage.raw(ere.getMessage()));
         return ere.getResult().getResultCode().intValue();
       }
+      catch (final InterruptedException e)
+      {
+        // This shouldn't happen because there are no other threads to
+        // interrupt this one.
+        println(LocalizableMessage.raw(e.getLocalizedMessage()));
+        return ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue();
+      }
     }
 
     try
@@ -464,7 +599,7 @@
       int result;
       if (rdr == null)
       {
-        for (String dn : dnStrings)
+        for (final String dn : dnStrings)
         {
           compare.setName(dn);
           result = executeCompare(compare, connection);
@@ -489,10 +624,10 @@
             }
           }
         }
-        catch (IOException ioe)
+        catch (final IOException ioe)
         {
-          println(ERR_LDAPCOMPARE_ERROR_READING_FILE.get(filename
-              .getValue(), ioe.toString()));
+          println(ERR_LDAPCOMPARE_ERROR_READING_FILE.get(filename.getValue(),
+              ioe.toString()));
           return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
       }
@@ -509,7 +644,7 @@
         {
           rdr.close();
         }
-        catch (IOException ioe)
+        catch (final IOException ioe)
         {
           // Just ignore
         }
@@ -519,149 +654,4 @@
     return 0;
   }
 
-
-
-  private int executeCompare(CompareRequest request,
-      Connection connection)
-  {
-    println(INFO_PROCESSING_COMPARE_OPERATION.get(request
-        .getAttributeDescription().toString(), request
-        .getAssertionValueAsString(), request.getName().toString()));
-    if (connection != null)
-    {
-      try
-      {
-        Result result;
-        try
-        {
-          result = connection.compare(request);
-        }
-        catch (InterruptedException e)
-        {
-          // This shouldn't happen because there are no other threads to
-          // interrupt this one.
-          result = Responses.newResult(
-              ResultCode.CLIENT_SIDE_USER_CANCELLED).setCause(e)
-              .setDiagnosticMessage(e.getLocalizedMessage());
-          throw ErrorResultException.wrap(result);
-        }
-
-        if (result.getResultCode() == ResultCode.COMPARE_FALSE)
-        {
-          println(INFO_COMPARE_OPERATION_RESULT_FALSE.get(request
-              .getName().toString()));
-        }
-        else
-        {
-
-          println(INFO_COMPARE_OPERATION_RESULT_TRUE.get(request
-              .getName().toString()));
-        }
-      }
-      catch (ErrorResultException ere)
-      {
-        LocalizableMessage msg = INFO_OPERATION_FAILED.get("COMPARE");
-        println(msg);
-        Result r = ere.getResult();
-        println(ERR_TOOL_RESULT_CODE.get(r.getResultCode().intValue(),
-            r.getResultCode().toString()));
-        if ((r.getDiagnosticMessage() != null)
-            && (r.getDiagnosticMessage().length() > 0))
-        {
-          println(LocalizableMessage.raw(r.getDiagnosticMessage()));
-        }
-        if (r.getMatchedDN() != null && r.getMatchedDN().length() > 0)
-        {
-          println(ERR_TOOL_MATCHED_DN.get(r.getMatchedDN()));
-        }
-        return r.getResultCode().intValue();
-      }
-    }
-    return ResultCode.SUCCESS.intValue();
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested advanced mode.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         advanced mode.
-   */
-  public boolean isAdvancedMode()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested interactive
-   * behavior.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         interactive behavior.
-   */
-  public boolean isInteractive()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not this console application is running in its
-   * menu-driven mode. This can be used to dictate whether output should
-   * go to the error stream or not. In addition, it may also dictate
-   * whether or not sub-menus should display a cancel option as well as
-   * a quit option.
-   *
-   * @return Returns <code>true</code> if this console application is
-   *         running in its menu-driven mode.
-   */
-  public boolean isMenuDrivenMode()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested quiet output.
-   *
-   * @return Returns <code>true</code> if the user has requested quiet
-   *         output.
-   */
-  public boolean isQuiet()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested script-friendly
-   * output.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         script-friendly output.
-   */
-  public boolean isScriptFriendly()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested verbose output.
-   *
-   * @return Returns <code>true</code> if the user has requested verbose
-   *         output.
-   */
-  public boolean isVerbose()
-  {
-    return verbose.isPresent();
-  }
-
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/LDAPModify.java b/sdk/src/com/sun/opends/sdk/tools/LDAPModify.java
index f79eeec..885a450 100644
--- a/sdk/src/com/sun/opends/sdk/tools/LDAPModify.java
+++ b/sdk/src/com/sun/opends/sdk/tools/LDAPModify.java
@@ -31,7 +31,7 @@
 
 import static com.sun.opends.sdk.messages.Messages.*;
 import static com.sun.opends.sdk.tools.ToolConstants.*;
-import static com.sun.opends.sdk.tools.Utils.*;
+import static com.sun.opends.sdk.tools.Utils.filterExitCode;
 
 import java.io.FileInputStream;
 import java.io.IOException;
@@ -39,6 +39,7 @@
 import java.io.OutputStream;
 import java.util.Collection;
 import java.util.LinkedList;
+import java.util.List;
 import java.util.StringTokenizer;
 
 import org.opends.sdk.*;
@@ -53,20 +54,254 @@
 
 
 
-
 /**
- * A tool that can be used to issue update (Add/Delete/Modify/ModifyDN)
- * requests to the Directory Server.
+ * A tool that can be used to issue update (Add/Delete/Modify/ModifyDN) requests
+ * to the Directory Server.
  */
 public final class LDAPModify extends ConsoleApplication
 {
-  private Connection connection;
+  private class VisitorImpl implements
+      ChangeRecordVisitor<Integer, java.lang.Void>
+  {
+    public Integer visitChangeRecord(final Void aVoid, final AddRequest change)
+    {
+      for (final Control control : controls)
+      {
+        change.addControl(control);
+      }
+      final String opType = "ADD";
+      println(INFO_PROCESSING_OPERATION
+          .get(opType, change.getName().toString()));
+      if (connection != null)
+      {
+        try
+        {
+          Result r;
+          try
+          {
+            r = connection.add(change);
+          }
+          catch (final InterruptedException e)
+          {
+            // This shouldn't happen because there are no other threads
+            // to interrupt this one.
+            r = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
+                .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
+            throw ErrorResultException.wrap(r);
+          }
+          printResult(opType, change.getName().toString(), r);
+          return r.getResultCode().intValue();
+        }
+        catch (final ErrorResultException ere)
+        {
+          return Utils.printErrorMessage(LDAPModify.this, ere);
+        }
+      }
+      return ResultCode.SUCCESS.intValue();
+    }
 
-  private EntryWriter writer;
 
-  private Collection<Control> controls;
 
-  private BooleanArgument verbose;
+    public Integer visitChangeRecord(final Void aVoid,
+        final DeleteRequest change)
+    {
+      for (final Control control : controls)
+      {
+        change.addControl(control);
+      }
+      final String opType = "DELETE";
+      println(INFO_PROCESSING_OPERATION
+          .get(opType, change.getName().toString()));
+      if (connection != null)
+      {
+        try
+        {
+          Result r;
+          try
+          {
+            r = connection.delete(change);
+          }
+          catch (final InterruptedException e)
+          {
+            // This shouldn't happen because there are no other threads
+            // to interrupt this one.
+            r = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
+                .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
+            throw ErrorResultException.wrap(r);
+          }
+          printResult(opType, change.getName().toString(), r);
+          return r.getResultCode().intValue();
+        }
+        catch (final ErrorResultException ere)
+        {
+          return Utils.printErrorMessage(LDAPModify.this, ere);
+        }
+      }
+      return ResultCode.SUCCESS.intValue();
+    }
+
+
+
+    public Integer visitChangeRecord(final Void aVoid,
+        final ModifyDNRequest change)
+    {
+      for (final Control control : controls)
+      {
+        change.addControl(control);
+      }
+      final String opType = "MODIFY DN";
+      println(INFO_PROCESSING_OPERATION
+          .get(opType, change.getName().toString()));
+      if (connection != null)
+      {
+        try
+        {
+          Result r;
+          try
+          {
+            r = connection.modifyDN(change);
+          }
+          catch (final InterruptedException e)
+          {
+            // This shouldn't happen because there are no other threads
+            // to interrupt this one.
+            r = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
+                .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
+            throw ErrorResultException.wrap(r);
+          }
+          printResult(opType, change.getName().toString(), r);
+          return r.getResultCode().intValue();
+        }
+        catch (final ErrorResultException ere)
+        {
+          return Utils.printErrorMessage(LDAPModify.this, ere);
+        }
+      }
+      return ResultCode.SUCCESS.intValue();
+    }
+
+
+
+    public Integer visitChangeRecord(final Void aVoid,
+        final ModifyRequest change)
+    {
+      for (final Control control : controls)
+      {
+        change.addControl(control);
+      }
+      final String opType = "MODIFY";
+      println(INFO_PROCESSING_OPERATION
+          .get(opType, change.getName().toString()));
+      if (connection != null)
+      {
+        try
+        {
+          Result r;
+          try
+          {
+            r = connection.modify(change);
+          }
+          catch (final InterruptedException e)
+          {
+            // This shouldn't happen because there are no other threads
+            // to interrupt this one.
+            r = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
+                .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
+            throw ErrorResultException.wrap(r);
+          }
+          printResult(opType, change.getName().toString(), r);
+          return r.getResultCode().intValue();
+        }
+        catch (final ErrorResultException ere)
+        {
+          return Utils.printErrorMessage(LDAPModify.this, ere);
+        }
+      }
+      return ResultCode.SUCCESS.intValue();
+    }
+
+
+
+    private void printResult(final String operationType, final String name,
+        final Result r)
+    {
+      if (r.getResultCode() != ResultCode.SUCCESS
+          && r.getResultCode() != ResultCode.REFERRAL)
+      {
+        final LocalizableMessage msg = INFO_OPERATION_FAILED.get(operationType);
+        println(msg);
+        println(ERR_TOOL_RESULT_CODE.get(r.getResultCode().intValue(), r
+            .getResultCode().toString()));
+        if ((r.getDiagnosticMessage() != null)
+            && (r.getDiagnosticMessage().length() > 0))
+        {
+          println(LocalizableMessage.raw(r.getDiagnosticMessage()));
+        }
+        if (r.getMatchedDN() != null && r.getMatchedDN().length() > 0)
+        {
+          println(ERR_TOOL_MATCHED_DN.get(r.getMatchedDN()));
+        }
+      }
+      else
+      {
+        final LocalizableMessage msg = INFO_OPERATION_SUCCESSFUL.get(
+            operationType, name);
+        println(msg);
+        if ((r.getDiagnosticMessage() != null)
+            && (r.getDiagnosticMessage().length() > 0))
+        {
+          println(LocalizableMessage.raw(r.getDiagnosticMessage()));
+        }
+        if (r.getReferralURIs() != null)
+        {
+          for (final String uri : r.getReferralURIs())
+          {
+            println(LocalizableMessage.raw(uri));
+          }
+        }
+      }
+
+      try
+      {
+        final PreReadResponseControl control = r.getControl(
+            PreReadResponseControl.DECODER, new DecodeOptions());
+        if (control != null)
+        {
+          println(INFO_LDAPMODIFY_PREREAD_ENTRY.get());
+          writer.writeEntry(control.getEntry());
+        }
+      }
+      catch (final DecodeException de)
+      {
+        println(ERR_DECODE_CONTROL_FAILURE.get(de.getLocalizedMessage()));
+      }
+      catch (final IOException ioe)
+      {
+        throw new RuntimeException(ioe);
+      }
+
+      try
+      {
+        final PostReadResponseControl control = r.getControl(
+            PostReadResponseControl.DECODER, new DecodeOptions());
+        if (control != null)
+        {
+          println(INFO_LDAPMODIFY_POSTREAD_ENTRY.get());
+          writer.writeEntry(control.getEntry());
+        }
+      }
+      catch (final DecodeException de)
+      {
+        println(ERR_DECODE_CONTROL_FAILURE.get(de.getLocalizedMessage()));
+      }
+      catch (final IOException ioe)
+      {
+        throw new RuntimeException(ioe);
+      }
+
+      // TODO: CSN control
+    }
+  }
 
 
 
@@ -77,24 +312,24 @@
    *          The command-line arguments provided to this program.
    */
 
-  public static void main(String[] args)
+  public static void main(final String[] args)
   {
-    int retCode = mainModify(args, System.in, System.out, System.err);
+    final int retCode = mainModify(args, System.in, System.out, System.err);
     System.exit(filterExitCode(retCode));
   }
 
 
 
   /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the LDAPModify tool.
+   * Parses the provided command-line arguments and uses that information to run
+   * the LDAPModify tool.
    *
    * @param args
    *          The command-line arguments provided to this program.
    * @return The error code.
    */
 
-  static int mainModify(String[] args)
+  static int mainModify(final String[] args)
   {
     return mainModify(args, System.in, System.out, System.err);
   }
@@ -102,33 +337,43 @@
 
 
   /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the LDAPModify tool.
+   * Parses the provided command-line arguments and uses that information to run
+   * the LDAPModify tool.
    *
    * @param args
-   *          The command-line arguments provided to this program.
-   *          specified, the number of matching entries should be
-   *          returned or not.
+   *          The command-line arguments provided to this program. specified,
+   *          the number of matching entries should be returned or not.
    * @param inStream
-   *          The input stream to use for standard input, or
-   *          <CODE>null</CODE> if standard input is not needed.
+   *          The input stream to use for standard input, or <CODE>null</CODE>
+   *          if standard input is not needed.
    * @param outStream
-   *          The output stream to use for standard output, or
-   *          <CODE>null</CODE> if standard output is not needed.
+   *          The output stream to use for standard output, or <CODE>null</CODE>
+   *          if standard output is not needed.
    * @param errStream
-   *          The output stream to use for standard error, or
-   *          <CODE>null</CODE> if standard error is not needed.
+   *          The output stream to use for standard error, or <CODE>null</CODE>
+   *          if standard error is not needed.
    * @return The error code.
    */
-  static int mainModify(String[] args, InputStream inStream,
-      OutputStream outStream, OutputStream errStream)
+  static int mainModify(final String[] args, final InputStream inStream,
+      final OutputStream outStream, final OutputStream errStream)
   {
     return new LDAPModify(inStream, outStream, errStream).run(args);
   }
 
 
 
-  private LDAPModify(InputStream in, OutputStream out, OutputStream err)
+  private Connection connection;
+
+  private EntryWriter writer;
+
+  private Collection<Control> controls;
+
+  private BooleanArgument verbose;
+
+
+
+  private LDAPModify(final InputStream in, final OutputStream out,
+      final OutputStream err)
   {
     super(in, out, err);
 
@@ -136,12 +381,97 @@
 
 
 
-  private int run(String[] args)
+  /**
+   * Indicates whether or not the user has requested advanced mode.
+   *
+   * @return Returns <code>true</code> if the user has requested advanced mode.
+   */
+  @Override
+  public boolean isAdvancedMode()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested interactive behavior.
+   *
+   * @return Returns <code>true</code> if the user has requested interactive
+   *         behavior.
+   */
+  @Override
+  public boolean isInteractive()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not this console application is running in its
+   * menu-driven mode. This can be used to dictate whether output should go to
+   * the error stream or not. In addition, it may also dictate whether or not
+   * sub-menus should display a cancel option as well as a quit option.
+   *
+   * @return Returns <code>true</code> if this console application is running in
+   *         its menu-driven mode.
+   */
+  @Override
+  public boolean isMenuDrivenMode()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested quiet output.
+   *
+   * @return Returns <code>true</code> if the user has requested quiet output.
+   */
+  @Override
+  public boolean isQuiet()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested script-friendly output.
+   *
+   * @return Returns <code>true</code> if the user has requested script-friendly
+   *         output.
+   */
+  @Override
+  public boolean isScriptFriendly()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested verbose output.
+   *
+   * @return Returns <code>true</code> if the user has requested verbose output.
+   */
+  @Override
+  public boolean isVerbose()
+  {
+    return verbose.isPresent();
+  }
+
+
+
+  private int run(final String[] args)
   {
     // Create the command-line argument parser for use with this
     // program.
-    LocalizableMessage toolDescription = INFO_LDAPMODIFY_TOOL_DESCRIPTION.get();
-    ArgumentParser argParser = new ArgumentParser(LDAPModify.class
+    final LocalizableMessage toolDescription = INFO_LDAPMODIFY_TOOL_DESCRIPTION
+        .get();
+    final ArgumentParser argParser = new ArgumentParser(LDAPModify.class
         .getName(), toolDescription, false);
     ArgumentParserConnectionFactory connectionFactory;
 
@@ -163,10 +493,9 @@
 
     try
     {
-      connectionFactory = new ArgumentParserConnectionFactory(
-          argParser, this);
-      propertiesFileArgument = new StringArgument("propertiesFilePath",
-          null, OPTION_LONG_PROP_FILE_PATH, false, false, true,
+      connectionFactory = new ArgumentParserConnectionFactory(argParser, this);
+      propertiesFileArgument = new StringArgument("propertiesFilePath", null,
+          OPTION_LONG_PROP_FILE_PATH, false, false, true,
           INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null,
           INFO_DESCRIPTION_PROP_FILE_PATH.get());
       argParser.addArgument(propertiesFileArgument);
@@ -190,8 +519,8 @@
       argParser.addArgument(filename);
 
       proxyAuthzID = new StringArgument("proxy_authzid",
-          OPTION_SHORT_PROXYAUTHID, OPTION_LONG_PROXYAUTHID, false,
-          false, true, INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
+          OPTION_SHORT_PROXYAUTHID, OPTION_LONG_PROXYAUTHID, false, false,
+          true, INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
           INFO_DESCRIPTION_PROXY_AUTHZID.get());
       proxyAuthzID.setPropertyName(OPTION_LONG_PROXYAUTHID);
       argParser.addArgument(proxyAuthzID);
@@ -217,22 +546,22 @@
       postReadAttributes.setPropertyName("postReadAttributes");
       argParser.addArgument(postReadAttributes);
 
-      controlStr = new StringArgument("control", 'J', "control", false,
-          true, true, INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
+      controlStr = new StringArgument("control", 'J', "control", false, true,
+          true, INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
           INFO_DESCRIPTION_CONTROLS.get());
       controlStr.setPropertyName("control");
       argParser.addArgument(controlStr);
 
-      version = new IntegerArgument("version",
-          OPTION_SHORT_PROTOCOL_VERSION, OPTION_LONG_PROTOCOL_VERSION,
-          false, false, true, INFO_PROTOCOL_VERSION_PLACEHOLDER.get(),
-          3, null, INFO_DESCRIPTION_VERSION.get());
+      version = new IntegerArgument("version", OPTION_SHORT_PROTOCOL_VERSION,
+          OPTION_LONG_PROTOCOL_VERSION, false, false, true,
+          INFO_PROTOCOL_VERSION_PLACEHOLDER.get(), 3, null,
+          INFO_DESCRIPTION_VERSION.get());
       version.setPropertyName(OPTION_LONG_PROTOCOL_VERSION);
       argParser.addArgument(version);
 
-      encodingStr = new StringArgument("encoding", 'i', "encoding",
-          false, false, true, INFO_ENCODING_PLACEHOLDER.get(), null,
-          null, INFO_DESCRIPTION_ENCODING.get());
+      encodingStr = new StringArgument("encoding", 'i', "encoding", false,
+          false, true, INFO_ENCODING_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_ENCODING.get());
       encodingStr.setPropertyName("encoding");
       argParser.addArgument(encodingStr);
 
@@ -256,9 +585,10 @@
       argParser.addArgument(showUsage);
       argParser.setUsageArgument(showUsage, getOutputStream());
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
+      final LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae
+          .getMessage());
       println(message);
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
@@ -269,9 +599,10 @@
       argParser.parseArguments(args);
       connectionFactory.validate();
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
+      final LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae
+          .getMessage());
       println(message);
       println(argParser.getUsageMessage());
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -286,7 +617,7 @@
 
     try
     {
-      int versionNumber = version.getIntValue();
+      final int versionNumber = version.getIntValue();
       if (versionNumber != 2 && versionNumber != 3)
       {
         println(ERR_DESCRIPTION_INVALID_VERSION.get(String
@@ -294,10 +625,10 @@
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      println(ERR_DESCRIPTION_INVALID_VERSION.get(String
-          .valueOf(version.getValue())));
+      println(ERR_DESCRIPTION_INVALID_VERSION.get(String.valueOf(version
+          .getValue())));
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
 
@@ -310,16 +641,16 @@
     controls = new LinkedList<Control>();
     if (controlStr.isPresent())
     {
-      for (String ctrlString : controlStr.getValues())
+      for (final String ctrlString : controlStr.getValues())
       {
         try
         {
-          Control ctrl = Utils.getControl(ctrlString);
+          final Control ctrl = Utils.getControl(ctrlString);
           controls.add(ctrl);
         }
-        catch (DecodeException de)
+        catch (final DecodeException de)
         {
-          LocalizableMessage message = ERR_TOOL_INVALID_CONTROL_STRING
+          final LocalizableMessage message = ERR_TOOL_INVALID_CONTROL_STRING
               .get(ctrlString);
           println(message);
           ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -329,29 +660,29 @@
 
     if (proxyAuthzID.isPresent())
     {
-      Control proxyControl = new ProxiedAuthV2Control(proxyAuthzID
-          .getValue());
+      final Control proxyControl = ProxiedAuthV2RequestControl
+          .newControl(proxyAuthzID.getValue());
       controls.add(proxyControl);
     }
 
     if (assertionFilter.isPresent())
     {
-      String filterString = assertionFilter.getValue();
+      final String filterString = assertionFilter.getValue();
       Filter filter;
       try
       {
         filter = Filter.valueOf(filterString);
 
         // FIXME -- Change this to the correct OID when the official one
-        // is
-        // assigned.
-        Control assertionControl = new AssertionControl(true, filter);
+        // is assigned.
+        final Control assertionControl = AssertionRequestControl.newControl(
+            true, filter);
         controls.add(assertionControl);
       }
-      catch (LocalizedIllegalArgumentException le)
+      catch (final LocalizedIllegalArgumentException le)
       {
-        LocalizableMessage message = ERR_LDAP_ASSERTION_INVALID_FILTER.get(le
-            .getMessage());
+        final LocalizableMessage message = ERR_LDAP_ASSERTION_INVALID_FILTER
+            .get(le.getMessage());
         println(message);
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
@@ -359,26 +690,29 @@
 
     if (preReadAttributes.isPresent())
     {
-      String valueStr = preReadAttributes.getValue();
-      StringTokenizer tokenizer = new StringTokenizer(valueStr, ", ");
-      PreReadControl.Request control = new PreReadControl.Request(true);
+      final String valueStr = preReadAttributes.getValue();
+      final StringTokenizer tokenizer = new StringTokenizer(valueStr, ", ");
+      final List<String> attributes = new LinkedList<String>();
       while (tokenizer.hasMoreTokens())
       {
-        control.addAttribute(tokenizer.nextToken());
+        attributes.add(tokenizer.nextToken());
       }
+      final PreReadRequestControl control = PreReadRequestControl.newControl(
+          true, attributes);
       controls.add(control);
     }
 
     if (postReadAttributes.isPresent())
     {
-      String valueStr = postReadAttributes.getValue();
-      StringTokenizer tokenizer = new StringTokenizer(valueStr, ", ");
-      PostReadControl.Request control = new PostReadControl.Request(
-          true);
+      final String valueStr = postReadAttributes.getValue();
+      final StringTokenizer tokenizer = new StringTokenizer(valueStr, ", ");
+      final List<String> attributes = new LinkedList<String>();
       while (tokenizer.hasMoreTokens())
       {
-        control.addAttribute(tokenizer.nextToken());
+        attributes.add(tokenizer.nextToken());
       }
+      final PostReadRequestControl control = PostReadRequestControl.newControl(
+          true, attributes);
       controls.add(control);
     }
 
@@ -388,16 +722,23 @@
       {
         connection = connectionFactory.getConnection();
       }
-      catch (ErrorResultException ere)
+      catch (final ErrorResultException ere)
       {
         return Utils.printErrorMessage(this, ere);
       }
+      catch (final InterruptedException e)
+      {
+        // This shouldn't happen because there are no other threads to
+        // interrupt this one.
+        println(LocalizableMessage.raw(e.getLocalizedMessage()));
+        return ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue();
+      }
     }
 
     Utils.printPasswordPolicyResults(this, connection);
 
     writer = new LDIFEntryWriter(getOutputStream());
-    VisitorImpl visitor = new VisitorImpl();
+    final VisitorImpl visitor = new VisitorImpl();
     try
     {
       ChangeRecordReader reader;
@@ -405,13 +746,13 @@
       {
         try
         {
-          reader = new LDIFChangeRecordReader(new FileInputStream(
-              filename.getValue()));
+          reader = new LDIFChangeRecordReader(new FileInputStream(filename
+              .getValue()));
         }
-        catch (Exception e)
+        catch (final Exception e)
         {
-          LocalizableMessage message = ERR_LDIF_FILE_CANNOT_OPEN_FOR_READ.get(
-              filename.getValue(), e.getLocalizedMessage());
+          final LocalizableMessage message = ERR_LDIF_FILE_CANNOT_OPEN_FOR_READ
+              .get(filename.getValue(), e.getLocalizedMessage());
           println(message);
           return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
@@ -434,10 +775,10 @@
           }
         }
       }
-      catch (IOException ioe)
+      catch (final IOException ioe)
       {
-        LocalizableMessage message = ERR_LDIF_FILE_READ_ERROR.get(filename
-            .getValue(), ioe.getLocalizedMessage());
+        final LocalizableMessage message = ERR_LDIF_FILE_READ_ERROR.get(
+            filename.getValue(), ioe.getLocalizedMessage());
         println(message);
         return ResultCode.CLIENT_SIDE_LOCAL_ERROR.intValue();
       }
@@ -452,326 +793,4 @@
 
     return ResultCode.SUCCESS.intValue();
   }
-
-
-
-  private class VisitorImpl implements
-      ChangeRecordVisitor<Integer, java.lang.Void>
-  {
-    private void printResult(String operationType, String name, Result r)
-    {
-      if (r.getResultCode() != ResultCode.SUCCESS
-          && r.getResultCode() != ResultCode.REFERRAL)
-      {
-        LocalizableMessage msg = INFO_OPERATION_FAILED.get(operationType);
-        println(msg);
-        println(ERR_TOOL_RESULT_CODE.get(r.getResultCode().intValue(),
-            r.getResultCode().toString()));
-        if ((r.getDiagnosticMessage() != null)
-            && (r.getDiagnosticMessage().length() > 0))
-        {
-          println(LocalizableMessage.raw(r.getDiagnosticMessage()));
-        }
-        if (r.getMatchedDN() != null && r.getMatchedDN().length() > 0)
-        {
-          println(ERR_TOOL_MATCHED_DN.get(r.getMatchedDN()));
-        }
-      }
-      else
-      {
-        LocalizableMessage msg = INFO_OPERATION_SUCCESSFUL
-            .get(operationType, name);
-        println(msg);
-        if ((r.getDiagnosticMessage() != null)
-            && (r.getDiagnosticMessage().length() > 0))
-        {
-          println(LocalizableMessage.raw(r.getDiagnosticMessage()));
-        }
-        if (r.getReferralURIs() != null)
-        {
-          for (String uri : r.getReferralURIs())
-          {
-            println(LocalizableMessage.raw(uri));
-          }
-        }
-      }
-
-      Control control = r
-          .getControl(PreReadControl.OID_LDAP_READENTRY_PREREAD);
-      if (control != null && control instanceof PreReadControl.Response)
-      {
-        PreReadControl.Response dc = (PreReadControl.Response) control;
-        println(INFO_LDAPMODIFY_PREREAD_ENTRY.get());
-        try
-        {
-          writer.writeEntry(dc.getSearchEntry());
-        }
-        catch (IOException ioe)
-        {
-          throw new RuntimeException(ioe);
-        }
-      }
-      control = r
-          .getControl(PostReadControl.OID_LDAP_READENTRY_POSTREAD);
-      if (control != null
-          && control instanceof PostReadControl.Response)
-      {
-        PostReadControl.Response dc = (PostReadControl.Response) control;
-        println(INFO_LDAPMODIFY_POSTREAD_ENTRY.get());
-        try
-        {
-          writer.writeEntry(dc.getSearchEntry());
-        }
-        catch (IOException ioe)
-        {
-          throw new RuntimeException(ioe);
-        }
-      }
-      // TODO: CSN control
-    }
-
-
-
-    public Integer visitChangeRecord(Void aVoid, AddRequest change)
-    {
-      for (Control control : controls)
-      {
-        change.addControl(control);
-      }
-      String opType = "ADD";
-      println(INFO_PROCESSING_OPERATION.get(opType, change.getName()
-          .toString()));
-      if (connection != null)
-      {
-        try
-        {
-          Result r;
-          try
-          {
-            r = connection.add(change);
-          }
-          catch (InterruptedException e)
-          {
-            // This shouldn't happen because there are no other threads
-            // to interrupt this one.
-            r = Responses.newResult(
-                ResultCode.CLIENT_SIDE_USER_CANCELLED).setCause(e)
-                .setDiagnosticMessage(e.getLocalizedMessage());
-            throw ErrorResultException.wrap(r);
-          }
-          printResult(opType, change.getName().toString(), r);
-          return r.getResultCode().intValue();
-        }
-        catch (ErrorResultException ere)
-        {
-          return Utils.printErrorMessage(LDAPModify.this, ere);
-        }
-      }
-      return ResultCode.SUCCESS.intValue();
-    }
-
-
-
-    public Integer visitChangeRecord(Void aVoid, DeleteRequest change)
-    {
-      for (Control control : controls)
-      {
-        change.addControl(control);
-      }
-      String opType = "DELETE";
-      println(INFO_PROCESSING_OPERATION.get(opType, change.getName()
-          .toString()));
-      if (connection != null)
-      {
-        try
-        {
-          Result r;
-          try
-          {
-            r = connection.delete(change);
-          }
-          catch (InterruptedException e)
-          {
-            // This shouldn't happen because there are no other threads
-            // to interrupt this one.
-            r = Responses.newResult(
-                ResultCode.CLIENT_SIDE_USER_CANCELLED).setCause(e)
-                .setDiagnosticMessage(e.getLocalizedMessage());
-            throw ErrorResultException.wrap(r);
-          }
-          printResult(opType, change.getName().toString(), r);
-          return r.getResultCode().intValue();
-        }
-        catch (ErrorResultException ere)
-        {
-          return Utils.printErrorMessage(LDAPModify.this, ere);
-        }
-      }
-      return ResultCode.SUCCESS.intValue();
-    }
-
-
-
-    public Integer visitChangeRecord(Void aVoid, ModifyDNRequest change)
-    {
-      for (Control control : controls)
-      {
-        change.addControl(control);
-      }
-      String opType = "MODIFY DN";
-      println(INFO_PROCESSING_OPERATION.get(opType, change.getName()
-          .toString()));
-      if (connection != null)
-      {
-        try
-        {
-          Result r;
-          try
-          {
-            r = connection.modifyDN(change);
-          }
-          catch (InterruptedException e)
-          {
-            // This shouldn't happen because there are no other threads
-            // to interrupt this one.
-            r = Responses.newResult(
-                ResultCode.CLIENT_SIDE_USER_CANCELLED).setCause(e)
-                .setDiagnosticMessage(e.getLocalizedMessage());
-            throw ErrorResultException.wrap(r);
-          }
-          printResult(opType, change.getName().toString(), r);
-          return r.getResultCode().intValue();
-        }
-        catch (ErrorResultException ere)
-        {
-          return Utils.printErrorMessage(LDAPModify.this, ere);
-        }
-      }
-      return ResultCode.SUCCESS.intValue();
-    }
-
-
-
-    public Integer visitChangeRecord(Void aVoid, ModifyRequest change)
-    {
-      for (Control control : controls)
-      {
-        change.addControl(control);
-      }
-      String opType = "MODIFY";
-      println(INFO_PROCESSING_OPERATION.get(opType, change.getName()
-          .toString()));
-      if (connection != null)
-      {
-        try
-        {
-          Result r;
-          try
-          {
-            r = connection.modify(change);
-          }
-          catch (InterruptedException e)
-          {
-            // This shouldn't happen because there are no other threads
-            // to interrupt this one.
-            r = Responses.newResult(
-                ResultCode.CLIENT_SIDE_USER_CANCELLED).setCause(e)
-                .setDiagnosticMessage(e.getLocalizedMessage());
-            throw ErrorResultException.wrap(r);
-          }
-          printResult(opType, change.getName().toString(), r);
-          return r.getResultCode().intValue();
-        }
-        catch (ErrorResultException ere)
-        {
-          return Utils.printErrorMessage(LDAPModify.this, ere);
-        }
-      }
-      return ResultCode.SUCCESS.intValue();
-    }
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested advanced mode.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         advanced mode.
-   */
-  public boolean isAdvancedMode()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested interactive
-   * behavior.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         interactive behavior.
-   */
-  public boolean isInteractive()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not this console application is running in its
-   * menu-driven mode. This can be used to dictate whether output should
-   * go to the error stream or not. In addition, it may also dictate
-   * whether or not sub-menus should display a cancel option as well as
-   * a quit option.
-   *
-   * @return Returns <code>true</code> if this console application is
-   *         running in its menu-driven mode.
-   */
-  public boolean isMenuDrivenMode()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested quiet output.
-   *
-   * @return Returns <code>true</code> if the user has requested quiet
-   *         output.
-   */
-  public boolean isQuiet()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested script-friendly
-   * output.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         script-friendly output.
-   */
-  public boolean isScriptFriendly()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested verbose output.
-   *
-   * @return Returns <code>true</code> if the user has requested verbose
-   *         output.
-   */
-  public boolean isVerbose()
-  {
-    return verbose.isPresent();
-  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/LDAPPasswordModify.java b/sdk/src/com/sun/opends/sdk/tools/LDAPPasswordModify.java
index 618ec88..fb209df 100644
--- a/sdk/src/com/sun/opends/sdk/tools/LDAPPasswordModify.java
+++ b/sdk/src/com/sun/opends/sdk/tools/LDAPPasswordModify.java
@@ -1,46 +1,76 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
 package com.sun.opends.sdk.tools;
 
+
+
 import static com.sun.opends.sdk.messages.Messages.*;
 import static com.sun.opends.sdk.tools.ToolConstants.*;
-import static com.sun.opends.sdk.tools.Utils.*;
+import static com.sun.opends.sdk.tools.Utils.filterExitCode;
 
 import java.io.InputStream;
 import java.io.OutputStream;
 
 import org.opends.sdk.*;
 import org.opends.sdk.controls.Control;
-import org.opends.sdk.extensions.PasswordModifyRequest;
-import org.opends.sdk.extensions.PasswordModifyResult;
-
+import org.opends.sdk.requests.PasswordModifyExtendedRequest;
+import org.opends.sdk.requests.Requests;
+import org.opends.sdk.responses.PasswordModifyExtendedResult;
+import org.opends.sdk.responses.Responses;
 
 
 
 /**
- * A tool that can be used to issue LDAP password modify extended
- * requests to the Directory Server. It exposes the three primary
- * options available for this operation, which are:
+ * A tool that can be used to issue LDAP password modify extended requests to
+ * the Directory Server. It exposes the three primary options available for this
+ * operation, which are:
  * <UL>
  * <LI>The user identity whose password should be changed.</LI>
  * <LI>The current password for the user.</LI>
  * <LI>The new password for the user.
  * </UL>
- * All of these are optional components that may be included or omitted
- * from the request.
+ * All of these are optional components that may be included or omitted from the
+ * request.
  */
-public class LDAPPasswordModify extends ConsoleApplication
+public final class LDAPPasswordModify extends ConsoleApplication
 {
-  private BooleanArgument verbose;
-
   /**
    * Parses the command-line arguments, establishes a connection to the
    * Directory Server, sends the password modify request, and reads the
    * response.
    *
-   * @param  args  The command-line arguments provided to this program.
+   * @param args
+   *          The command-line arguments provided to this program.
    */
-  public static void main(String[] args)
+  public static void main(final String[] args)
   {
-    int retCode = mainPasswordModify(args, System.in, System.out, System.err);
+    final int retCode = mainPasswordModify(args, System.in, System.out,
+        System.err);
     System.exit(filterExitCode(retCode));
   }
 
@@ -51,12 +81,12 @@
    * Directory Server, sends the password modify request, and reads the
    * response.
    *
-   * @param  args  The command-line arguments provided to this program.
-   *
-   * @return  An integer value of zero if everything completed successfully, or
-   *          a nonzero value if an error occurred.
+   * @param args
+   *          The command-line arguments provided to this program.
+   * @return An integer value of zero if everything completed successfully, or a
+   *         nonzero value if an error occurred.
    */
-  static int mainPasswordModify(String[] args)
+  static int mainPasswordModify(final String[] args)
   {
     return mainPasswordModify(args, System.in, System.out, System.err);
   }
@@ -64,149 +94,223 @@
 
 
   /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the LDAPPasswordModify tool.
+   * Parses the provided command-line arguments and uses that information to run
+   * the LDAPPasswordModify tool.
    *
    * @param args
-   *          The command-line arguments provided to this program.
-   *          specified, the number of matching entries should be
-   *          returned or not.
+   *          The command-line arguments provided to this program. specified,
+   *          the number of matching entries should be returned or not.
    * @param inStream
-   *          The input stream to use for standard input, or
-   *          <CODE>null</CODE> if standard input is not needed.
+   *          The input stream to use for standard input, or <CODE>null</CODE>
+   *          if standard input is not needed.
    * @param outStream
-   *          The output stream to use for standard output, or
-   *          <CODE>null</CODE> if standard output is not needed.
+   *          The output stream to use for standard output, or <CODE>null</CODE>
+   *          if standard output is not needed.
    * @param errStream
-   *          The output stream to use for standard error, or
-   *          <CODE>null</CODE> if standard error is not needed.
+   *          The output stream to use for standard error, or <CODE>null</CODE>
+   *          if standard error is not needed.
    * @return The error code.
    */
-  static int mainPasswordModify(String[] args, InputStream inStream,
-                                       OutputStream outStream, OutputStream errStream)
+  static int mainPasswordModify(final String[] args,
+      final InputStream inStream, final OutputStream outStream,
+      final OutputStream errStream)
   {
     return new LDAPPasswordModify(inStream, outStream, errStream).run(args);
   }
 
 
 
-  private LDAPPasswordModify(InputStream in, OutputStream out, OutputStream err)
+  private BooleanArgument verbose;
+
+
+
+  private LDAPPasswordModify(final InputStream in, final OutputStream out,
+      final OutputStream err)
   {
     super(in, out, err);
 
   }
 
-  private int run(String[] args)
+
+
+  /**
+   * Indicates whether or not the user has requested advanced mode.
+   *
+   * @return Returns <code>true</code> if the user has requested advanced mode.
+   */
+  @Override
+  public boolean isAdvancedMode()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested interactive behavior.
+   *
+   * @return Returns <code>true</code> if the user has requested interactive
+   *         behavior.
+   */
+  @Override
+  public boolean isInteractive()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not this console application is running in its
+   * menu-driven mode. This can be used to dictate whether output should go to
+   * the error stream or not. In addition, it may also dictate whether or not
+   * sub-menus should display a cancel option as well as a quit option.
+   *
+   * @return Returns <code>true</code> if this console application is running in
+   *         its menu-driven mode.
+   */
+  @Override
+  public boolean isMenuDrivenMode()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested quiet output.
+   *
+   * @return Returns <code>true</code> if the user has requested quiet output.
+   */
+  @Override
+  public boolean isQuiet()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested script-friendly output.
+   *
+   * @return Returns <code>true</code> if the user has requested script-friendly
+   *         output.
+   */
+  @Override
+  public boolean isScriptFriendly()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested verbose output.
+   *
+   * @return Returns <code>true</code> if the user has requested verbose output.
+   */
+  @Override
+  public boolean isVerbose()
+  {
+    return verbose.isPresent();
+  }
+
+
+
+  private int run(final String[] args)
   {
     // Create the command-line argument parser for use with this
     // program.
-    LocalizableMessage toolDescription = INFO_LDAPPWMOD_TOOL_DESCRIPTION.get();
-    ArgumentParser argParser =
-        new ArgumentParser(LDAPPasswordModify.class.getName(), toolDescription,
-            false);
+    final LocalizableMessage toolDescription = INFO_LDAPPWMOD_TOOL_DESCRIPTION
+        .get();
+    final ArgumentParser argParser = new ArgumentParser(
+        LDAPPasswordModify.class.getName(), toolDescription, false);
     ArgumentParserConnectionFactory connectionFactory;
 
     FileBasedArgument currentPWFile;
     FileBasedArgument newPWFile;
     BooleanArgument showUsage;
     IntegerArgument version;
-    StringArgument    currentPW;
+    StringArgument currentPW;
     StringArgument controlStr;
-    StringArgument    newPW;
+    StringArgument newPW;
     StringArgument proxyAuthzID;
     StringArgument propertiesFileArgument;
     BooleanArgument noPropertiesFileArgument;
 
     try
     {
-      connectionFactory =
-          new ArgumentParserConnectionFactory(argParser, this);
-      propertiesFileArgument =
-          new StringArgument("propertiesFilePath", null,
-              OPTION_LONG_PROP_FILE_PATH, false, false, true,
-              INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null,
-              INFO_DESCRIPTION_PROP_FILE_PATH.get());
+      connectionFactory = new ArgumentParserConnectionFactory(argParser, this);
+      propertiesFileArgument = new StringArgument("propertiesFilePath", null,
+          OPTION_LONG_PROP_FILE_PATH, false, false, true,
+          INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_PROP_FILE_PATH.get());
       argParser.addArgument(propertiesFileArgument);
       argParser.setFilePropertiesArgument(propertiesFileArgument);
 
-      noPropertiesFileArgument =
-          new BooleanArgument("noPropertiesFileArgument", null,
-              OPTION_LONG_NO_PROP_FILE, INFO_DESCRIPTION_NO_PROP_FILE
-                  .get());
+      noPropertiesFileArgument = new BooleanArgument(
+          "noPropertiesFileArgument", null, OPTION_LONG_NO_PROP_FILE,
+          INFO_DESCRIPTION_NO_PROP_FILE.get());
       argParser.addArgument(noPropertiesFileArgument);
       argParser.setNoPropertiesFileArgument(noPropertiesFileArgument);
 
       newPW = new StringArgument("newpw", 'n', "newPassword", false, false,
-          true, INFO_NEW_PASSWORD_PLACEHOLDER.get(),
-          null, null,
+          true, INFO_NEW_PASSWORD_PLACEHOLDER.get(), null, null,
           INFO_LDAPPWMOD_DESCRIPTION_NEWPW.get());
       newPW.setPropertyName("newPassword");
       argParser.addArgument(newPW);
 
-
-      newPWFile = new FileBasedArgument(
-          "newpwfile", 'F', "newPasswordFile",
+      newPWFile = new FileBasedArgument("newpwfile", 'F', "newPasswordFile",
           false, false, INFO_FILE_PLACEHOLDER.get(), null, null,
           INFO_LDAPPWMOD_DESCRIPTION_NEWPWFILE.get());
       newPWFile.setPropertyName("newPasswordFile");
       argParser.addArgument(newPWFile);
 
-
-      currentPW =
-          new StringArgument("currentpw", 'c', "currentPassword", false, false,
-              true, INFO_CURRENT_PASSWORD_PLACEHOLDER.get(),
-              null,  null,
-              INFO_LDAPPWMOD_DESCRIPTION_CURRENTPW.get());
+      currentPW = new StringArgument("currentpw", 'c', "currentPassword",
+          false, false, true, INFO_CURRENT_PASSWORD_PLACEHOLDER.get(), null,
+          null, INFO_LDAPPWMOD_DESCRIPTION_CURRENTPW.get());
       currentPW.setPropertyName("currentPassword");
       argParser.addArgument(currentPW);
 
-
-      currentPWFile =
-          new FileBasedArgument(
-              "currentpwfile", 'C', "currentPasswordFile",
-              false, false, INFO_FILE_PLACEHOLDER.get(), null, null,
-              INFO_LDAPPWMOD_DESCRIPTION_CURRENTPWFILE.get());
+      currentPWFile = new FileBasedArgument("currentpwfile", 'C',
+          "currentPasswordFile", false, false, INFO_FILE_PLACEHOLDER.get(),
+          null, null, INFO_LDAPPWMOD_DESCRIPTION_CURRENTPWFILE.get());
       currentPWFile.setPropertyName("currentPasswordFile");
       argParser.addArgument(currentPWFile);
 
-      proxyAuthzID =
-          new StringArgument("authzid", 'a', "authzID", false, false,
-              true, INFO_PROXYAUTHID_PLACEHOLDER.get(),
-              null, null,
-              INFO_LDAPPWMOD_DESCRIPTION_AUTHZID.get());
+      proxyAuthzID = new StringArgument("authzid", 'a', "authzID", false,
+          false, true, INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
+          INFO_LDAPPWMOD_DESCRIPTION_AUTHZID.get());
       proxyAuthzID.setPropertyName("authzID");
       argParser.addArgument(proxyAuthzID);
 
-      controlStr =
-          new StringArgument("control", 'J', "control", false, true,
-              true, INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
-              INFO_DESCRIPTION_CONTROLS.get());
+      controlStr = new StringArgument("control", 'J', "control", false, true,
+          true, INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_CONTROLS.get());
       controlStr.setPropertyName("control");
       argParser.addArgument(controlStr);
 
-      version =
-          new IntegerArgument("version", OPTION_SHORT_PROTOCOL_VERSION,
-              OPTION_LONG_PROTOCOL_VERSION, false, false, true,
-              INFO_PROTOCOL_VERSION_PLACEHOLDER.get(), 3, null,
-              INFO_DESCRIPTION_VERSION.get());
+      version = new IntegerArgument("version", OPTION_SHORT_PROTOCOL_VERSION,
+          OPTION_LONG_PROTOCOL_VERSION, false, false, true,
+          INFO_PROTOCOL_VERSION_PLACEHOLDER.get(), 3, null,
+          INFO_DESCRIPTION_VERSION.get());
       version.setPropertyName(OPTION_LONG_PROTOCOL_VERSION);
       argParser.addArgument(version);
 
-      verbose =
-          new BooleanArgument("verbose", 'v', "verbose",
-              INFO_DESCRIPTION_VERBOSE.get());
+      verbose = new BooleanArgument("verbose", 'v', "verbose",
+          INFO_DESCRIPTION_VERBOSE.get());
       verbose.setPropertyName("verbose");
       argParser.addArgument(verbose);
 
-      showUsage =
-          new BooleanArgument("showUsage", OPTION_SHORT_HELP,
-              OPTION_LONG_HELP, INFO_DESCRIPTION_SHOWUSAGE.get());
+      showUsage = new BooleanArgument("showUsage", OPTION_SHORT_HELP,
+          OPTION_LONG_HELP, INFO_DESCRIPTION_SHOWUSAGE.get());
       argParser.addArgument(showUsage);
       argParser.setUsageArgument(showUsage, getOutputStream());
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
+      final LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae
+          .getMessage());
       println(message);
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
@@ -217,9 +321,10 @@
       argParser.parseArguments(args);
       connectionFactory.validate();
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
+      final LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae
+          .getMessage());
       println(message);
       println(argParser.getUsageMessage());
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -232,10 +337,11 @@
       return 0;
     }
 
-    PasswordModifyRequest request = new PasswordModifyRequest();
+    final PasswordModifyExtendedRequest request = Requests
+        .newPasswordModifyExtendedRequest();
     try
     {
-      int versionNumber = version.getIntValue();
+      final int versionNumber = version.getIntValue();
       if (versionNumber != 2 && versionNumber != 3)
       {
         println(ERR_DESCRIPTION_INVALID_VERSION.get(String
@@ -243,26 +349,26 @@
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      println(ERR_DESCRIPTION_INVALID_VERSION.get(String
-          .valueOf(version.getValue())));
+      println(ERR_DESCRIPTION_INVALID_VERSION.get(String.valueOf(version
+          .getValue())));
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
 
     if (controlStr.isPresent())
     {
-      for (String ctrlString : controlStr.getValues())
+      for (final String ctrlString : controlStr.getValues())
       {
         try
         {
-          Control ctrl = Utils.getControl(ctrlString);
+          final Control ctrl = Utils.getControl(ctrlString);
           request.addControl(ctrl);
         }
-        catch (DecodeException de)
+        catch (final DecodeException de)
         {
-          LocalizableMessage message =
-              ERR_TOOL_INVALID_CONTROL_STRING.get(ctrlString);
+          final LocalizableMessage message = ERR_TOOL_INVALID_CONTROL_STRING
+              .get(ctrlString);
           println(message);
           ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
@@ -271,18 +377,16 @@
 
     if (newPW.isPresent() && newPWFile.isPresent())
     {
-      LocalizableMessage message = ERR_LDAPPWMOD_CONFLICTING_ARGS.get(
-          newPW.getLongIdentifier(),
-          newPWFile.getLongIdentifier());
+      final LocalizableMessage message = ERR_LDAPPWMOD_CONFLICTING_ARGS.get(
+          newPW.getLongIdentifier(), newPWFile.getLongIdentifier());
       println(message);
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
 
     if (currentPW.isPresent() && currentPWFile.isPresent())
     {
-      LocalizableMessage message = ERR_LDAPPWMOD_CONFLICTING_ARGS.get(
-          currentPW.getLongIdentifier(),
-          currentPWFile.getLongIdentifier());
+      final LocalizableMessage message = ERR_LDAPPWMOD_CONFLICTING_ARGS.get(
+          currentPW.getLongIdentifier(), currentPWFile.getLongIdentifier());
       println(message);
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
@@ -292,10 +396,17 @@
     {
       connection = connectionFactory.getConnection();
     }
-    catch (ErrorResultException ere)
+    catch (final ErrorResultException ere)
     {
       return Utils.printErrorMessage(this, ere);
     }
+    catch (final InterruptedException e)
+    {
+      // This shouldn't happen because there are no other threads to
+      // interrupt this one.
+      println(LocalizableMessage.raw(e.getLocalizedMessage()));
+      return ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue();
+    }
 
     if (proxyAuthzID.isPresent())
     {
@@ -320,38 +431,38 @@
       request.setNewPassword(ByteString.valueOf(newPWFile.getValue()));
     }
 
-    PasswordModifyResult result;
+    PasswordModifyExtendedResult result;
     try
     {
       try
       {
         result = connection.extendedRequest(request);
       }
-      catch (InterruptedException e)
+      catch (final InterruptedException e)
       {
         // This shouldn't happen because there are no other threads to
         // interrupt this one.
-        result = new PasswordModifyResult(
+        result = Responses.newPasswordModifyExtendedResult(
             ResultCode.CLIENT_SIDE_USER_CANCELLED).setCause(e)
             .setDiagnosticMessage(e.getLocalizedMessage());
         throw ErrorResultException.wrap(result);
       }
     }
-    catch (ErrorResultException e)
+    catch (final ErrorResultException e)
     {
-      LocalizableMessage message =
-          ERR_LDAPPWMOD_FAILED.get(e.getResult().getResultCode().intValue(),
-              e.getResult().getResultCode().toString());
+      LocalizableMessage message = ERR_LDAPPWMOD_FAILED
+          .get(e.getResult().getResultCode().intValue(), e.getResult()
+              .getResultCode().toString());
       println(message);
 
-      String errorMessage = e.getResult().getDiagnosticMessage();
+      final String errorMessage = e.getResult().getDiagnosticMessage();
       if ((errorMessage != null) && (errorMessage.length() > 0))
       {
         message = ERR_LDAPPWMOD_FAILURE_ERROR_MESSAGE.get(errorMessage);
         println(message);
       }
 
-      String matchedDN = e.getResult().getMatchedDN();
+      final String matchedDN = e.getResult().getMatchedDN();
       if (matchedDN != null && matchedDN.length() > 0)
       {
         message = ERR_LDAPPWMOD_FAILURE_MATCHED_DN.get(matchedDN);
@@ -363,7 +474,7 @@
     LocalizableMessage message = INFO_LDAPPWMOD_SUCCESSFUL.get();
     println(message);
 
-    String additionalInfo = result.getDiagnosticMessage();
+    final String additionalInfo = result.getDiagnosticMessage();
     if ((additionalInfo != null) && (additionalInfo.length() > 0))
     {
 
@@ -371,96 +482,13 @@
       println(message);
     }
 
-    if(result.getGenPassword() != null)
+    if (result.getGeneratedPassword() != null)
     {
-      message = INFO_LDAPPWMOD_GENERATED_PASSWORD.get(result.getGenPassword().toString());
+      message = INFO_LDAPPWMOD_GENERATED_PASSWORD.get(result
+          .getGeneratedPasswordAsString());
       println(message);
     }
 
     return 0;
   }
-
-
-
-  /**
-   * Indicates whether or not the user has requested advanced mode.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         advanced mode.
-   */
-  public boolean isAdvancedMode()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested interactive
-   * behavior.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         interactive behavior.
-   */
-  public boolean isInteractive()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not this console application is running in its
-   * menu-driven mode. This can be used to dictate whether output should
-   * go to the error stream or not. In addition, it may also dictate
-   * whether or not sub-menus should display a cancel option as well as
-   * a quit option.
-   *
-   * @return Returns <code>true</code> if this console application is
-   *         running in its menu-driven mode.
-   */
-  public boolean isMenuDrivenMode()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested quiet output.
-   *
-   * @return Returns <code>true</code> if the user has requested quiet
-   *         output.
-   */
-  public boolean isQuiet()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested script-friendly
-   * output.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         script-friendly output.
-   */
-  public boolean isScriptFriendly()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested verbose output.
-   *
-   * @return Returns <code>true</code> if the user has requested verbose
-   *         output.
-   */
-  public boolean isVerbose()
-  {
-    return verbose.isPresent();
-  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/LDAPSearch.java b/sdk/src/com/sun/opends/sdk/tools/LDAPSearch.java
index e371ad7..1741c99 100644
--- a/sdk/src/com/sun/opends/sdk/tools/LDAPSearch.java
+++ b/sdk/src/com/sun/opends/sdk/tools/LDAPSearch.java
@@ -31,13 +31,10 @@
 
 import static com.sun.opends.sdk.messages.Messages.*;
 import static com.sun.opends.sdk.tools.ToolConstants.*;
-import static com.sun.opends.sdk.tools.Utils.*;
+import static com.sun.opends.sdk.tools.Utils.filterExitCode;
 
 import java.io.*;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.StringTokenizer;
+import java.util.*;
 
 import org.opends.sdk.*;
 import org.opends.sdk.controls.*;
@@ -50,22 +47,16 @@
 import org.opends.sdk.responses.SearchResultEntry;
 import org.opends.sdk.responses.SearchResultReference;
 
+import com.sun.opends.sdk.controls.AccountUsabilityResponseControl;
 import com.sun.opends.sdk.util.StaticUtils;
 
 
 
 /**
- * A tool that can be used to issue Search requests to the Directory
- * Server.
+ * A tool that can be used to issue Search requests to the Directory Server.
  */
 public final class LDAPSearch extends ConsoleApplication
 {
-  private BooleanArgument verbose;
-
-  private EntryWriter ldifWriter;
-
-
-
   private class LDAPSearchResultHandler implements SearchResultHandler
   {
     private int entryCount = 0;
@@ -75,92 +66,108 @@
     /**
      * {@inheritDoc}
      */
-    public void handleEntry(SearchResultEntry entry)
+    public boolean handleEntry(final SearchResultEntry entry)
     {
       entryCount++;
 
-      Control control = entry
-          .getControl(EntryChangeNotificationControl.OID_ENTRY_CHANGE_NOTIFICATION);
-      if (control != null
-          && control instanceof EntryChangeNotificationControl)
+      try
       {
-        EntryChangeNotificationControl dc = (EntryChangeNotificationControl) control;
-        println(INFO_LDAPSEARCH_PSEARCH_CHANGE_TYPE.get(dc
-            .getChangeType().toString()));
-        String previousDN = dc.getPreviousDN();
-        if (previousDN != null)
+        final EntryChangeNotificationResponseControl control = entry
+            .getControl(EntryChangeNotificationResponseControl.DECODER,
+                new DecodeOptions());
+        if (control != null)
         {
-          println(INFO_LDAPSEARCH_PSEARCH_PREVIOUS_DN.get(previousDN));
+          println(INFO_LDAPSEARCH_PSEARCH_CHANGE_TYPE.get(control
+              .getChangeType().toString()));
+          final DN previousDN = control.getPreviousName();
+          if (previousDN != null)
+          {
+            println(INFO_LDAPSEARCH_PSEARCH_PREVIOUS_DN.get(previousDN
+                .toString()));
+          }
         }
       }
-      control = entry
-          .getControl(AccountUsabilityControl.OID_ACCOUNT_USABLE_CONTROL);
-      if (control != null
-          && control instanceof AccountUsabilityControl.Response)
+      catch (final DecodeException de)
       {
-        AccountUsabilityControl.Response dc = (AccountUsabilityControl.Response) control;
+        println(ERR_DECODE_CONTROL_FAILURE.get(de.getLocalizedMessage()));
+      }
 
-        println(INFO_LDAPSEARCH_ACCTUSABLE_HEADER.get());
-        if (dc.isUsable())
+      try
+      {
+        final AccountUsabilityResponseControl control = entry.getControl(
+            AccountUsabilityResponseControl.DECODER, new DecodeOptions());
+
+        if (control != null)
         {
-
-          println(INFO_LDAPSEARCH_ACCTUSABLE_IS_USABLE.get());
-          if (dc.getSecondsBeforeExpiration() > 0)
+          println(INFO_LDAPSEARCH_ACCTUSABLE_HEADER.get());
+          if (control.isUsable())
           {
-            int timeToExp = dc.getSecondsBeforeExpiration();
-            LocalizableMessage timeToExpStr = Utils.secondsToTimeString(timeToExp);
 
-            println(INFO_LDAPSEARCH_ACCTUSABLE_TIME_UNTIL_EXPIRATION
-                .get(timeToExpStr));
-          }
-        }
-        else
-        {
-
-          println(INFO_LDAPSEARCH_ACCTUSABLE_NOT_USABLE.get());
-          if (dc.isInactive())
-          {
-            println(INFO_LDAPSEARCH_ACCTUSABLE_ACCT_INACTIVE.get());
-          }
-          if (dc.isReset())
-          {
-            println(INFO_LDAPSEARCH_ACCTUSABLE_PW_RESET.get());
-          }
-          if (dc.isExpired())
-          {
-            println(INFO_LDAPSEARCH_ACCTUSABLE_PW_EXPIRED.get());
-
-            if (dc.getRemainingGraceLogins() > 0)
+            println(INFO_LDAPSEARCH_ACCTUSABLE_IS_USABLE.get());
+            if (control.getSecondsBeforeExpiration() > 0)
             {
-              println(INFO_LDAPSEARCH_ACCTUSABLE_REMAINING_GRACE.get(dc
-                  .getRemainingGraceLogins()));
+              final int timeToExp = control.getSecondsBeforeExpiration();
+              final LocalizableMessage timeToExpStr = Utils
+                  .secondsToTimeString(timeToExp);
+
+              println(INFO_LDAPSEARCH_ACCTUSABLE_TIME_UNTIL_EXPIRATION
+                  .get(timeToExpStr));
             }
           }
-          if (dc.isLocked())
+          else
           {
-            println(INFO_LDAPSEARCH_ACCTUSABLE_LOCKED.get());
-            if (dc.getSecondsBeforeUnlock() > 0)
-            {
-              int timeToUnlock = dc.getSecondsBeforeUnlock();
-              LocalizableMessage timeToUnlockStr = Utils
-                  .secondsToTimeString(timeToUnlock);
 
-              println(INFO_LDAPSEARCH_ACCTUSABLE_TIME_UNTIL_UNLOCK
-                  .get(timeToUnlockStr));
+            println(INFO_LDAPSEARCH_ACCTUSABLE_NOT_USABLE.get());
+            if (control.isInactive())
+            {
+              println(INFO_LDAPSEARCH_ACCTUSABLE_ACCT_INACTIVE.get());
+            }
+            if (control.isReset())
+            {
+              println(INFO_LDAPSEARCH_ACCTUSABLE_PW_RESET.get());
+            }
+            if (control.isExpired())
+            {
+              println(INFO_LDAPSEARCH_ACCTUSABLE_PW_EXPIRED.get());
+
+              if (control.getRemainingGraceLogins() > 0)
+              {
+                println(INFO_LDAPSEARCH_ACCTUSABLE_REMAINING_GRACE.get(control
+                    .getRemainingGraceLogins()));
+              }
+            }
+            if (control.isLocked())
+            {
+              println(INFO_LDAPSEARCH_ACCTUSABLE_LOCKED.get());
+              if (control.getSecondsBeforeUnlock() > 0)
+              {
+                final int timeToUnlock = control.getSecondsBeforeUnlock();
+                final LocalizableMessage timeToUnlockStr = Utils
+                    .secondsToTimeString(timeToUnlock);
+
+                println(INFO_LDAPSEARCH_ACCTUSABLE_TIME_UNTIL_UNLOCK
+                    .get(timeToUnlockStr));
+              }
             }
           }
         }
       }
+      catch (final DecodeException de)
+      {
+        println(ERR_DECODE_CONTROL_FAILURE.get(de.getLocalizedMessage()));
+      }
+
       try
       {
         ldifWriter.writeEntry(entry);
         ldifWriter.flush();
       }
-      catch (IOException ioe)
+      catch (final IOException ioe)
       {
         // Something is seriously wrong
         throw new RuntimeException(ioe);
       }
+      return true;
     }
 
 
@@ -168,9 +175,10 @@
     /**
      * {@inheritDoc}
      */
-    public void handleReference(SearchResultReference reference)
+    public boolean handleReference(final SearchResultReference reference)
     {
       println(LocalizableMessage.raw(reference.toString()));
+      return true;
     }
   }
 
@@ -183,9 +191,9 @@
    *          The command-line arguments provided to this program.
    */
 
-  public static void main(String[] args)
+  public static void main(final String[] args)
   {
-    int retCode = mainSearch(args, false, System.in, System.out,
+    final int retCode = mainSearch(args, false, System.in, System.out,
         System.err);
     System.exit(filterExitCode(retCode));
   }
@@ -193,15 +201,15 @@
 
 
   /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the ldapsearch tool.
+   * Parses the provided command-line arguments and uses that information to run
+   * the ldapsearch tool.
    *
    * @param args
    *          The command-line arguments provided to this program.
    * @return The error code.
    */
 
-  static int mainSearch(String[] args)
+  static int mainSearch(final String[] args)
   {
     return mainSearch(args, true, System.in, System.out, System.err);
   }
@@ -209,54 +217,29 @@
 
 
   /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the ldapsearch tool.
-   *
-   * @param args
-   *          The command-line arguments provided to this program.
-   * @param inStream
-   *          The input stream to use for standard input, or
-   *          <CODE>null</CODE> if standard input is not needed.
-   * @param outStream
-   *          The output stream to use for standard output, or
-   *          <CODE>null</CODE> if standard output is not needed.
-   * @param errStream
-   *          The output stream to use for standard error, or
-   *          <CODE>null</CODE> if standard error is not needed.
-   * @return The error code.
-   */
-  static int mainSearch(String[] args, InputStream inStream,
-      OutputStream outStream, OutputStream errStream)
-  {
-    return mainSearch(args, true, inStream, outStream, errStream);
-  }
-
-
-
-  /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the ldapsearch tool.
+   * Parses the provided command-line arguments and uses that information to run
+   * the ldapsearch tool.
    *
    * @param args
    *          The command-line arguments provided to this program.
    * @param returnMatchingEntries
-   *          whether when the option --countEntries is specified, the
-   *          number of matching entries should be returned or not.
+   *          whether when the option --countEntries is specified, the number of
+   *          matching entries should be returned or not.
    * @param inStream
-   *          The input stream to use for standard input, or
-   *          <CODE>null</CODE> if standard input is not needed.
+   *          The input stream to use for standard input, or <CODE>null</CODE>
+   *          if standard input is not needed.
    * @param outStream
-   *          The output stream to use for standard output, or
-   *          <CODE>null</CODE> if standard output is not needed.
+   *          The output stream to use for standard output, or <CODE>null</CODE>
+   *          if standard output is not needed.
    * @param errStream
-   *          The output stream to use for standard error, or
-   *          <CODE>null</CODE> if standard error is not needed.
+   *          The output stream to use for standard error, or <CODE>null</CODE>
+   *          if standard error is not needed.
    * @return The error code.
    */
 
-  static int mainSearch(String[] args,
-      boolean returnMatchingEntries, InputStream inStream,
-      OutputStream outStream, OutputStream errStream)
+  static int mainSearch(final String[] args,
+      final boolean returnMatchingEntries, final InputStream inStream,
+      final OutputStream outStream, final OutputStream errStream)
   {
     return new LDAPSearch(inStream, outStream, errStream).run(args,
         returnMatchingEntries);
@@ -264,7 +247,39 @@
 
 
 
-  private LDAPSearch(InputStream in, OutputStream out, OutputStream err)
+  /**
+   * Parses the provided command-line arguments and uses that information to run
+   * the ldapsearch tool.
+   *
+   * @param args
+   *          The command-line arguments provided to this program.
+   * @param inStream
+   *          The input stream to use for standard input, or <CODE>null</CODE>
+   *          if standard input is not needed.
+   * @param outStream
+   *          The output stream to use for standard output, or <CODE>null</CODE>
+   *          if standard output is not needed.
+   * @param errStream
+   *          The output stream to use for standard error, or <CODE>null</CODE>
+   *          if standard error is not needed.
+   * @return The error code.
+   */
+  static int mainSearch(final String[] args, final InputStream inStream,
+      final OutputStream outStream, final OutputStream errStream)
+  {
+    return mainSearch(args, true, inStream, outStream, errStream);
+  }
+
+
+
+  private BooleanArgument verbose;
+
+  private EntryWriter ldifWriter;
+
+
+
+  private LDAPSearch(final InputStream in, final OutputStream out,
+      final OutputStream err)
   {
     super(in, out, err);
 
@@ -272,12 +287,97 @@
 
 
 
-  private int run(String[] args, boolean returnMatchingEntries)
+  /**
+   * Indicates whether or not the user has requested advanced mode.
+   *
+   * @return Returns <code>true</code> if the user has requested advanced mode.
+   */
+  @Override
+  public boolean isAdvancedMode()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested interactive behavior.
+   *
+   * @return Returns <code>true</code> if the user has requested interactive
+   *         behavior.
+   */
+  @Override
+  public boolean isInteractive()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * Indicates whether or not this console application is running in its
+   * menu-driven mode. This can be used to dictate whether output should go to
+   * the error stream or not. In addition, it may also dictate whether or not
+   * sub-menus should display a cancel option as well as a quit option.
+   *
+   * @return Returns <code>true</code> if this console application is running in
+   *         its menu-driven mode.
+   */
+  @Override
+  public boolean isMenuDrivenMode()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested quiet output.
+   *
+   * @return Returns <code>true</code> if the user has requested quiet output.
+   */
+  @Override
+  public boolean isQuiet()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested script-friendly output.
+   *
+   * @return Returns <code>true</code> if the user has requested script-friendly
+   *         output.
+   */
+  @Override
+  public boolean isScriptFriendly()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested verbose output.
+   *
+   * @return Returns <code>true</code> if the user has requested verbose output.
+   */
+  @Override
+  public boolean isVerbose()
+  {
+    return verbose.isPresent();
+  }
+
+
+
+  private int run(final String[] args, final boolean returnMatchingEntries)
   {
     // Create the command-line argument parser for use with this
     // program.
-    LocalizableMessage toolDescription = INFO_LDAPSEARCH_TOOL_DESCRIPTION.get();
-    ArgumentParser argParser = new ArgumentParser(LDAPSearch.class
+    final LocalizableMessage toolDescription = INFO_LDAPSEARCH_TOOL_DESCRIPTION
+        .get();
+    final ArgumentParser argParser = new ArgumentParser(LDAPSearch.class
         .getName(), toolDescription, false, true, 0, 0,
         "[filter] [attributes ...]");
     ArgumentParserConnectionFactory connectionFactory;
@@ -305,32 +405,30 @@
     IntegerArgument sizeLimit;
     try
     {
-      connectionFactory = new ArgumentParserConnectionFactory(
-          argParser, this);
-      StringArgument propertiesFileArgument = new StringArgument(
-          "propertiesFilePath", null, OPTION_LONG_PROP_FILE_PATH,
-          false, false, true, INFO_PROP_FILE_PATH_PLACEHOLDER.get(),
-          null, null, INFO_DESCRIPTION_PROP_FILE_PATH.get());
+      connectionFactory = new ArgumentParserConnectionFactory(argParser, this);
+      final StringArgument propertiesFileArgument = new StringArgument(
+          "propertiesFilePath", null, OPTION_LONG_PROP_FILE_PATH, false, false,
+          true, INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_PROP_FILE_PATH.get());
       argParser.addArgument(propertiesFileArgument);
       argParser.setFilePropertiesArgument(propertiesFileArgument);
 
-      BooleanArgument noPropertiesFileArgument = new BooleanArgument(
+      final BooleanArgument noPropertiesFileArgument = new BooleanArgument(
           "noPropertiesFileArgument", null, OPTION_LONG_NO_PROP_FILE,
           INFO_DESCRIPTION_NO_PROP_FILE.get());
       argParser.addArgument(noPropertiesFileArgument);
       argParser.setNoPropertiesFileArgument(noPropertiesFileArgument);
 
       baseDN = new StringArgument("baseDN", OPTION_SHORT_BASEDN,
-          OPTION_LONG_BASEDN, true, false, true,
-          INFO_BASEDN_PLACEHOLDER.get(), null, null,
-          INFO_SEARCH_DESCRIPTION_BASEDN.get());
+          OPTION_LONG_BASEDN, true, false, true, INFO_BASEDN_PLACEHOLDER.get(),
+          null, null, INFO_SEARCH_DESCRIPTION_BASEDN.get());
       baseDN.setPropertyName(OPTION_LONG_BASEDN);
       argParser.addArgument(baseDN);
 
-      searchScope = new MultiChoiceArgument<SearchScope>("searchScope",
-          's', "searchScope", false, true,
-          INFO_SEARCH_SCOPE_PLACEHOLDER.get(), SearchScope.values(),
-          false, INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE.get());
+      searchScope = new MultiChoiceArgument<SearchScope>("searchScope", 's',
+          "searchScope", false, true, INFO_SEARCH_SCOPE_PLACEHOLDER.get(),
+          SearchScope.values(), false, INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE
+              .get());
       searchScope.setPropertyName("searchScope");
       searchScope.setDefaultValue(SearchScope.WHOLE_SUBTREE);
       argParser.addArgument(searchScope);
@@ -343,23 +441,22 @@
       argParser.addArgument(filename);
 
       proxyAuthzID = new StringArgument("proxy_authzid",
-          OPTION_SHORT_PROXYAUTHID, OPTION_LONG_PROXYAUTHID, false,
-          false, true, INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
+          OPTION_SHORT_PROXYAUTHID, OPTION_LONG_PROXYAUTHID, false, false,
+          true, INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
           INFO_DESCRIPTION_PROXY_AUTHZID.get());
       proxyAuthzID.setPropertyName(OPTION_LONG_PROXYAUTHID);
       argParser.addArgument(proxyAuthzID);
 
-      pSearchInfo = new StringArgument("psearchinfo", 'C',
-          "persistentSearch", false, false, true,
-          INFO_PSEARCH_PLACEHOLDER.get(), null, null,
+      pSearchInfo = new StringArgument("psearchinfo", 'C', "persistentSearch",
+          false, false, true, INFO_PSEARCH_PLACEHOLDER.get(), null, null,
           INFO_DESCRIPTION_PSEARCH_INFO.get());
       pSearchInfo.setPropertyName("persistentSearch");
       argParser.addArgument(pSearchInfo);
 
       simplePageSize = new IntegerArgument("simplepagesize", null,
-          "simplePageSize", false, false, true,
-          INFO_NUM_ENTRIES_PLACEHOLDER.get(), 1000, null, true, 1,
-          false, 0, INFO_DESCRIPTION_SIMPLE_PAGE_SIZE.get());
+          "simplePageSize", false, false, true, INFO_NUM_ENTRIES_PLACEHOLDER
+              .get(), 1000, null, true, 1, false, 0,
+          INFO_DESCRIPTION_SIMPLE_PAGE_SIZE.get());
       simplePageSize.setPropertyName("simplePageSize");
       argParser.addArgument(simplePageSize);
 
@@ -371,66 +468,61 @@
       argParser.addArgument(assertionFilter);
 
       matchedValuesFilter = new StringArgument("matchedvalues", null,
-          "matchedValuesFilter", false, true, true,
-          INFO_FILTER_PLACEHOLDER.get(), null, null,
-          INFO_DESCRIPTION_MATCHED_VALUES_FILTER.get());
+          "matchedValuesFilter", false, true, true, INFO_FILTER_PLACEHOLDER
+              .get(), null, null, INFO_DESCRIPTION_MATCHED_VALUES_FILTER.get());
       matchedValuesFilter.setPropertyName("matchedValuesFilter");
       argParser.addArgument(matchedValuesFilter);
 
-      sortOrder = new StringArgument("sortorder", 'S', "sortOrder",
-          false, false, true, INFO_SORT_ORDER_PLACEHOLDER.get(), null,
-          null, INFO_DESCRIPTION_SORT_ORDER.get());
+      sortOrder = new StringArgument("sortorder", 'S', "sortOrder", false,
+          false, true, INFO_SORT_ORDER_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_SORT_ORDER.get());
       sortOrder.setPropertyName("sortOrder");
       argParser.addArgument(sortOrder);
 
       vlvDescriptor = new StringArgument("vlvdescriptor", 'G',
-          "virtualListView", false, false, true, INFO_VLV_PLACEHOLDER
-              .get(), null, null, INFO_DESCRIPTION_VLV.get());
+          "virtualListView", false, false, true, INFO_VLV_PLACEHOLDER.get(),
+          null, null, INFO_DESCRIPTION_VLV.get());
       vlvDescriptor.setPropertyName("virtualListView");
       argParser.addArgument(vlvDescriptor);
 
-      controlStr = new StringArgument("control", 'J', "control", false,
-          true, true, INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
+      controlStr = new StringArgument("control", 'J', "control", false, true,
+          true, INFO_LDAP_CONTROL_PLACEHOLDER.get(), null, null,
           INFO_DESCRIPTION_CONTROLS.get());
       controlStr.setPropertyName("control");
       argParser.addArgument(controlStr);
 
       effectiveRightsUser = new StringArgument("effectiveRightsUser",
-          OPTION_SHORT_EFFECTIVERIGHTSUSER,
-          OPTION_LONG_EFFECTIVERIGHTSUSER, false, false, true,
-          INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
+          OPTION_SHORT_EFFECTIVERIGHTSUSER, OPTION_LONG_EFFECTIVERIGHTSUSER,
+          false, false, true, INFO_PROXYAUTHID_PLACEHOLDER.get(), null, null,
           INFO_DESCRIPTION_EFFECTIVERIGHTS_USER.get());
-      effectiveRightsUser
-          .setPropertyName(OPTION_LONG_EFFECTIVERIGHTSUSER);
+      effectiveRightsUser.setPropertyName(OPTION_LONG_EFFECTIVERIGHTSUSER);
       argParser.addArgument(effectiveRightsUser);
 
       effectiveRightsAttrs = new StringArgument("effectiveRightsAttrs",
-          OPTION_SHORT_EFFECTIVERIGHTSATTR,
-          OPTION_LONG_EFFECTIVERIGHTSATTR, false, true, true,
-          INFO_ATTRIBUTE_PLACEHOLDER.get(), null, null,
+          OPTION_SHORT_EFFECTIVERIGHTSATTR, OPTION_LONG_EFFECTIVERIGHTSATTR,
+          false, true, true, INFO_ATTRIBUTE_PLACEHOLDER.get(), null, null,
           INFO_DESCRIPTION_EFFECTIVERIGHTS_ATTR.get());
-      effectiveRightsAttrs
-          .setPropertyName(OPTION_LONG_EFFECTIVERIGHTSATTR);
+      effectiveRightsAttrs.setPropertyName(OPTION_LONG_EFFECTIVERIGHTSATTR);
       argParser.addArgument(effectiveRightsAttrs);
 
-      version = new IntegerArgument("version",
-          OPTION_SHORT_PROTOCOL_VERSION, OPTION_LONG_PROTOCOL_VERSION,
-          false, false, true, INFO_PROTOCOL_VERSION_PLACEHOLDER.get(),
-          3, null, INFO_DESCRIPTION_VERSION.get());
+      version = new IntegerArgument("version", OPTION_SHORT_PROTOCOL_VERSION,
+          OPTION_LONG_PROTOCOL_VERSION, false, false, true,
+          INFO_PROTOCOL_VERSION_PLACEHOLDER.get(), 3, null,
+          INFO_DESCRIPTION_VERSION.get());
       version.setPropertyName(OPTION_LONG_PROTOCOL_VERSION);
       argParser.addArgument(version);
 
-      StringArgument encodingStr = new StringArgument("encoding", 'i',
-          "encoding", false, false, true, INFO_ENCODING_PLACEHOLDER
-              .get(), null, null, INFO_DESCRIPTION_ENCODING.get());
+      final StringArgument encodingStr = new StringArgument("encoding", 'i',
+          "encoding", false, false, true, INFO_ENCODING_PLACEHOLDER.get(),
+          null, null, INFO_DESCRIPTION_ENCODING.get());
       encodingStr.setPropertyName("encoding");
       argParser.addArgument(encodingStr);
 
       dereferencePolicy = new MultiChoiceArgument<DereferenceAliasesPolicy>(
           "derefpolicy", 'a', "dereferencePolicy", false, true,
-          INFO_DEREFERENCE_POLICE_PLACEHOLDER.get(),
-          DereferenceAliasesPolicy.values(), false,
-          INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY.get());
+          INFO_DEREFERENCE_POLICE_PLACEHOLDER.get(), DereferenceAliasesPolicy
+              .values(), false, INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY
+              .get());
       dereferencePolicy.setPropertyName("dereferencePolicy");
       dereferencePolicy.setDefaultValue(DereferenceAliasesPolicy.NEVER);
       argParser.addArgument(dereferencePolicy);
@@ -440,15 +532,15 @@
       typesOnly.setPropertyName("typesOnly");
       argParser.addArgument(typesOnly);
 
-      sizeLimit = new IntegerArgument("sizeLimit", 'z', "sizeLimit",
-          false, false, true, INFO_SIZE_LIMIT_PLACEHOLDER.get(), 0,
-          null, INFO_SEARCH_DESCRIPTION_SIZE_LIMIT.get());
+      sizeLimit = new IntegerArgument("sizeLimit", 'z', "sizeLimit", false,
+          false, true, INFO_SIZE_LIMIT_PLACEHOLDER.get(), 0, null,
+          INFO_SEARCH_DESCRIPTION_SIZE_LIMIT.get());
       sizeLimit.setPropertyName("sizeLimit");
       argParser.addArgument(sizeLimit);
 
-      timeLimit = new IntegerArgument("timeLimit", 'l', "timeLimit",
-          false, false, true, INFO_TIME_LIMIT_PLACEHOLDER.get(), 0,
-          null, INFO_SEARCH_DESCRIPTION_TIME_LIMIT.get());
+      timeLimit = new IntegerArgument("timeLimit", 'l', "timeLimit", false,
+          false, true, INFO_TIME_LIMIT_PLACEHOLDER.get(), 0, null,
+          INFO_SEARCH_DESCRIPTION_TIME_LIMIT.get());
       timeLimit.setPropertyName("timeLimit");
       argParser.addArgument(timeLimit);
 
@@ -457,12 +549,12 @@
       dontWrap.setPropertyName("dontWrap");
       argParser.addArgument(dontWrap);
 
-      countEntries = new BooleanArgument("countentries", null,
-          "countEntries", INFO_DESCRIPTION_COUNT_ENTRIES.get());
+      countEntries = new BooleanArgument("countentries", null, "countEntries",
+          INFO_DESCRIPTION_COUNT_ENTRIES.get());
       countEntries.setPropertyName("countEntries");
       argParser.addArgument(countEntries);
 
-      BooleanArgument continueOnError = new BooleanArgument(
+      final BooleanArgument continueOnError = new BooleanArgument(
           "continueOnError", 'c', "continueOnError",
           INFO_DESCRIPTION_CONTINUE_ON_ERROR.get());
       continueOnError.setPropertyName("continueOnError");
@@ -478,15 +570,15 @@
       verbose.setPropertyName("verbose");
       argParser.addArgument(verbose);
 
-      BooleanArgument showUsage = new BooleanArgument("showUsage",
-          OPTION_SHORT_HELP, OPTION_LONG_HELP,
-          INFO_DESCRIPTION_SHOWUSAGE.get());
+      final BooleanArgument showUsage = new BooleanArgument("showUsage",
+          OPTION_SHORT_HELP, OPTION_LONG_HELP, INFO_DESCRIPTION_SHOWUSAGE.get());
       argParser.addArgument(showUsage);
       argParser.setUsageArgument(showUsage, getOutputStream());
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
+      final LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae
+          .getMessage());
       println(message);
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
@@ -497,9 +589,10 @@
       argParser.parseArguments(args);
       connectionFactory.validate();
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
+      final LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae
+          .getMessage());
       println(message);
       println(argParser.getUsageMessage());
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -512,9 +605,9 @@
       return 0;
     }
 
-    List<Filter> filters = new LinkedList<Filter>();
-    List<String> attributes = new LinkedList<String>();
-    ArrayList<String> filterAndAttributeStrings = argParser
+    final List<Filter> filters = new LinkedList<Filter>();
+    final List<String> attributes = new LinkedList<String>();
+    final ArrayList<String> filterAndAttributeStrings = argParser
         .getTrailingArguments();
     if (filterAndAttributeStrings.size() > 0)
     {
@@ -525,20 +618,20 @@
       // considered the filter, the other as attributes.
       if (!filename.isPresent())
       {
-        String filterString = filterAndAttributeStrings.remove(0);
+        final String filterString = filterAndAttributeStrings.remove(0);
 
         try
         {
           filters.add(Filter.valueOf(filterString));
         }
-        catch (LocalizedIllegalArgumentException e)
+        catch (final LocalizedIllegalArgumentException e)
         {
           println(e.getMessageObject());
           return ResultCode.CLIENT_SIDE_FILTER_ERROR.intValue();
         }
       }
       // The rest are attributes
-      for (String s : filterAndAttributeStrings)
+      for (final String s : filterAndAttributeStrings)
       {
         attributes.add(s);
       }
@@ -560,16 +653,16 @@
             // ignore empty lines.
             continue;
           }
-          Filter ldapFilter = Filter.valueOf(line);
+          final Filter ldapFilter = Filter.valueOf(line);
           filters.add(ldapFilter);
         }
       }
-      catch (LocalizedIllegalArgumentException e)
+      catch (final LocalizedIllegalArgumentException e)
       {
         println(e.getMessageObject());
         return ResultCode.CLIENT_SIDE_FILTER_ERROR.intValue();
       }
-      catch (IOException e)
+      catch (final IOException e)
       {
         println(LocalizableMessage.raw(e.toString()));
         return ResultCode.CLIENT_SIDE_FILTER_ERROR.intValue();
@@ -582,7 +675,7 @@
           {
             in.close();
           }
-          catch (IOException ioe)
+          catch (final IOException ioe)
           {
           }
         }
@@ -601,7 +694,7 @@
     {
       scope = searchScope.getTypedValue();
     }
-    catch (ArgumentException ex1)
+    catch (final ArgumentException ex1)
     {
       println(ex1.getMessageObject());
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -610,11 +703,10 @@
     SearchRequest search;
     try
     {
-      search = Requests.newSearchRequest(DN.valueOf(baseDN.getValue()), scope, filters.get(0),
-          attributes.toArray(new String[attributes
-              .size()]));
+      search = Requests.newSearchRequest(DN.valueOf(baseDN.getValue()), scope,
+          filters.get(0), attributes.toArray(new String[attributes.size()]));
     }
-    catch (LocalizedIllegalArgumentException e)
+    catch (final LocalizedIllegalArgumentException e)
     {
       println(e.getMessageObject());
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -623,7 +715,7 @@
     // Read the LDAP version number.
     try
     {
-      int versionNumber = version.getIntValue();
+      final int versionNumber = version.getIntValue();
       if (versionNumber != 2 && versionNumber != 3)
       {
         println(ERR_DESCRIPTION_INVALID_VERSION.get(String
@@ -631,10 +723,10 @@
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      println(ERR_DESCRIPTION_INVALID_VERSION.get(String
-          .valueOf(version.getValue())));
+      println(ERR_DESCRIPTION_INVALID_VERSION.get(String.valueOf(version
+          .getValue())));
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
 
@@ -649,17 +741,16 @@
       search.setTimeLimit(timeLimit.getIntValue());
       search.setSizeLimit(sizeLimit.getIntValue());
     }
-    catch (ArgumentException ex1)
+    catch (final ArgumentException ex1)
     {
       println(ex1.getMessageObject());
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
     try
     {
-      search.setDereferenceAliasesPolicy(dereferencePolicy
-          .getTypedValue());
+      search.setDereferenceAliasesPolicy(dereferencePolicy.getTypedValue());
     }
-    catch (ArgumentException ex1)
+    catch (final ArgumentException ex1)
     {
       println(ex1.getMessageObject());
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -667,16 +758,16 @@
 
     if (controlStr.isPresent())
     {
-      for (String ctrlString : controlStr.getValues())
+      for (final String ctrlString : controlStr.getValues())
       {
         try
         {
-          Control ctrl = Utils.getControl(ctrlString);
+          final Control ctrl = Utils.getControl(ctrlString);
           search.addControl(ctrl);
         }
-        catch (DecodeException de)
+        catch (final DecodeException de)
         {
-          LocalizableMessage message = ERR_TOOL_INVALID_CONTROL_STRING
+          final LocalizableMessage message = ERR_TOOL_INVALID_CONTROL_STRING
               .get(ctrlString);
           println(message);
           ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -686,60 +777,60 @@
 
     if (effectiveRightsUser.isPresent())
     {
-      String authzID = effectiveRightsUser.getValue();
+      final String authzID = effectiveRightsUser.getValue();
       if (!authzID.startsWith("dn:"))
       {
-        LocalizableMessage message = ERR_EFFECTIVERIGHTS_INVALID_AUTHZID
+        final LocalizableMessage message = ERR_EFFECTIVERIGHTS_INVALID_AUTHZID
             .get(authzID);
         println(message);
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
-      Control effectiveRightsControl = new GetEffectiveRightsRequestControl(
-          false, authzID.substring(3), effectiveRightsAttrs.getValues()
-              .toArray(
+      final Control effectiveRightsControl = GetEffectiveRightsRequestControl
+          .newControl(false, authzID.substring(3), effectiveRightsAttrs
+              .getValues().toArray(
                   new String[effectiveRightsAttrs.getValues().size()]));
       search.addControl(effectiveRightsControl);
     }
 
     if (proxyAuthzID.isPresent())
     {
-      Control proxyControl = new ProxiedAuthV2Control(proxyAuthzID
-          .getValue());
+      final Control proxyControl = ProxiedAuthV2RequestControl
+          .newControl(proxyAuthzID.getValue());
       search.addControl(proxyControl);
     }
 
     if (pSearchInfo.isPresent())
     {
-      String infoString = StaticUtils.toLowerCase(pSearchInfo
-          .getValue().trim());
+      final String infoString = StaticUtils.toLowerCase(pSearchInfo.getValue()
+          .trim());
       boolean changesOnly = true;
       boolean returnECs = true;
 
-      StringTokenizer tokenizer = new StringTokenizer(infoString, ":");
+      final StringTokenizer tokenizer = new StringTokenizer(infoString, ":");
 
       if (!tokenizer.hasMoreTokens())
       {
-        LocalizableMessage message = ERR_PSEARCH_MISSING_DESCRIPTOR.get();
+        final LocalizableMessage message = ERR_PSEARCH_MISSING_DESCRIPTOR.get();
         println(message);
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
       else
       {
-        String token = tokenizer.nextToken();
+        final String token = tokenizer.nextToken();
         if (!token.equals("ps"))
         {
-          LocalizableMessage message = ERR_PSEARCH_DOESNT_START_WITH_PS.get(String
-              .valueOf(infoString));
+          final LocalizableMessage message = ERR_PSEARCH_DOESNT_START_WITH_PS
+              .get(String.valueOf(infoString));
           println(message);
           return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
       }
 
-      ArrayList<PersistentSearchChangeType> ct = new ArrayList<PersistentSearchChangeType>(
+      final ArrayList<PersistentSearchChangeType> ct = new ArrayList<PersistentSearchChangeType>(
           4);
       if (tokenizer.hasMoreTokens())
       {
-        StringTokenizer st = new StringTokenizer(tokenizer.nextToken(),
+        final StringTokenizer st = new StringTokenizer(tokenizer.nextToken(),
             ", ");
         if (!st.hasMoreTokens())
         {
@@ -749,9 +840,10 @@
           ct.add(PersistentSearchChangeType.MODIFY_DN);
         }
         else
+        {
           do
           {
-            String token = st.nextToken();
+            final String token = st.nextToken();
             if (token.equals("add"))
             {
               ct.add(PersistentSearchChangeType.ADD);
@@ -778,19 +870,20 @@
             }
             else
             {
-              LocalizableMessage message = ERR_PSEARCH_INVALID_CHANGE_TYPE
+              final LocalizableMessage message = ERR_PSEARCH_INVALID_CHANGE_TYPE
                   .get(String.valueOf(token));
               println(message);
               return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
             }
-          } while (st.hasMoreTokens());
+          }
+          while (st.hasMoreTokens());
+        }
       }
 
       if (tokenizer.hasMoreTokens())
       {
-        String token = tokenizer.nextToken();
-        if (token.equals("1") || token.equals("true")
-            || token.equals("yes"))
+        final String token = tokenizer.nextToken();
+        if (token.equals("1") || token.equals("true") || token.equals("yes"))
         {
           changesOnly = true;
         }
@@ -801,8 +894,8 @@
         }
         else
         {
-          LocalizableMessage message = ERR_PSEARCH_INVALID_CHANGESONLY.get(String
-              .valueOf(token));
+          final LocalizableMessage message = ERR_PSEARCH_INVALID_CHANGESONLY
+              .get(String.valueOf(token));
           println(message);
           return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
@@ -810,9 +903,8 @@
 
       if (tokenizer.hasMoreTokens())
       {
-        String token = tokenizer.nextToken();
-        if (token.equals("1") || token.equals("true")
-            || token.equals("yes"))
+        final String token = tokenizer.nextToken();
+        if (token.equals("1") || token.equals("true") || token.equals("yes"))
         {
           returnECs = true;
         }
@@ -823,22 +915,22 @@
         }
         else
         {
-          LocalizableMessage message = ERR_PSEARCH_INVALID_RETURN_ECS.get(String
-              .valueOf(token));
+          final LocalizableMessage message = ERR_PSEARCH_INVALID_RETURN_ECS
+              .get(String.valueOf(token));
           println(message);
           return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
       }
 
-      PersistentSearchControl psearchControl = new PersistentSearchControl(
-          changesOnly, returnECs, ct
+      final PersistentSearchRequestControl psearchControl = PersistentSearchRequestControl
+          .newControl(true, changesOnly, returnECs, ct
               .toArray(new PersistentSearchChangeType[ct.size()]));
       search.addControl(psearchControl);
     }
 
     if (assertionFilter.isPresent())
     {
-      String filterString = assertionFilter.getValue();
+      final String filterString = assertionFilter.getValue();
       Filter filter;
       try
       {
@@ -846,13 +938,14 @@
 
         // FIXME -- Change this to the correct OID when the official one
         // is assigned.
-        Control assertionControl = new AssertionControl(true, filter);
+        final Control assertionControl = AssertionRequestControl.newControl(
+            true, filter);
         search.addControl(assertionControl);
       }
-      catch (LocalizedIllegalArgumentException le)
+      catch (final LocalizedIllegalArgumentException le)
       {
-        LocalizableMessage message = ERR_LDAP_ASSERTION_INVALID_FILTER.get(le
-            .getMessage());
+        final LocalizableMessage message = ERR_LDAP_ASSERTION_INVALID_FILTER
+            .get(le.getMessage());
         println(message);
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
@@ -860,27 +953,27 @@
 
     if (matchedValuesFilter.isPresent())
     {
-      LinkedList<String> mvFilterStrings = matchedValuesFilter
+      final LinkedList<String> mvFilterStrings = matchedValuesFilter
           .getValues();
-      List<Filter> mvFilters = new ArrayList<Filter>();
-      for (String s : mvFilterStrings)
+      final List<Filter> mvFilters = new ArrayList<Filter>();
+      for (final String s : mvFilterStrings)
       {
         try
         {
-          Filter f = Filter.valueOf(s);
+          final Filter f = Filter.valueOf(s);
           mvFilters.add(f);
         }
-        catch (LocalizedIllegalArgumentException le)
+        catch (final LocalizedIllegalArgumentException le)
         {
-          LocalizableMessage message = ERR_LDAP_MATCHEDVALUES_INVALID_FILTER
+          final LocalizableMessage message = ERR_LDAP_MATCHEDVALUES_INVALID_FILTER
               .get(le.getMessage());
           println(message);
           return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
       }
 
-      MatchedValuesControl mvc = new MatchedValuesControl(true,
-          mvFilters.toArray(new Filter[mvFilters.size()]));
+      final MatchedValuesRequestControl mvc = MatchedValuesRequestControl
+          .newControl(true, mvFilters);
       search.addControl(mvc);
     }
 
@@ -888,13 +981,13 @@
     {
       try
       {
-        search.addControl(new ServerSideSortControl.Request(false,
+        search.addControl(ServerSideSortRequestControl.newControl(false,
             sortOrder.getValue()));
       }
-      catch (DecodeException le)
+      catch (final LocalizedIllegalArgumentException le)
       {
-        LocalizableMessage message = ERR_LDAP_SORTCONTROL_INVALID_ORDER.get(le
-            .getMessageObject());
+        final LocalizableMessage message = ERR_LDAP_SORTCONTROL_INVALID_ORDER
+            .get(le.getMessageObject());
         println(message);
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
@@ -904,30 +997,31 @@
     {
       if (!sortOrder.isPresent())
       {
-        LocalizableMessage message = ERR_LDAPSEARCH_VLV_REQUIRES_SORT.get(
-            vlvDescriptor.getLongIdentifier(), sortOrder
+        final LocalizableMessage message = ERR_LDAPSEARCH_VLV_REQUIRES_SORT
+            .get(vlvDescriptor.getLongIdentifier(), sortOrder
                 .getLongIdentifier());
         println(message);
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
 
-      StringTokenizer tokenizer = new StringTokenizer(vlvDescriptor
+      final StringTokenizer tokenizer = new StringTokenizer(vlvDescriptor
           .getValue(), ":");
-      int numTokens = tokenizer.countTokens();
+      final int numTokens = tokenizer.countTokens();
       if (numTokens == 3)
       {
         try
         {
-          int beforeCount = Integer.parseInt(tokenizer.nextToken());
-          int afterCount = Integer.parseInt(tokenizer.nextToken());
-          ByteString assertionValue = ByteString.valueOf(tokenizer
+          final int beforeCount = Integer.parseInt(tokenizer.nextToken());
+          final int afterCount = Integer.parseInt(tokenizer.nextToken());
+          final ByteString assertionValue = ByteString.valueOf(tokenizer
               .nextToken());
-          search.addControl(new VLVControl.Request(beforeCount,
-              afterCount, assertionValue));
+          search.addControl(VirtualListViewRequestControl.newAssertionControl(
+              true, assertionValue, beforeCount, afterCount, null));
         }
-        catch (Exception e)
+        catch (final Exception e)
         {
-          LocalizableMessage message = ERR_LDAPSEARCH_VLV_INVALID_DESCRIPTOR.get();
+          final LocalizableMessage message = ERR_LDAPSEARCH_VLV_INVALID_DESCRIPTOR
+              .get();
           println(message);
           return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
@@ -936,23 +1030,25 @@
       {
         try
         {
-          int beforeCount = Integer.parseInt(tokenizer.nextToken());
-          int afterCount = Integer.parseInt(tokenizer.nextToken());
-          int offset = Integer.parseInt(tokenizer.nextToken());
-          int contentCount = Integer.parseInt(tokenizer.nextToken());
-          search.addControl(new VLVControl.Request(beforeCount,
-              afterCount, offset, contentCount));
+          final int beforeCount = Integer.parseInt(tokenizer.nextToken());
+          final int afterCount = Integer.parseInt(tokenizer.nextToken());
+          final int offset = Integer.parseInt(tokenizer.nextToken());
+          final int contentCount = Integer.parseInt(tokenizer.nextToken());
+          search.addControl(VirtualListViewRequestControl.newOffsetControl(
+              true, offset, contentCount, beforeCount, afterCount, null));
         }
-        catch (Exception e)
+        catch (final Exception e)
         {
-          LocalizableMessage message = ERR_LDAPSEARCH_VLV_INVALID_DESCRIPTOR.get();
+          final LocalizableMessage message = ERR_LDAPSEARCH_VLV_INVALID_DESCRIPTOR
+              .get();
           println(message);
           return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
         }
       }
       else
       {
-        LocalizableMessage message = ERR_LDAPSEARCH_VLV_INVALID_DESCRIPTOR.get();
+        final LocalizableMessage message = ERR_LDAPSEARCH_VLV_INVALID_DESCRIPTOR
+            .get();
         println(message);
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
@@ -963,7 +1059,7 @@
     {
       if (filters.size() > 1)
       {
-        LocalizableMessage message = ERR_PAGED_RESULTS_REQUIRES_SINGLE_FILTER
+        final LocalizableMessage message = ERR_PAGED_RESULTS_REQUIRES_SINGLE_FILTER
             .get();
         println(message);
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -972,20 +1068,20 @@
       try
       {
         pageSize = simplePageSize.getIntValue();
-        search.addControl(new PagedResultsControl(pageSize, ByteString
-            .empty()));
+        search.addControl(SimplePagedResultsControl.newControl(true, pageSize,
+            ByteString.empty()));
       }
-      catch (ArgumentException ae)
+      catch (final ArgumentException ae)
       {
-        LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
+        final LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae
+            .getMessage());
         println(message);
         return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
       }
     }
     /*
-     * if(connectionOptions.useSASLExternal()) {
-     * if(!connectionOptions.useSSL() &&
-     * !connectionOptions.useStartTLS()) { LocalizableMessage message =
+     * if(connectionOptions.useSASLExternal()) { if(!connectionOptions.useSSL()
+     * && !connectionOptions.useStartTLS()) { LocalizableMessage message =
      * ERR_TOOL_SASLEXTERNAL_NEEDS_SSL_OR_TLS.get();
      * err.println(wrapText(message, MAX_LINE_WIDTH)); return
      * CLIENT_SIDE_PARAM_ERROR; } if(keyStorePathValue == null) {
@@ -1004,12 +1100,9 @@
     if (noop.isPresent())
     {
       // We don't actually need to open a connection or perform the
-      // search,
-      // so we're done. We should return 0 to either mean that the
-      // processing
-      // was successful or that there were no matching entries, based on
-      // countEntries.isPresent() (but in either case the return value
-      // should
+      // search, so we're done. We should return 0 to either mean that the
+      // processing was successful or that there were no matching entries, based
+      // on countEntries.isPresent() (but in either case the return value should
       // be zero).
       return 0;
     }
@@ -1019,10 +1112,17 @@
     {
       connection = connectionFactory.getConnection();
     }
-    catch (ErrorResultException ere)
+    catch (final ErrorResultException ere)
     {
       return Utils.printErrorMessage(this, ere);
     }
+    catch (final InterruptedException e)
+    {
+      // This shouldn't happen because there are no other threads to
+      // interrupt this one.
+      println(LocalizableMessage.raw(e.getLocalizedMessage()));
+      return ResultCode.CLIENT_SIDE_USER_CANCELLED.intValue();
+    }
 
     Utils.printPasswordPolicyResults(this, connection);
 
@@ -1031,7 +1131,7 @@
       int filterIndex = 0;
       ldifWriter = new LDIFEntryWriter(getOutputStream())
           .setWrapColumn(wrapColumn);
-      LDAPSearchResultHandler resultHandler = new LDAPSearchResultHandler();
+      final LDAPSearchResultHandler resultHandler = new LDAPSearchResultHandler();
       while (true)
       {
         Result result;
@@ -1039,82 +1139,106 @@
         {
           result = connection.search(search, resultHandler);
         }
-        catch (InterruptedException e)
+        catch (final InterruptedException e)
         {
           // This shouldn't happen because there are no other threads to
           // interrupt this one.
-          result = Responses.newResult(
-              ResultCode.CLIENT_SIDE_USER_CANCELLED).setCause(e)
-              .setDiagnosticMessage(e.getLocalizedMessage());
+          result = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED)
+              .setCause(e).setDiagnosticMessage(e.getLocalizedMessage());
           throw ErrorResultException.wrap(result);
         }
 
-        Control control = result
-            .getControl(ServerSideSortControl.OID_SERVER_SIDE_SORT_RESPONSE_CONTROL);
-        if (control != null
-            && control instanceof ServerSideSortControl.Response)
+        try
         {
-          ServerSideSortControl.Response dc = (ServerSideSortControl.Response) control;
-          if (dc.getSortResult() != SortResult.SUCCESS)
+          final ServerSideSortResponseControl control = result.getControl(
+              ServerSideSortResponseControl.DECODER, new DecodeOptions());
+          if (control != null)
           {
-            LocalizableMessage msg = WARN_LDAPSEARCH_SORT_ERROR.get(dc
-                .getSortResult().toString());
-            println(msg);
-          }
-        }
-        control = result
-            .getControl(VLVControl.OID_VLV_RESPONSE_CONTROL);
-        if (control != null && control instanceof VLVControl.Response)
-        {
-          VLVControl.Response dc = (VLVControl.Response) control;
-          if (dc.getVLVResult() == VLVResult.SUCCESS)
-          {
-            LocalizableMessage msg = INFO_LDAPSEARCH_VLV_TARGET_OFFSET.get(dc
-                .getTargetPosition());
-            println(msg);
-
-            msg = INFO_LDAPSEARCH_VLV_CONTENT_COUNT.get(dc
-                .getContentCount());
-            println(msg);
-          }
-          else
-          {
-            LocalizableMessage msg = WARN_LDAPSEARCH_VLV_ERROR.get(dc
-                .getVLVResult().toString());
-            println(msg);
-          }
-        }
-
-        control = result
-            .getControl(PagedResultsControl.OID_PAGED_RESULTS_CONTROL);
-        if (control != null && control instanceof PagedResultsControl)
-        {
-          PagedResultsControl pagedControl = (PagedResultsControl) control;
-          if (pagedControl.getCookie().length() > 0)
-          {
-            if (!isQuiet())
+            if (control.getResult() != ResultCode.SUCCESS)
             {
-              pressReturnToContinue();
+              final LocalizableMessage msg = WARN_LDAPSEARCH_SORT_ERROR
+                  .get(control.getResult().toString());
+              println(msg);
             }
-            pagedControl = new PagedResultsControl(pageSize,
-                pagedControl.getCookie());
-            search
-                .removeControl(PagedResultsControl.OID_PAGED_RESULTS_CONTROL);
-            search.addControl(pagedControl);
-            continue;
           }
         }
+        catch (final DecodeException e)
+        {
+          println(ERR_DECODE_CONTROL_FAILURE.get(e.getLocalizedMessage()));
+        }
+
+        try
+        {
+          final VirtualListViewResponseControl control = result.getControl(
+              VirtualListViewResponseControl.DECODER, new DecodeOptions());
+          if (control != null)
+          {
+            if (control.getResult() == ResultCode.SUCCESS)
+            {
+              LocalizableMessage msg = INFO_LDAPSEARCH_VLV_TARGET_OFFSET
+                  .get(control.getTargetPosition());
+              println(msg);
+
+              msg = INFO_LDAPSEARCH_VLV_CONTENT_COUNT.get(control
+                  .getContentCount());
+              println(msg);
+            }
+            else
+            {
+              final LocalizableMessage msg = WARN_LDAPSEARCH_VLV_ERROR
+                  .get(control.getResult().toString());
+              println(msg);
+            }
+          }
+        }
+        catch (final DecodeException e)
+        {
+          println(ERR_DECODE_CONTROL_FAILURE.get(e.getLocalizedMessage()));
+        }
+
+        try
+        {
+          SimplePagedResultsControl control = result.getControl(
+              SimplePagedResultsControl.DECODER, new DecodeOptions());
+          if (control != null)
+          {
+            if (control.getCookie().length() > 0)
+            {
+              if (!isQuiet())
+              {
+                pressReturnToContinue();
+              }
+              final Iterator<Control> iterator = search.getControls()
+                  .iterator();
+              while (iterator.hasNext())
+              {
+                if (iterator.next().getOID().equals(
+                    SimplePagedResultsControl.OID))
+                {
+                  iterator.remove();
+                }
+              }
+              control = SimplePagedResultsControl.newControl(true, pageSize,
+                  control.getCookie());
+              search.addControl(control);
+              continue;
+            }
+          }
+        }
+        catch (final DecodeException e)
+        {
+          println(ERR_DECODE_CONTROL_FAILURE.get(e.getLocalizedMessage()));
+        }
 
         println();
-        println(ERR_TOOL_RESULT_CODE.get(result.getResultCode()
-            .intValue(), result.getResultCode().toString()));
+        println(ERR_TOOL_RESULT_CODE.get(result.getResultCode().intValue(),
+            result.getResultCode().toString()));
         if ((result.getDiagnosticMessage() != null)
             && (result.getDiagnosticMessage().length() > 0))
         {
           println(LocalizableMessage.raw(result.getDiagnosticMessage()));
         }
-        if (result.getMatchedDN() != null
-            && result.getMatchedDN().length() > 0)
+        if (result.getMatchedDN() != null && result.getMatchedDN().length() > 0)
         {
           println(ERR_TOOL_MATCHED_DN.get(result.getMatchedDN()));
         }
@@ -1131,13 +1255,13 @@
       }
       if (countEntries.isPresent() && !isQuiet())
       {
-        LocalizableMessage message = INFO_LDAPSEARCH_MATCHING_ENTRY_COUNT
+        final LocalizableMessage message = INFO_LDAPSEARCH_MATCHING_ENTRY_COUNT
             .get(resultHandler.entryCount);
         println(message);
         println();
       }
     }
-    catch (ErrorResultException ere)
+    catch (final ErrorResultException ere)
     {
       return Utils.printErrorMessage(this, ere);
     }
@@ -1148,88 +1272,4 @@
 
     return 0;
   }
-
-
-
-  /**
-   * Indicates whether or not the user has requested advanced mode.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         advanced mode.
-   */
-  public boolean isAdvancedMode()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested interactive
-   * behavior.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         interactive behavior.
-   */
-  public boolean isInteractive()
-  {
-    return true;
-  }
-
-
-
-  /**
-   * Indicates whether or not this console application is running in its
-   * menu-driven mode. This can be used to dictate whether output should
-   * go to the error stream or not. In addition, it may also dictate
-   * whether or not sub-menus should display a cancel option as well as
-   * a quit option.
-   *
-   * @return Returns <code>true</code> if this console application is
-   *         running in its menu-driven mode.
-   */
-  public boolean isMenuDrivenMode()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested quiet output.
-   *
-   * @return Returns <code>true</code> if the user has requested quiet
-   *         output.
-   */
-  public boolean isQuiet()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested script-friendly
-   * output.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         script-friendly output.
-   */
-  public boolean isScriptFriendly()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested verbose output.
-   *
-   * @return Returns <code>true</code> if the user has requested verbose
-   *         output.
-   */
-  public boolean isVerbose()
-  {
-    return verbose.isPresent();
-  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/ModRate.java b/sdk/src/com/sun/opends/sdk/tools/ModRate.java
index f1874db..2e689e8 100644
--- a/sdk/src/com/sun/opends/sdk/tools/ModRate.java
+++ b/sdk/src/com/sun/opends/sdk/tools/ModRate.java
@@ -31,7 +31,7 @@
 
 import static com.sun.opends.sdk.messages.Messages.*;
 import static com.sun.opends.sdk.tools.ToolConstants.*;
-import static com.sun.opends.sdk.tools.Utils.*;
+import static com.sun.opends.sdk.tools.Utils.filterExitCode;
 
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -43,232 +43,15 @@
 
 
 
-
 /**
- * A load generation tool that can be used to load a Directory Server
- * with Modify requests using one or more LDAP connections.
+ * A load generation tool that can be used to load a Directory Server with
+ * Modify requests using one or more LDAP connections.
  */
 public final class ModRate extends ConsoleApplication
 {
-  private BooleanArgument verbose;
-
-
-
-  /**
-   * The main method for ModRate tool.
-   *
-   * @param args
-   *          The command-line arguments provided to this program.
-   */
-
-  public static void main(String[] args)
+  private static final class ModifyPerformanceRunner extends PerformanceRunner
   {
-    int retCode = mainModRate(args, System.in, System.out, System.err);
-    System.exit(filterExitCode(retCode));
-  }
-
-
-
-  /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the modrate tool.
-   *
-   * @param args
-   *          The command-line arguments provided to this program.
-   * @return The error code.
-   */
-
-  static int mainModRate(String[] args)
-  {
-    return mainModRate(args, System.in, System.out, System.err);
-  }
-
-
-
-  /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the modrate tool.
-   *
-   * @param args
-   *          The command-line arguments provided to this program.
-   * @param inStream
-   *          The input stream to use for standard input, or
-   *          <CODE>null</CODE> if standard input is not needed.
-   * @param outStream
-   *          The output stream to use for standard output, or
-   *          <CODE>null</CODE> if standard output is not needed.
-   * @param errStream
-   *          The output stream to use for standard error, or
-   *          <CODE>null</CODE> if standard error is not needed.
-   * @return The error code.
-   */
-
-  static int mainModRate(String[] args, InputStream inStream,
-      OutputStream outStream, OutputStream errStream)
-
-  {
-    return new ModRate(inStream, outStream, errStream).run(args);
-  }
-
-
-
-  private ModRate(InputStream in, OutputStream out, OutputStream err)
-  {
-    super(in, out, err);
-
-  }
-
-
-
-  private int run(String[] args)
-  {
-    // Create the command-line argument parser for use with this
-    // program.
-    LocalizableMessage toolDescription =
-        LocalizableMessage.raw("This utility can be used to "
-            + "measure modify performance");
-    // TODO: correct usage
-    ArgumentParser argParser =
-        new ArgumentParser(ModRate.class.getName(), toolDescription,
-            false, true, 1, 0, "[modifyString ...]");
-    ArgumentParserConnectionFactory connectionFactory;
-    ModifyPerformanceRunner runner;
-
-    BooleanArgument showUsage;
-    StringArgument propertiesFileArgument;
-    BooleanArgument noPropertiesFileArgument;
-    StringArgument baseDN;
-
-    try
-    {
-      connectionFactory =
-          new ArgumentParserConnectionFactory(argParser, this);
-      runner = new ModifyPerformanceRunner(argParser, this);
-      propertiesFileArgument =
-          new StringArgument("propertiesFilePath", null,
-              OPTION_LONG_PROP_FILE_PATH, false, false, true,
-              INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null,
-              INFO_DESCRIPTION_PROP_FILE_PATH.get());
-      argParser.addArgument(propertiesFileArgument);
-      argParser.setFilePropertiesArgument(propertiesFileArgument);
-
-      noPropertiesFileArgument =
-          new BooleanArgument("noPropertiesFileArgument", null,
-              OPTION_LONG_NO_PROP_FILE, INFO_DESCRIPTION_NO_PROP_FILE
-                  .get());
-      argParser.addArgument(noPropertiesFileArgument);
-      argParser.setNoPropertiesFileArgument(noPropertiesFileArgument);
-
-      baseDN =
-          new StringArgument("baseDN", OPTION_SHORT_BASEDN,
-              OPTION_LONG_BASEDN, true, false, true,
-              INFO_BASEDN_PLACEHOLDER.get(), null, null,
-              INFO_SEARCH_DESCRIPTION_BASEDN.get());
-      baseDN.setPropertyName(OPTION_LONG_BASEDN);
-      argParser.addArgument(baseDN);
-
-      verbose =
-          new BooleanArgument("verbose", 'v', "verbose",
-              INFO_DESCRIPTION_VERBOSE.get());
-      verbose.setPropertyName("verbose");
-      argParser.addArgument(verbose);
-
-      showUsage =
-          new BooleanArgument("showUsage", OPTION_SHORT_HELP,
-              OPTION_LONG_HELP, INFO_DESCRIPTION_SHOWUSAGE.get());
-      argParser.addArgument(showUsage);
-      argParser.setUsageArgument(showUsage, getOutputStream());
-    }
-    catch (ArgumentException ae)
-    {
-      LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
-      println(message);
-      return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
-    }
-
-    // Parse the command-line arguments provided to this program.
-    try
-    {
-      argParser.parseArguments(args);
-      connectionFactory.validate();
-      runner.validate();
-    }
-    catch (ArgumentException ae)
-    {
-      LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
-      println(message);
-      println(argParser.getUsageMessage());
-      return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
-    }
-
-    // If we should just display usage or version information,
-    // then print it and exit.
-    if (argParser.usageOrVersionDisplayed())
-    {
-      return 0;
-    }
-
-    runner.modStrings =
-        argParser.getTrailingArguments().toArray(
-            new String[argParser.getTrailingArguments().size()]);
-    runner.baseDN = baseDN.getValue();
-
-    try
-    {
-
-      // Try it out to make sure the format string and data sources
-      // match.
-      Object[] data =
-          DataSource.generateData(runner.getDataSources(), null);
-      for (String modString : runner.modStrings)
-      {
-        String.format(modString, data);
-      }
-      String.format(runner.baseDN, data);
-    }
-    catch (Exception ex1)
-    {
-      println(LocalizableMessage.raw("Error formatting filter or base DN: "
-          + ex1.toString()));
-      return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
-    }
-
-    return runner.run(connectionFactory);
-  }
-
-
-
-  private class ModifyPerformanceRunner extends PerformanceRunner
-  {
-    private String baseDN;
-    private String[] modStrings;
-
-
-
-    private ModifyPerformanceRunner(ArgumentParser argParser,
-        ConsoleApplication app) throws ArgumentException
-    {
-      super(argParser, app);
-    }
-
-
-
-    WorkerThread<?> newWorkerThread(AsynchronousConnection connection,
-        ConnectionFactory connectionFactory)
-    {
-      return new ModifyWorkerThread(connection, connectionFactory);
-    }
-
-
-
-    StatsThread newStatsThread()
-    {
-      return new StatsThread(new String[0]);
-    }
-
-
-
-    private class ModifyWorkerThread extends
+    private final class ModifyWorkerThread extends
         WorkerThread<ResultHandler<Result>>
     {
       private ModifyRequest mr;
@@ -276,24 +59,26 @@
 
 
 
-      private ModifyWorkerThread(AsynchronousConnection connection,
-          ConnectionFactory connectionFactory)
+      private ModifyWorkerThread(final AsynchronousConnection connection,
+          final ConnectionFactory connectionFactory)
       {
         super(connection, connectionFactory);
       }
 
 
 
-      public ResultHandler<Result> getHandler(long startTime)
+      @Override
+      public ResultHandler<Result> getHandler(final long startTime)
       {
         return new UpdateStatsResultHandler<Result>(startTime);
       }
 
 
 
+      @Override
       public FutureResult<?> performOperation(
-          AsynchronousConnection connection,
-          ResultHandler<Result> handler, DataSource[] dataSources)
+          final AsynchronousConnection connection,
+          final ResultHandler<Result> handler, final DataSource[] dataSources)
       {
         if (dataSources != null)
         {
@@ -305,7 +90,7 @@
 
 
 
-      private ModifyRequest newModifyRequest(Object[] data)
+      private ModifyRequest newModifyRequest(final Object[] data)
       {
         String formattedString;
         int colonPos;
@@ -318,20 +103,20 @@
         {
           mr = Requests.newModifyRequest(String.format(baseDN, data));
         }
-        for (int i = 0; i < modStrings.length; i++)
+        for (final String modString : modStrings)
         {
           if (data == null)
           {
-            formattedString = modStrings[i];
+            formattedString = modString;
           }
           else
           {
-            formattedString = String.format(modStrings[i], data);
+            formattedString = String.format(modString, data);
           }
           colonPos = formattedString.indexOf(':');
           if (colonPos > 0)
           {
-            mr.addChange(ModificationType.REPLACE, formattedString
+            mr.addModification(ModificationType.REPLACE, formattedString
                 .substring(0, colonPos), formattedString
                 .substring(colonPos + 1));
           }
@@ -339,6 +124,108 @@
         return mr;
       }
     }
+
+
+
+    private String baseDN;
+
+    private String[] modStrings;
+
+
+
+    private ModifyPerformanceRunner(final ArgumentParser argParser,
+        final ConsoleApplication app) throws ArgumentException
+    {
+      super(argParser, app);
+    }
+
+
+
+    @Override
+    StatsThread newStatsThread()
+    {
+      return new StatsThread(new String[0]);
+    }
+
+
+
+    @Override
+    WorkerThread<?> newWorkerThread(final AsynchronousConnection connection,
+        final ConnectionFactory connectionFactory)
+    {
+      return new ModifyWorkerThread(connection, connectionFactory);
+    }
+  }
+
+
+
+  /**
+   * The main method for ModRate tool.
+   *
+   * @param args
+   *          The command-line arguments provided to this program.
+   */
+
+  public static void main(final String[] args)
+  {
+    final int retCode = mainModRate(args, System.in, System.out, System.err);
+    System.exit(filterExitCode(retCode));
+  }
+
+
+
+  /**
+   * Parses the provided command-line arguments and uses that information to run
+   * the modrate tool.
+   *
+   * @param args
+   *          The command-line arguments provided to this program.
+   * @return The error code.
+   */
+
+  static int mainModRate(final String[] args)
+  {
+    return mainModRate(args, System.in, System.out, System.err);
+  }
+
+
+
+  /**
+   * Parses the provided command-line arguments and uses that information to run
+   * the modrate tool.
+   *
+   * @param args
+   *          The command-line arguments provided to this program.
+   * @param inStream
+   *          The input stream to use for standard input, or <CODE>null</CODE>
+   *          if standard input is not needed.
+   * @param outStream
+   *          The output stream to use for standard output, or <CODE>null</CODE>
+   *          if standard output is not needed.
+   * @param errStream
+   *          The output stream to use for standard error, or <CODE>null</CODE>
+   *          if standard error is not needed.
+   * @return The error code.
+   */
+
+  static int mainModRate(final String[] args, final InputStream inStream,
+      final OutputStream outStream, final OutputStream errStream)
+
+  {
+    return new ModRate(inStream, outStream, errStream).run(args);
+  }
+
+
+
+  private BooleanArgument verbose;
+
+
+
+  private ModRate(final InputStream in, final OutputStream out,
+      final OutputStream err)
+  {
+    super(in, out, err);
+
   }
 
 
@@ -346,9 +233,9 @@
   /**
    * Indicates whether or not the user has requested advanced mode.
    *
-   * @return Returns <code>true</code> if the user has requested
-   *         advanced mode.
+   * @return Returns <code>true</code> if the user has requested advanced mode.
    */
+  @Override
   public boolean isAdvancedMode()
   {
     return false;
@@ -357,12 +244,12 @@
 
 
   /**
-   * Indicates whether or not the user has requested interactive
-   * behavior.
+   * Indicates whether or not the user has requested interactive behavior.
    *
-   * @return Returns <code>true</code> if the user has requested
-   *         interactive behavior.
+   * @return Returns <code>true</code> if the user has requested interactive
+   *         behavior.
    */
+  @Override
   public boolean isInteractive()
   {
     return false;
@@ -372,14 +259,14 @@
 
   /**
    * Indicates whether or not this console application is running in its
-   * menu-driven mode. This can be used to dictate whether output should
-   * go to the error stream or not. In addition, it may also dictate
-   * whether or not sub-menus should display a cancel option as well as
-   * a quit option.
+   * menu-driven mode. This can be used to dictate whether output should go to
+   * the error stream or not. In addition, it may also dictate whether or not
+   * sub-menus should display a cancel option as well as a quit option.
    *
-   * @return Returns <code>true</code> if this console application is
-   *         running in its menu-driven mode.
+   * @return Returns <code>true</code> if this console application is running in
+   *         its menu-driven mode.
    */
+  @Override
   public boolean isMenuDrivenMode()
   {
     return false;
@@ -390,9 +277,9 @@
   /**
    * Indicates whether or not the user has requested quiet output.
    *
-   * @return Returns <code>true</code> if the user has requested quiet
-   *         output.
+   * @return Returns <code>true</code> if the user has requested quiet output.
    */
+  @Override
   public boolean isQuiet()
   {
     return false;
@@ -401,12 +288,12 @@
 
 
   /**
-   * Indicates whether or not the user has requested script-friendly
-   * output.
+   * Indicates whether or not the user has requested script-friendly output.
    *
-   * @return Returns <code>true</code> if the user has requested
-   *         script-friendly output.
+   * @return Returns <code>true</code> if the user has requested script-friendly
+   *         output.
    */
+  @Override
   public boolean isScriptFriendly()
   {
     return false;
@@ -417,11 +304,122 @@
   /**
    * Indicates whether or not the user has requested verbose output.
    *
-   * @return Returns <code>true</code> if the user has requested verbose
-   *         output.
+   * @return Returns <code>true</code> if the user has requested verbose output.
    */
+  @Override
   public boolean isVerbose()
   {
     return verbose.isPresent();
   }
+
+
+
+  private int run(final String[] args)
+  {
+    // Create the command-line argument parser for use with this
+    // program.
+    final LocalizableMessage toolDescription = LocalizableMessage
+        .raw("This utility can be used to " + "measure modify performance");
+    // TODO: correct usage
+    final ArgumentParser argParser = new ArgumentParser(
+        ModRate.class.getName(), toolDescription, false, true, 1, 0,
+        "[modifyString ...]");
+    ArgumentParserConnectionFactory connectionFactory;
+    ModifyPerformanceRunner runner;
+
+    BooleanArgument showUsage;
+    StringArgument propertiesFileArgument;
+    BooleanArgument noPropertiesFileArgument;
+    StringArgument baseDN;
+
+    try
+    {
+      connectionFactory = new ArgumentParserConnectionFactory(argParser, this);
+      runner = new ModifyPerformanceRunner(argParser, this);
+      propertiesFileArgument = new StringArgument("propertiesFilePath", null,
+          OPTION_LONG_PROP_FILE_PATH, false, false, true,
+          INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null,
+          INFO_DESCRIPTION_PROP_FILE_PATH.get());
+      argParser.addArgument(propertiesFileArgument);
+      argParser.setFilePropertiesArgument(propertiesFileArgument);
+
+      noPropertiesFileArgument = new BooleanArgument(
+          "noPropertiesFileArgument", null, OPTION_LONG_NO_PROP_FILE,
+          INFO_DESCRIPTION_NO_PROP_FILE.get());
+      argParser.addArgument(noPropertiesFileArgument);
+      argParser.setNoPropertiesFileArgument(noPropertiesFileArgument);
+
+      baseDN = new StringArgument("baseDN", OPTION_SHORT_BASEDN,
+          OPTION_LONG_BASEDN, true, false, true, INFO_BASEDN_PLACEHOLDER.get(),
+          null, null, INFO_SEARCH_DESCRIPTION_BASEDN.get());
+      baseDN.setPropertyName(OPTION_LONG_BASEDN);
+      argParser.addArgument(baseDN);
+
+      verbose = new BooleanArgument("verbose", 'v', "verbose",
+          INFO_DESCRIPTION_VERBOSE.get());
+      verbose.setPropertyName("verbose");
+      argParser.addArgument(verbose);
+
+      showUsage = new BooleanArgument("showUsage", OPTION_SHORT_HELP,
+          OPTION_LONG_HELP, INFO_DESCRIPTION_SHOWUSAGE.get());
+      argParser.addArgument(showUsage);
+      argParser.setUsageArgument(showUsage, getOutputStream());
+    }
+    catch (final ArgumentException ae)
+    {
+      final LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae
+          .getMessage());
+      println(message);
+      return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
+    }
+
+    // Parse the command-line arguments provided to this program.
+    try
+    {
+      argParser.parseArguments(args);
+      connectionFactory.validate();
+      runner.validate();
+    }
+    catch (final ArgumentException ae)
+    {
+      final LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae
+          .getMessage());
+      println(message);
+      println(argParser.getUsageMessage());
+      return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
+    }
+
+    // If we should just display usage or version information,
+    // then print it and exit.
+    if (argParser.usageOrVersionDisplayed())
+    {
+      return 0;
+    }
+
+    runner.modStrings = argParser.getTrailingArguments().toArray(
+        new String[argParser.getTrailingArguments().size()]);
+    runner.baseDN = baseDN.getValue();
+
+    try
+    {
+
+      // Try it out to make sure the format string and data sources
+      // match.
+      final Object[] data = DataSource.generateData(runner.getDataSources(),
+          null);
+      for (final String modString : runner.modStrings)
+      {
+        String.format(modString, data);
+      }
+      String.format(runner.baseDN, data);
+    }
+    catch (final Exception ex1)
+    {
+      println(LocalizableMessage.raw("Error formatting filter or base DN: "
+          + ex1.toString()));
+      return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
+    }
+
+    return runner.run(connectionFactory);
+  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/MultiChoiceArgument.java b/sdk/src/com/sun/opends/sdk/tools/MultiChoiceArgument.java
index 2a573b3..61eb812 100644
--- a/sdk/src/com/sun/opends/sdk/tools/MultiChoiceArgument.java
+++ b/sdk/src/com/sun/opends/sdk/tools/MultiChoiceArgument.java
@@ -28,7 +28,7 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_MCARG_VALUE_NOT_ALLOWED;
 
 import java.util.Collection;
 
@@ -37,20 +37,21 @@
 
 
 
-
 /**
- * This class defines an argument type that will only accept one or more
- * of a specific set of string values.
+ * This class defines an argument type that will only accept one or more of a
+ * specific set of string values.
+ *
+ * @param <T>
+ *          The type of values returned by this argument.
  */
 final class MultiChoiceArgument<T> extends Argument
 {
   // Indicates whether argument values should be treated in a
-  // case-sensitive
-  // manner.
-  private boolean caseSensitive;
+  // case-sensitive manner.
+  private final boolean caseSensitive;
 
   // The set of values that will be allowed for use with this argument.
-  private Collection<T> allowedValues;
+  private final Collection<T> allowedValues;
 
 
 
@@ -58,109 +59,56 @@
    * Creates a new string argument with the provided information.
    *
    * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
+   *          The generic name that should be used to refer to this argument.
    * @param shortIdentifier
    *          The single-character identifier for this argument, or
    *          <CODE>null</CODE> if there is none.
    * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
    * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
-   * @param needsValue
-   *          Indicates whether this argument requires a value.
-   * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
-   * @param allowedValues
-   *          The set of values that are allowed for use for this
-   *          argument. If they are not to be treated in a
-   *          case-sensitive value then they should all be formatted in
-   *          lowercase.
-   * @param caseSensitive
-   *          Indicates whether the set of allowed values should be
-   *          treated in a case-sensitive manner.
-   * @param description
-   *          LocalizableMessage for the description of this argument.
-   * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
-   */
-  public MultiChoiceArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean needsValue,
-      LocalizableMessage valuePlaceholder, Collection<T> allowedValues,
-      boolean caseSensitive, LocalizableMessage description)
-      throws ArgumentException
-  {
-    super(name, shortIdentifier, longIdentifier, isRequired, false,
-        needsValue, valuePlaceholder, null, null, description);
-
-    this.allowedValues = allowedValues;
-    this.caseSensitive = caseSensitive;
-  }
-
-
-
-  /**
-   * Creates a new string argument with the provided information.
-   *
-   * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
-   * @param shortIdentifier
-   *          The single-character identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
-   * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
+   *          Indicates whether this argument must be specified on the command
+   *          line.
    * @param isMultiValued
-   *          Indicates whether this argument may be specified more than
-   *          once to provide multiple values.
+   *          Indicates whether this argument may be specified more than once to
+   *          provide multiple values.
    * @param needsValue
    *          Indicates whether this argument requires a value.
    * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
    * @param defaultValue
-   *          The default value that should be used for this argument if
-   *          none is provided in a properties file or on the command
-   *          line. This may be <CODE>null</CODE> if there is no generic
-   *          default.
+   *          The default value that should be used for this argument if none is
+   *          provided in a properties file or on the command line. This may be
+   *          <CODE>null</CODE> if there is no generic default.
    * @param propertyName
-   *          The name of the property in a property file that may be
-   *          used to override the default value but will be overridden
-   *          by a command-line argument.
+   *          The name of the property in a property file that may be used to
+   *          override the default value but will be overridden by a
+   *          command-line argument.
    * @param allowedValues
-   *          The set of values that are allowed for use for this
-   *          argument. If they are not to be treated in a
-   *          case-sensitive value then they should all be formatted in
-   *          lowercase.
+   *          The set of values that are allowed for use for this argument. If
+   *          they are not to be treated in a case-sensitive value then they
+   *          should all be formatted in lowercase.
    * @param caseSensitive
-   *          Indicates whether the set of allowed values should be
-   *          treated in a case-sensitive manner.
+   *          Indicates whether the set of allowed values should be treated in a
+   *          case-sensitive manner.
    * @param description
    *          LocalizableMessage for the description of this argument.
    * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
    */
-  public MultiChoiceArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean isMultiValued,
-      boolean needsValue, LocalizableMessage valuePlaceholder,
-      String defaultValue, String propertyName,
-      Collection<T> allowedValues, boolean caseSensitive,
-      LocalizableMessage description) throws ArgumentException
+  public MultiChoiceArgument(final String name,
+      final Character shortIdentifier, final String longIdentifier,
+      final boolean isRequired, final boolean isMultiValued,
+      final boolean needsValue, final LocalizableMessage valuePlaceholder,
+      final String defaultValue, final String propertyName,
+      final Collection<T> allowedValues, final boolean caseSensitive,
+      final LocalizableMessage description) throws ArgumentException
   {
-    super(name, shortIdentifier, longIdentifier, isRequired,
-        isMultiValued, needsValue, valuePlaceholder, defaultValue,
-        propertyName, description);
+    super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued,
+        needsValue, valuePlaceholder, defaultValue, propertyName, description);
 
     this.allowedValues = allowedValues;
     this.caseSensitive = caseSensitive;
@@ -169,8 +117,57 @@
 
 
   /**
-   * Retrieves the set of allowed values for this argument. The contents
-   * of this set must not be altered by the caller.
+   * Creates a new string argument with the provided information.
+   *
+   * @param name
+   *          The generic name that should be used to refer to this argument.
+   * @param shortIdentifier
+   *          The single-character identifier for this argument, or
+   *          <CODE>null</CODE> if there is none.
+   * @param longIdentifier
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
+   * @param isRequired
+   *          Indicates whether this argument must be specified on the command
+   *          line.
+   * @param needsValue
+   *          Indicates whether this argument requires a value.
+   * @param valuePlaceholder
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
+   * @param allowedValues
+   *          The set of values that are allowed for use for this argument. If
+   *          they are not to be treated in a case-sensitive value then they
+   *          should all be formatted in lowercase.
+   * @param caseSensitive
+   *          Indicates whether the set of allowed values should be treated in a
+   *          case-sensitive manner.
+   * @param description
+   *          LocalizableMessage for the description of this argument.
+   * @throws ArgumentException
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
+   */
+  public MultiChoiceArgument(final String name,
+      final Character shortIdentifier, final String longIdentifier,
+      final boolean isRequired, final boolean needsValue,
+      final LocalizableMessage valuePlaceholder,
+      final Collection<T> allowedValues, final boolean caseSensitive,
+      final LocalizableMessage description) throws ArgumentException
+  {
+    super(name, shortIdentifier, longIdentifier, isRequired, false, needsValue,
+        valuePlaceholder, null, null, description);
+
+    this.allowedValues = allowedValues;
+    this.caseSensitive = caseSensitive;
+  }
+
+
+
+  /**
+   * Retrieves the set of allowed values for this argument. The contents of this
+   * set must not be altered by the caller.
    *
    * @return The set of allowed values for this argument.
    */
@@ -182,8 +179,39 @@
 
 
   /**
-   * Indicates whether the set of allowed values for this argument
-   * should be treated in a case-sensitive manner.
+   * Retrieves the string vale for this argument. If it has multiple values,
+   * then the first will be returned. If it does not have any values, then the
+   * default value will be returned.
+   *
+   * @return The string value for this argument, or <CODE>null</CODE> if there
+   *         are no values and no default value has been given.
+   * @throws ArgumentException
+   *           The value cannot be parsed.
+   */
+  public T getTypedValue() throws ArgumentException
+  {
+    final String v = super.getValue();
+    if (v == null)
+    {
+      return null;
+    }
+    for (final T o : allowedValues)
+    {
+      if ((caseSensitive && o.toString().equals(v))
+          || o.toString().equalsIgnoreCase(v))
+      {
+        return o;
+      }
+    }
+    // TODO: Some message
+    throw new ArgumentException(null);
+  }
+
+
+
+  /**
+   * Indicates whether the set of allowed values for this argument should be
+   * treated in a case-sensitive manner.
    *
    * @return <CODE>true</CODE> if the values are to be treated in a
    *         case-sensitive manner, or <CODE>false</CODE> if not.
@@ -196,47 +224,15 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in this
-   * argument.
-   *
-   * @param valueString
-   *          The value for which to make the determination.
-   * @param invalidReason
-   *          A buffer into which the invalid reason may be written if
-   *          the value is not acceptable.
-   * @return <CODE>true</CODE> if the value is acceptable, or
-   *         <CODE>false</CODE> if it is not.
-   */
-  public boolean valueIsAcceptable(String valueString,
-      LocalizableMessageBuilder invalidReason)
-  {
-    for (T o : allowedValues)
-    {
-      if ((caseSensitive && o.toString().equals(valueString))
-          || o.toString().equalsIgnoreCase(valueString))
-      {
-        return true;
-      }
-    }
-    invalidReason.append(ERR_MCARG_VALUE_NOT_ALLOWED.get(getName(),
-        valueString));
-
-    return false;
-  }
-
-
-
-  /**
-   * Specifies the default value that will be used for this argument if
-   * it is not specified on the command line and it is not set from a
-   * properties file.
+   * Specifies the default value that will be used for this argument if it is
+   * not specified on the command line and it is not set from a properties file.
    *
    * @param defaultValue
-   *          The default value that will be used for this argument if
-   *          it is not specified on the command line and it is not set
-   *          from a properties file.
+   *          The default value that will be used for this argument if it is not
+   *          specified on the command line and it is not set from a properties
+   *          file.
    */
-  public void setDefaultValue(T defaultValue)
+  public void setDefaultValue(final T defaultValue)
   {
     super.setDefaultValue(defaultValue.toString());
   }
@@ -244,31 +240,32 @@
 
 
   /**
-   * Retrieves the string vale for this argument. If it has multiple
-   * values, then the first will be returned. If it does not have any
-   * values, then the default value will be returned.
+   * Indicates whether the provided value is acceptable for use in this
+   * argument.
    *
-   * @return The string value for this argument, or <CODE>null</CODE> if
-   *         there are no values and no default value has been given.
-   * @throws ArgumentException
-   *           The value cannot be parsed.
+   * @param valueString
+   *          The value for which to make the determination.
+   * @param invalidReason
+   *          A buffer into which the invalid reason may be written if the value
+   *          is not acceptable.
+   * @return <CODE>true</CODE> if the value is acceptable, or <CODE>false</CODE>
+   *         if it is not.
    */
-  public T getTypedValue() throws ArgumentException
+  @Override
+  public boolean valueIsAcceptable(final String valueString,
+      final LocalizableMessageBuilder invalidReason)
   {
-    String v = super.getValue();
-    if (v == null)
+    for (final T o : allowedValues)
     {
-      return null;
-    }
-    for (T o : allowedValues)
-    {
-      if ((caseSensitive && o.toString().equals(v))
-          || o.toString().equalsIgnoreCase(v))
+      if ((caseSensitive && o.toString().equals(valueString))
+          || o.toString().equalsIgnoreCase(valueString))
       {
-        return o;
+        return true;
       }
     }
-    // TODO: Some message
-    throw new ArgumentException(null);
+    invalidReason.append(ERR_MCARG_VALUE_NOT_ALLOWED
+        .get(getName(), valueString));
+
+    return false;
   }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/MultiColumnPrinter.java b/sdk/src/com/sun/opends/sdk/tools/MultiColumnPrinter.java
index 1f80177..f0bcd44 100644
--- a/sdk/src/com/sun/opends/sdk/tools/MultiColumnPrinter.java
+++ b/sdk/src/com/sun/opends/sdk/tools/MultiColumnPrinter.java
@@ -2,7 +2,8 @@
  * CDDL HEADER START
  *
  * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Versiance
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
  * with the License.
  *
  * You can obtain a copy of the license at
@@ -21,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
 package com.sun.opends.sdk.tools;
@@ -38,9 +39,8 @@
  * <P>
  * This class allows you to specify:
  * <UL>
- * <LI>The number of columns in the output. This will determine the
- * dimension of the string arrays passed to add(String[]) or
- * addTitle(String[]).
+ * <LI>The number of columns in the output. This will determine the dimension of
+ * the string arrays passed to add(String[]) or addTitle(String[]).
  * <LI>spacing/gap between columns
  * <LI>character to use for title border (null means no border)
  * <LI>column alignment. Only LEFT/CENTER is supported for now.
@@ -77,8 +77,8 @@
  *  John       john@foo.com   456-7890
  * </PRE>
  * <P>
- * This class also supports multi-row titles and having title strings
- * spanning multiple collumns. Example usage:
+ * This class also supports multi-row titles and having title strings spanning
+ * multiple collumns. Example usage:
  *
  * <PRE>
  * TestPrinter tp = new TestPrinter(4, 2, &quot;-&quot;);
@@ -147,13 +147,48 @@
 
   private Vector<int[]> titleSpanTable = null;
 
-  private int curLength[];
+  private final int curLength[];
 
   private final ConsoleApplication app;
 
 
 
   /**
+   * Creates a sorted new MultiColumnPrinter class using LEFT alignment and with
+   * no title border.
+   *
+   * @param numCol
+   *          number of columns
+   * @param gap
+   *          gap between each column
+   */
+  MultiColumnPrinter(final int numCol, final int gap,
+      final ConsoleApplication app)
+  {
+    this(numCol, gap, null, LEFT, app);
+  }
+
+
+
+  /**
+   * Creates a sorted new MultiColumnPrinter class using LEFT alignment.
+   *
+   * @param numCol
+   *          number of columns
+   * @param gap
+   *          gap between each column
+   * @param border
+   *          character used to frame the titles
+   */
+  MultiColumnPrinter(final int numCol, final int gap, final String border,
+      final ConsoleApplication app)
+  {
+    this(numCol, gap, border, LEFT, app);
+  }
+
+
+
+  /**
    * Creates a new MultiColumnPrinter class.
    *
    * @param numCol
@@ -165,8 +200,8 @@
    * @param align
    *          type of alignment within columns
    */
-  MultiColumnPrinter(int numCol, int gap, String border, int align,
-      ConsoleApplication app)
+  MultiColumnPrinter(final int numCol, final int gap, final String border,
+      final int align, final ConsoleApplication app)
   {
 
     titleTable = new Vector<String[]>();
@@ -185,50 +220,19 @@
 
 
   /**
-   * Creates a sorted new MultiColumnPrinter class using LEFT alignment.
-   *
-   * @param numCol
-   *          number of columns
-   * @param gap
-   *          gap between each column
-   * @param border
-   *          character used to frame the titles
-   */
-  MultiColumnPrinter(int numCol, int gap, String border,
-      ConsoleApplication app)
-  {
-    this(numCol, gap, border, LEFT, app);
-  }
-
-
-
-  /**
-   * Creates a sorted new MultiColumnPrinter class using LEFT alignment
-   * and with no title border.
-   *
-   * @param numCol
-   *          number of columns
-   * @param gap
-   *          gap between each column
-   */
-  MultiColumnPrinter(int numCol, int gap, ConsoleApplication app)
-  {
-    this(numCol, gap, null, LEFT, app);
-  }
-
-
-
-  /**
    * Adds to the row of strings to be used as the title for the table.
    *
    * @param row
    *          Array of strings to print in one row of title.
    */
-  void addTitle(String[] row)
+  void addTitle(final String[] row)
   {
-    if (row == null) return;
+    if (row == null)
+    {
+      return;
+    }
 
-    int[] span = new int[row.length];
+    final int[] span = new int[row.length];
     for (int i = 0; i < row.length; i++)
     {
       span[i] = 1;
@@ -240,12 +244,12 @@
 
 
   /**
-   * Adds to the row of strings to be used as the title for the table.
-   * Also allows for certain title strings to span multiple collumns The
-   * span parameter is an array of integers which indicate how many
-   * collumns the corresponding title string will occupy. For a row that
-   * is 4 collumns wide, it is possible to have some title strings in a
-   * row to 'span' multiple collumns:
+   * Adds to the row of strings to be used as the title for the table. Also
+   * allows for certain title strings to span multiple collumns The span
+   * parameter is an array of integers which indicate how many collumns the
+   * corresponding title string will occupy. For a row that is 4 collumns wide,
+   * it is possible to have some title strings in a row to 'span' multiple
+   * collumns:
    * <P>
    *
    * <PRE>
@@ -257,9 +261,9 @@
    * John   Doe    john@foo.com  456-7890
    * </PRE>
    *
-   * In the example above, the title row has a string 'Name' that spans
-   * 2 collumns. The string 'Contact' also spans 2 collumns. The above
-   * is done by passing in to addTitle() an array that contains:
+   * In the example above, the title row has a string 'Name' that spans 2
+   * collumns. The string 'Contact' also spans 2 collumns. The above is done by
+   * passing in to addTitle() an array that contains:
    *
    * <PRE>
    * span[0] = 2; // spans 2 collumns
@@ -286,12 +290,12 @@
    *          Array of integers that reflect the number of collumns the
    *          corresponding title string will occupy.
    */
-  void addTitle(String[] row, int span[])
+  void addTitle(final String[] row, final int span[])
   {
     // Need to create a new instance of it, otherwise the new values
     // will always overwrite the old values.
 
-    String[] rowInstance = new String[(row.length)];
+    final String[] rowInstance = new String[(row.length)];
     for (int i = 0; i < row.length; i++)
     {
       rowInstance[i] = row[i];
@@ -304,18 +308,6 @@
 
 
   /**
-   * Set alignment for title strings
-   *
-   * @param titleAlign
-   */
-  void setTitleAlign(int titleAlign)
-  {
-    this.titleAlign = titleAlign;
-  }
-
-
-
-  /**
    * Clears title strings.
    */
   void clearTitle()
@@ -327,6 +319,54 @@
 
 
   /**
+   * Adds one row of text to output.
+   *
+   * @param row
+   *          Array of strings to print in one row.
+   */
+  void printRow(final String... row)
+  {
+    for (int i = 0; i < numCol; i++)
+    {
+      if (titleAlign == RIGHT)
+      {
+        final int spaceBefore = curLength[i] - row[i].length();
+        printSpaces(spaceBefore);
+        app.getOutputStream().print(row[i]);
+        if (i < numCol - 1)
+        {
+          printSpaces(gap);
+        }
+      }
+      else if (align == CENTER)
+      {
+        int space1, space2;
+        space1 = (curLength[i] - row[i].length()) / 2;
+        space2 = curLength[i] - row[i].length() - space1;
+
+        printSpaces(space1);
+        app.getOutputStream().print(row[i]);
+        printSpaces(space2);
+        if (i < numCol - 1)
+        {
+          printSpaces(gap);
+        }
+      }
+      else
+      {
+        app.getOutputStream().print(row[i]);
+        if (i < numCol - 1)
+        {
+          printSpaces(curLength[i] - row[i].length() + gap);
+        }
+      }
+    }
+    app.getOutputStream().println("");
+  }
+
+
+
+  /**
    * Prints the table title
    */
   void printTitle()
@@ -338,23 +378,27 @@
     Enumeration<int[]> spanEnum = titleSpanTable.elements();
     while (elm.hasMoreElements())
     {
-      String[] row = elm.nextElement();
-      int[] curSpan = spanEnum.nextElement();
+      final String[] row = elm.nextElement();
+      final int[] curSpan = spanEnum.nextElement();
 
       for (int i = 0; i < numCol; i++)
       {
         // None of the fields should be null, but if it
         // happens to be so, replace it with "-".
-        if (row[i] == null) row[i] = "-";
+        if (row[i] == null)
+        {
+          row[i] = "-";
+        }
 
         int len = row[i].length();
 
         /*
-         * If a title string spans multiple collumns, then the space it
-         * occupies in each collumn is at most len/span (since we have
-         * gap to take into account as well).
+         * If a title string spans multiple collumns, then the space it occupies
+         * in each collumn is at most len/span (since we have gap to take into
+         * account as well).
          */
-        int span = curSpan[i], rem = 0;
+        final int span = curSpan[i];
+        int rem = 0;
         if (span > 1)
         {
           rem = len % span;
@@ -373,8 +417,7 @@
             }
 
             /*
-             * Add remainder to last collumn in span to avoid round-off
-             * errors.
+             * Add remainder to last collumn in span to avoid round-off errors.
              */
             curLength[(i + span) - 1] += rem;
           }
@@ -388,14 +431,18 @@
 
     while (elm.hasMoreElements())
     {
-      String[] row = elm.nextElement();
-      int[] curSpan = spanEnum.nextElement();
+      final String[] row = elm.nextElement();
+      final int[] curSpan = spanEnum.nextElement();
 
       for (int i = 0; i < numCol; i++)
       {
-        int availableSpace = 0, span = curSpan[i];
+        int availableSpace = 0;
+        final int span = curSpan[i];
 
-        if (span == 0) continue;
+        if (span == 0)
+        {
+          continue;
+        }
 
         availableSpace = curLength[i];
 
@@ -410,27 +457,35 @@
 
         if (titleAlign == RIGHT)
         {
-          int space_before = availableSpace - row[i].length();
-          printSpaces(space_before);
+          final int spaceBefore = availableSpace - row[i].length();
+          printSpaces(spaceBefore);
           app.getOutputStream().print(row[i]);
-          if (i < numCol - 1) printSpaces(gap);
+          if (i < numCol - 1)
+          {
+            printSpaces(gap);
+          }
         }
         else if (titleAlign == CENTER)
         {
-          int space_before, space_after;
-          space_before = (availableSpace - row[i].length()) / 2;
-          space_after = availableSpace - row[i].length() - space_before;
+          int spaceBefore, spaceAfter;
+          spaceBefore = (availableSpace - row[i].length()) / 2;
+          spaceAfter = availableSpace - row[i].length() - spaceBefore;
 
-          printSpaces(space_before);
+          printSpaces(spaceBefore);
           app.getOutputStream().print(row[i]);
-          printSpaces(space_after);
-          if (i < numCol - 1) printSpaces(gap);
+          printSpaces(spaceAfter);
+          if (i < numCol - 1)
+          {
+            printSpaces(gap);
+          }
         }
         else
         {
           app.getOutputStream().print(row[i]);
           if (i < numCol - 1)
+          {
             printSpaces(availableSpace - row[i].length() + gap);
+          }
         }
 
       }
@@ -442,58 +497,23 @@
 
 
   /**
-   * Adds one row of text to output.
+   * Set alignment for title strings
    *
-   * @param row
-   *          Array of strings to print in one row.
+   * @param titleAlign
    */
-  void printRow(String... row)
+  void setTitleAlign(final int titleAlign)
   {
-    for (int i = 0; i < numCol; i++)
-    {
-      if (titleAlign == RIGHT)
-      {
-        int space_before = curLength[i] - row[i].length();
-        printSpaces(space_before);
-        app.getOutputStream().print(row[i]);
-        if (i < numCol - 1) printSpaces(gap);
-      }
-      else if (align == CENTER)
-      {
-        int space1, space2;
-        space1 = (curLength[i] - row[i].length()) / 2;
-        space2 = curLength[i] - row[i].length() - space1;
-
-        printSpaces(space1);
-        app.getOutputStream().print(row[i]);
-        printSpaces(space2);
-        if (i < numCol - 1) printSpaces(gap);
-      }
-      else
-      {
-        app.getOutputStream().print(row[i]);
-        if (i < numCol - 1)
-          printSpaces(curLength[i] - row[i].length() + gap);
-      }
-    }
-    app.getOutputStream().println("");
-  }
-
-
-
-  private void printSpaces(int count)
-  {
-    for (int i = 0; i < count; ++i)
-    {
-      app.getOutputStream().print(" ");
-    }
+    this.titleAlign = titleAlign;
   }
 
 
 
   private void printBorder()
   {
-    if (border == null) return;
+    if (border == null)
+    {
+      return;
+    }
 
     // For the value in each column
     for (int i = 0; i < numCol; i++)
@@ -514,4 +534,14 @@
     }
     app.getOutputStream().println("");
   }
+
+
+
+  private void printSpaces(final int count)
+  {
+    for (int i = 0; i < count; ++i)
+    {
+      app.getOutputStream().print(" ");
+    }
+  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/PerformanceRunner.java b/sdk/src/com/sun/opends/sdk/tools/PerformanceRunner.java
index f1f4811..03c0bce 100644
--- a/sdk/src/com/sun/opends/sdk/tools/PerformanceRunner.java
+++ b/sdk/src/com/sun/opends/sdk/tools/PerformanceRunner.java
@@ -38,491 +38,23 @@
 import java.util.concurrent.atomic.AtomicReference;
 
 import org.opends.sdk.*;
+import org.opends.sdk.responses.ExtendedResult;
 import org.opends.sdk.responses.Result;
 
 import com.sun.opends.sdk.tools.AuthenticatedConnectionFactory.AuthenticatedAsynchronousConnection;
 
 
 
-
 /**
  * Benchmark application framework.
  */
-abstract class PerformanceRunner
+abstract class PerformanceRunner implements ConnectionEventListener
 {
-  private final AtomicInteger operationRecentCount = new AtomicInteger();
-
-  private final AtomicInteger successRecentCount = new AtomicInteger();
-
-  private final AtomicInteger failedRecentCount = new AtomicInteger();
-
-  private final AtomicLong waitRecentTime = new AtomicLong();
-
-  private final AtomicReference<ReversableArray> eTimeBuffer = new AtomicReference<ReversableArray>(
-      new ReversableArray(100000));
-
-  private final ConsoleApplication app;
-
-  private final ThreadLocal<DataSource[]> dataSources = new ThreadLocal<DataSource[]>();
-
-  private volatile boolean stopRequested;
-
-  private int numThreads;
-
-  private int numConnections;
-
-  private int targetThroughput;
-
-  private int maxIterations;
-
-  private boolean isAsync;
-
-  private boolean noRebind;
-
-  private int statsInterval;
-
-  private IntegerArgument numThreadsArgument;
-
-  private IntegerArgument maxIterationsArgument;
-
-  private IntegerArgument statsIntervalArgument;
-
-  private IntegerArgument targetThroughputArgument;
-
-  private IntegerArgument numConnectionsArgument;
-
-  private IntegerArgument percentilesArgument;
-
-  private BooleanArgument keepConnectionsOpen;
-
-  private BooleanArgument noRebindArgument;
-
-  private BooleanArgument asyncArgument;
-
-  private StringArgument arguments;
-
-
-
-  PerformanceRunner(ArgumentParser argParser, ConsoleApplication app)
-      throws ArgumentException
-  {
-    this.app = app;
-    numThreadsArgument = new IntegerArgument("numThreads", 't',
-        "numThreads", false, false, true, LocalizableMessage.raw("{numThreads}"),
-        1, null, true, 1, false, 0, LocalizableMessage
-            .raw("number of search threads per connection"));
-    numThreadsArgument.setPropertyName("numThreads");
-    argParser.addArgument(numThreadsArgument);
-
-    numConnectionsArgument = new IntegerArgument("numConnections", 'c',
-        "numConnections", false, false, true, LocalizableMessage
-            .raw("{numConnections}"), 1, null, true, 1, false, 0,
-        LocalizableMessage.raw("number of connections"));
-    numThreadsArgument.setPropertyName("numConnections");
-    argParser.addArgument(numConnectionsArgument);
-
-    maxIterationsArgument = new IntegerArgument("maxIterations", 'm',
-        "maxIterations", false, false, true, LocalizableMessage
-            .raw("{maxIterations}"), 0, null, LocalizableMessage
-            .raw("max searches per thread, 0 for unlimited"));
-    numThreadsArgument.setPropertyName("maxIterations");
-    argParser.addArgument(maxIterationsArgument);
-
-    statsIntervalArgument = new IntegerArgument("statInterval", 'i',
-        "statInterval", false, false, true, LocalizableMessage
-            .raw("{statInterval}"), 5, null, true, 1, false, 0, LocalizableMessage
-            .raw("Display results each specified number of seconds"));
-    numThreadsArgument.setPropertyName("statInterval");
-    argParser.addArgument(statsIntervalArgument);
-
-    targetThroughputArgument = new IntegerArgument("targetThroughput",
-        'M', "targetThroughput", false, false, true, LocalizableMessage
-            .raw("{targetThroughput}"), 0, null, LocalizableMessage
-            .raw("Target average throughput to achieve"));
-    targetThroughputArgument.setPropertyName("targetThroughput");
-    argParser.addArgument(targetThroughputArgument);
-
-    percentilesArgument = new IntegerArgument("percentile", 'e',
-        "percentile", false, true, LocalizableMessage.raw("{percentile}"), true,
-        50, true, 100, LocalizableMessage.raw("Calculate max response time for a "
-            + "percentile of operations"));
-    percentilesArgument.setPropertyName("percentile");
-    argParser.addArgument(percentilesArgument);
-
-    keepConnectionsOpen = new BooleanArgument("keepConnectionsOpen",
-        'f', "keepConnectionsOpen", LocalizableMessage
-            .raw("keep connections open"));
-    keepConnectionsOpen.setPropertyName("keepConnectionsOpen");
-    argParser.addArgument(keepConnectionsOpen);
-
-    noRebindArgument = new BooleanArgument("noRebind", 'F', "noRebind",
-        LocalizableMessage.raw("keep connections open and don't rebind"));
-    keepConnectionsOpen.setPropertyName("noRebind");
-    argParser.addArgument(noRebindArgument);
-
-    asyncArgument = new BooleanArgument("asynchronous", 'A',
-        "asynchronous", LocalizableMessage.raw("asynch, don't wait for results"));
-    keepConnectionsOpen.setPropertyName("asynchronous");
-    argParser.addArgument(asyncArgument);
-
-    arguments = new StringArgument(
-        "arguments",
-        'g',
-        "arguments",
-        false,
-        true,
-        true,
-        LocalizableMessage.raw("{arguments}"),
-        null,
-        null,
-        LocalizableMessage
-            .raw("arguments for variables in the filter and/or base DN"));
-    arguments.setPropertyName("arguments");
-    argParser.addArgument(arguments);
-  }
-
-
-
-  public void validate() throws ArgumentException
-  {
-    numConnections = numConnectionsArgument.getIntValue();
-    numThreads = numThreadsArgument.getIntValue();
-    maxIterations = maxIterationsArgument.getIntValue();
-    statsInterval = statsIntervalArgument.getIntValue() * 1000;
-    targetThroughput = targetThroughputArgument.getIntValue();
-
-    isAsync = asyncArgument.isPresent();
-    noRebind = noRebindArgument.isPresent();
-
-    if (!noRebindArgument.isPresent() && this.numThreads > 1)
-    {
-      throw new ArgumentException(LocalizableMessage.raw("--"
-          + noRebindArgument.getLongIdentifier()
-          + " must be used if --"
-          + numThreadsArgument.getLongIdentifier() + " is > 1"));
-    }
-
-    if (!noRebindArgument.isPresent() && asyncArgument.isPresent())
-    {
-      throw new ArgumentException(LocalizableMessage.raw("--"
-          + noRebindArgument.getLongIdentifier()
-          + " must be used when using --"
-          + asyncArgument.getLongIdentifier()));
-    }
-
-    try
-    {
-      DataSource.parse(arguments.getValues());
-    }
-    catch (IOException ioe)
-    {
-      throw new ArgumentException(LocalizableMessage
-          .raw("Error occured while parsing arguments: "
-              + ioe.toString()));
-    }
-  }
-
-
-
-  final int run(ConnectionFactory connectionFactory)
-  {
-    List<Thread> threads = new ArrayList<Thread>();
-
-    AsynchronousConnection connection = null;
-    Thread thread;
-    try
-    {
-      for (int i = 0; i < numConnections; i++)
-      {
-        if (keepConnectionsOpen.isPresent()
-            || noRebindArgument.isPresent())
-        {
-          connection = connectionFactory.getAsynchronousConnection(
-              null).get();
-        }
-        for (int j = 0; j < numThreads; j++)
-        {
-          thread = newWorkerThread(connection, connectionFactory);
-
-          threads.add(thread);
-          thread.start();
-        }
-      }
-
-      Thread statsThread = newStatsThread();
-      statsThread.start();
-
-      for (Thread t : threads)
-      {
-        t.join();
-      }
-      stopRequested = true;
-      statsThread.join();
-    }
-    catch (InterruptedException e)
-    {
-      stopRequested = true;
-    }
-    catch (ErrorResultException e)
-    {
-      stopRequested = true;
-      app.println(LocalizableMessage.raw(e.getResult().getDiagnosticMessage()));
-    }
-
-    return 0;
-  }
-
-
-
-  final DataSource[] getDataSources()
-  {
-    try
-    {
-      return DataSource.parse(arguments.getValues());
-    }
-    catch (IOException ioe)
-    {
-      // Ignore as this shouldn've been handled eariler
-    }
-    return new DataSource[0];
-  }
-
-
-
-  abstract WorkerThread<?> newWorkerThread(
-      AsynchronousConnection connection,
-      ConnectionFactory connectionFactory);
-
-
-
-  abstract StatsThread newStatsThread();
-
-
-
-  class UpdateStatsResultHandler<S extends Result> implements
-      ResultHandler<S>
-  {
-    private long eTime;
-
-
-
-    UpdateStatsResultHandler(long eTime)
-    {
-      this.eTime = eTime;
-    }
-
-
-
-    public void handleResult(S result)
-    {
-      successRecentCount.getAndIncrement();
-      eTime = System.nanoTime() - eTime;
-      waitRecentTime.getAndAdd(eTime);
-      synchronized (this)
-      {
-        ReversableArray array = eTimeBuffer.get();
-        if (array.remaining() == 0)
-        {
-          array.set(array.size() - 1, eTime);
-        }
-        else
-        {
-          array.append(eTime);
-        }
-      }
-    }
-
-
-
-    public void handleErrorResult(ErrorResultException error)
-    {
-      failedRecentCount.getAndIncrement();
-      app.println(LocalizableMessage.raw(error.getResult().toString()));
-    }
-
-
-
-    public long getETime()
-    {
-      return eTime;
-    }
-  }
-
-
-
-  abstract class WorkerThread<R extends ResultHandler<?>> extends
-      Thread
-  {
-    private int count;
-
-    private final AsynchronousConnection connection;
-
-    private final ConnectionFactory connectionFactory;
-
-
-
-    WorkerThread(AsynchronousConnection connection,
-        ConnectionFactory connectionFactory)
-    {
-      super("Worker Thread");
-      this.connection = connection;
-      this.connectionFactory = connectionFactory;
-    }
-
-
-
-    public abstract FutureResult<?> performOperation(
-        AsynchronousConnection connection, R handler,
-        DataSource[] dataSources);
-
-
-
-    public abstract R getHandler(long startTime);
-
-
-
-    public void run()
-    {
-      if (dataSources.get() == null)
-      {
-        try
-        {
-          dataSources.set(DataSource.parse(arguments.getValues()));
-        }
-        catch (IOException ioe)
-        {
-          // Ignore as this shouldn've been handled eariler
-        }
-      }
-
-      FutureResult<?> future;
-      AsynchronousConnection connection;
-      R handler;
-
-      double targetTimeInMS = (1.0 / (targetThroughput / (numThreads * numConnections))) * 1000.0;
-      double sleepTimeInMS = 0;
-      long start;
-      while (!stopRequested
-          && !(maxIterations > 0 && count >= maxIterations))
-      {
-        start = System.nanoTime();
-        handler = getHandler(start);
-
-        if (this.connection == null)
-        {
-          try
-          {
-            connection = connectionFactory.getAsynchronousConnection(
-                null).get();
-          }
-          catch (InterruptedException e)
-          {
-            // Ignore and check stop requested
-            continue;
-          }
-          catch (ErrorResultException e)
-          {
-            app.println(LocalizableMessage.raw(e.getResult()
-                .getDiagnosticMessage()));
-            if (e.getCause() != null && app.isVerbose())
-            {
-              e.getCause().printStackTrace(app.getErrorStream());
-            }
-            stopRequested = true;
-            break;
-          }
-        }
-        else
-        {
-          connection = this.connection;
-          if (!noRebind
-              && connection instanceof AuthenticatedAsynchronousConnection)
-          {
-            AuthenticatedAsynchronousConnection ac = (AuthenticatedAsynchronousConnection) connection;
-            try
-            {
-              ac.rebind(null).get();
-            }
-            catch (InterruptedException e)
-            {
-              // Ignore and check stop requested
-              continue;
-            }
-            catch (ErrorResultException e)
-            {
-              app.println(LocalizableMessage.raw(e.getResult().toString()));
-              if (e.getCause() != null && app.isVerbose())
-              {
-                e.getCause().printStackTrace(app.getErrorStream());
-              }
-              stopRequested = true;
-              break;
-            }
-          }
-        }
-        future = performOperation(connection, handler, dataSources
-            .get());
-        operationRecentCount.getAndIncrement();
-        count++;
-        if (!isAsync)
-        {
-          try
-          {
-            future.get();
-          }
-          catch (InterruptedException e)
-          {
-            // Ignore and check stop requested
-            continue;
-          }
-          catch (ErrorResultException e)
-          {
-            if (e.getCause() instanceof IOException)
-            {
-              e.getCause().printStackTrace(app.getErrorStream());
-              stopRequested = true;
-              break;
-            }
-            // Ignore. Handled by result handler
-          }
-          if (this.connection == null)
-          {
-            connection.close();
-          }
-        }
-        if (targetThroughput > 0)
-        {
-          try
-          {
-            if (sleepTimeInMS > 1)
-            {
-              sleep((long) Math.floor(sleepTimeInMS));
-            }
-          }
-          catch (InterruptedException e)
-          {
-            continue;
-          }
-
-          sleepTimeInMS += targetTimeInMS
-              - ((System.nanoTime() - start) / 1000000.0);
-          if (sleepTimeInMS < -60000)
-          {
-            // If we fall behind by 60 seconds, just forget about
-            // catching up
-            sleepTimeInMS = -60000;
-          }
-        }
-      }
-    }
-  }
-
-
-
+  /**
+   * Statistics thread base implementation.
+   */
   class StatsThread extends Thread
   {
-    protected final String[] EMPTY_STRINGS = new String[0];
-
     private final MultiColumnPrinter printer;
 
     private final List<GarbageCollectorMXBean> beans;
@@ -561,10 +93,10 @@
 
 
 
-    public StatsThread(String[] additionalColumns)
+    public StatsThread(final String[] additionalColumns)
     {
       super("Stats Thread");
-      TreeSet<Double> pSet = new TreeSet<Double>();
+      final TreeSet<Double> pSet = new TreeSet<Double>();
       if (!percentilesArgument.isPresent())
       {
         pSet.add(.1);
@@ -573,14 +105,14 @@
       }
       else
       {
-        for (String percentile : percentilesArgument.getValues())
+        for (final String percentile : percentilesArgument.getValues())
         {
           pSet.add(100.0 - Double.parseDouble(percentile));
         }
       }
       this.percentiles = pSet.descendingSet();
-      numColumns = 5 + this.percentiles.size()
-          + additionalColumns.length + (isAsync ? 1 : 0);
+      numColumns = 5 + this.percentiles.size() + additionalColumns.length
+          + (isAsync ? 1 : 0);
       printer = new MultiColumnPrinter(numColumns, 2, "-",
           MultiColumnPrinter.RIGHT, app);
       printer.setTitleAlign(MultiColumnPrinter.RIGHT);
@@ -607,7 +139,7 @@
       title[2] = "recent";
       title[3] = "average";
       int i = 4;
-      for (Double percentile : this.percentiles)
+      for (final Double percentile : this.percentiles)
       {
         title[i++] = Double.toString(100.0 - percentile) + "%";
       }
@@ -616,7 +148,7 @@
       {
         title[i++] = "req/res";
       }
-      for (String column : additionalColumns)
+      for (final String column : additionalColumns)
       {
         title[i++] = column;
       }
@@ -628,24 +160,17 @@
 
 
 
-    String[] getAdditionalColumns()
-    {
-      return EMPTY_STRINGS;
-    }
-
-
-
     @Override
     public void run()
     {
       printer.printTitle();
 
-      String[] strings = new String[numColumns];
+      final String[] strings = new String[numColumns];
 
-      long startTime = System.currentTimeMillis();
+      final long startTime = System.currentTimeMillis();
       long statTime = startTime;
       long gcDuration = 0;
-      for (GarbageCollectorMXBean bean : beans)
+      for (final GarbageCollectorMXBean bean : beans)
       {
         gcDuration += bean.getCollectionTime();
       }
@@ -655,7 +180,7 @@
         {
           sleep(statsInterval);
         }
-        catch (InterruptedException ie)
+        catch (final InterruptedException ie)
         {
           // Ignore.
         }
@@ -665,7 +190,7 @@
 
         lastGCDuration = gcDuration;
         gcDuration = 0;
-        for (GarbageCollectorMXBean bean : beans)
+        for (final GarbageCollectorMXBean bean : beans)
         {
           gcDuration += bean.getCollectionTime();
         }
@@ -684,19 +209,31 @@
         averageDuration -= gcDuration;
         recentDuration /= 1000.0;
         averageDuration /= 1000.0;
-        strings[0] = String.format("%.1f", successCount
-            / recentDuration);
-        strings[1] = String.format("%.1f", totalSuccessCount
-            / averageDuration);
-        strings[2] = String.format("%.3f",
-            (waitTime - (gcDuration - lastGCDuration)) / successCount
-                / 1000000.0);
-        strings[3] = String.format("%.3f", (totalWaitTime - gcDuration)
-            / totalSuccessCount / 1000000.0);
+        strings[0] = String.format("%.1f", successCount / recentDuration);
+        strings[1] = String.format("%.1f", totalSuccessCount / averageDuration);
+        if (successCount > 0)
+        {
+          strings[2] = String.format("%.3f",
+              (waitTime - (gcDuration - lastGCDuration)) / successCount
+                  / 1000000.0);
+        }
+        else
+        {
+          strings[2] = "-";
+        }
+        if (totalSuccessCount > 0)
+        {
+          strings[3] = String.format("%.3f", (totalWaitTime - gcDuration)
+              / totalSuccessCount / 1000000.0);
+        }
+        else
+        {
+          strings[3] = "-";
+        }
 
         boolean changed = false;
         etimes = eTimeBuffer.getAndSet(etimes);
-        int appendLength = Math.min(array.remaining(), etimes.size());
+        final int appendLength = Math.min(array.remaining(), etimes.size());
         if (appendLength > 0)
         {
           array.append(etimes, appendLength);
@@ -737,36 +274,288 @@
         // Now everything is ordered from smallest to largest
         int index;
         int i = 4;
-        for (Double percent : percentiles)
+        for (final Double percent : percentiles)
         {
-          index = array.size()
-              - (int) Math.floor((percent / 100.0) * totalSuccessCount)
-              - 1;
-          if (index < 0)
+          if (array.size() <= 0)
           {
-            strings[i++] = String.format("*%.3f",
-                array.get(0) / 1000000.0);
+            strings[i++] = "-";
           }
           else
           {
-            strings[i++] = String.format("%.3f",
-                array.get(index) / 1000000.0);
+            index = array.size()
+                - (int) Math.floor((percent / 100.0) * totalSuccessCount) - 1;
+            if (index < 0)
+            {
+              strings[i++] = String.format("*%.3f", array.get(0) / 1000000.0);
+            }
+            else
+            {
+              strings[i++] = String
+                  .format("%.3f", array.get(index) / 1000000.0);
+            }
           }
         }
-        strings[i++] = String.format("%.1f", totalFailedCount
-            / averageDuration);
+        strings[i++] = String
+            .format("%.1f", totalFailedCount / averageDuration);
         if (isAsync)
         {
-          strings[i++] = String.format("%.1f", (double) searchCount
-              / successCount);
+          if (successCount > 0)
+          {
+            strings[i++] = String.format("%.1f", (double) searchCount
+                / successCount);
+          }
+          else
+          {
+            strings[i++] = "-";
+          }
         }
-        for (String column : getAdditionalColumns())
+        for (final String column : getAdditionalColumns())
         {
           strings[i++] = column;
         }
         printer.printRow(strings);
       }
     }
+
+
+
+    String[] getAdditionalColumns()
+    {
+      return EMPTY_STRINGS;
+    }
+  }
+
+
+
+  /**
+   * Statistics update result handler implementation.
+   *
+   * @param <S>
+   *          The type of expected result.
+   */
+  class UpdateStatsResultHandler<S extends Result> implements ResultHandler<S>
+  {
+    private long eTime;
+
+
+
+    UpdateStatsResultHandler(final long eTime)
+    {
+      this.eTime = eTime;
+    }
+
+
+
+    public long getETime()
+    {
+      return eTime;
+    }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      failedRecentCount.getAndIncrement();
+      app.println(LocalizableMessage.raw(error.getResult().toString()));
+    }
+
+
+
+    public void handleResult(final S result)
+    {
+      successRecentCount.getAndIncrement();
+      eTime = System.nanoTime() - eTime;
+      waitRecentTime.getAndAdd(eTime);
+      synchronized (this)
+      {
+        final ReversableArray array = eTimeBuffer.get();
+        if (array.remaining() == 0)
+        {
+          array.set(array.size() - 1, eTime);
+        }
+        else
+        {
+          array.append(eTime);
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * Worker thread base implementation.
+   *
+   * @param <R>
+   *          Type of result handler.
+   */
+  abstract class WorkerThread<R extends ResultHandler<?>> extends Thread
+  {
+    private int count;
+
+    private final AsynchronousConnection connection;
+
+    private final ConnectionFactory connectionFactory;
+
+
+
+    WorkerThread(final AsynchronousConnection connection,
+        final ConnectionFactory connectionFactory)
+    {
+      super("Worker Thread");
+      this.connection = connection;
+      this.connectionFactory = connectionFactory;
+    }
+
+
+
+    public abstract R getHandler(long startTime);
+
+
+
+    public abstract FutureResult<?> performOperation(
+        AsynchronousConnection connection, R handler, DataSource[] dataSources);
+
+
+
+    @Override
+    public void run()
+    {
+      if (dataSources.get() == null)
+      {
+        try
+        {
+          dataSources.set(DataSource.parse(arguments.getValues()));
+        }
+        catch (final IOException ioe)
+        {
+          // Ignore as this shouldn've been handled eariler
+        }
+      }
+
+      FutureResult<?> future;
+      AsynchronousConnection connection;
+      R handler;
+
+      final double targetTimeInMS =
+        (1.0 / (targetThroughput / (numThreads * numConnections))) * 1000.0;
+      double sleepTimeInMS = 0;
+      long start;
+      while (!stopRequested && !(maxIterations > 0 && count >= maxIterations))
+      {
+        start = System.nanoTime();
+        handler = getHandler(start);
+
+        if (this.connection == null)
+        {
+          try
+          {
+            connection = connectionFactory.getAsynchronousConnection(null)
+                .get();
+          }
+          catch (final InterruptedException e)
+          {
+            // Ignore and check stop requested
+            continue;
+          }
+          catch (final ErrorResultException e)
+          {
+            app.println(LocalizableMessage.raw(e.getResult()
+                .getDiagnosticMessage()));
+            if (e.getCause() != null && app.isVerbose())
+            {
+              e.getCause().printStackTrace(app.getErrorStream());
+            }
+            stopRequested = true;
+            break;
+          }
+        }
+        else
+        {
+          connection = this.connection;
+          if (!noRebind
+              && connection instanceof AuthenticatedAsynchronousConnection)
+          {
+            final AuthenticatedAsynchronousConnection ac =
+              (AuthenticatedAsynchronousConnection) connection;
+            try
+            {
+              ac.rebind(null).get();
+            }
+            catch (final InterruptedException e)
+            {
+              // Ignore and check stop requested
+              continue;
+            }
+            catch (final ErrorResultException e)
+            {
+              app.println(LocalizableMessage.raw(e.getResult().toString()));
+              if (e.getCause() != null && app.isVerbose())
+              {
+                e.getCause().printStackTrace(app.getErrorStream());
+              }
+              stopRequested = true;
+              break;
+            }
+          }
+        }
+        future = performOperation(connection, handler, dataSources.get());
+        operationRecentCount.getAndIncrement();
+        count++;
+        if (!isAsync)
+        {
+          try
+          {
+            future.get();
+          }
+          catch (final InterruptedException e)
+          {
+            // Ignore and check stop requested
+            continue;
+          }
+          catch (final ErrorResultException e)
+          {
+            if (e.getCause() instanceof IOException)
+            {
+              e.getCause().printStackTrace(app.getErrorStream());
+              stopRequested = true;
+              break;
+            }
+            // Ignore. Handled by result handler
+          }
+          finally
+          {
+            if (this.connection == null)
+            {
+              connection.close();
+            }
+          }
+        }
+        if (targetThroughput > 0)
+        {
+          try
+          {
+            if (sleepTimeInMS > 1)
+            {
+              sleep((long) Math.floor(sleepTimeInMS));
+            }
+          }
+          catch (final InterruptedException e)
+          {
+            continue;
+          }
+
+          sleepTimeInMS += targetTimeInMS
+              - ((System.nanoTime() - start) / 1000000.0);
+          if (sleepTimeInMS < -60000)
+          {
+            // If we fall behind by 60 seconds, just forget about
+            // catching up
+            sleepTimeInMS = -60000;
+          }
+        }
+      }
+    }
   }
 
 
@@ -781,64 +570,14 @@
 
 
 
-    public ReversableArray(int capacity)
+    public ReversableArray(final int capacity)
     {
       this.array = new long[capacity];
     }
 
 
 
-    public void set(int index, long value)
-    {
-      if (index >= size)
-      {
-        throw new IndexOutOfBoundsException();
-      }
-      if (!reversed)
-      {
-        array[index] = value;
-      }
-      else
-      {
-        array[size - index - 1] = value;
-      }
-    }
-
-
-
-    public long get(int index)
-    {
-      if (index >= size)
-      {
-        throw new IndexOutOfBoundsException();
-      }
-      if (!reversed)
-      {
-        return array[index];
-      }
-      else
-      {
-        return array[size - index - 1];
-      }
-    }
-
-
-
-    public int size()
-    {
-      return size;
-    }
-
-
-
-    public void reverse()
-    {
-      reversed = !reversed;
-    }
-
-
-
-    public void append(long value)
+    public void append(final long value)
     {
       if (size == array.length)
       {
@@ -859,7 +598,7 @@
 
 
 
-    public void append(ReversableArray a, int length)
+    public void append(final ReversableArray a, final int length)
     {
       if (length > a.size() || length > remaining())
       {
@@ -879,13 +618,6 @@
 
 
 
-    public int remaining()
-    {
-      return array.length - size;
-    }
-
-
-
     public void clear()
     {
       size = 0;
@@ -893,7 +625,57 @@
 
 
 
-    public void siftDown(int start, int end)
+    public long get(final int index)
+    {
+      if (index >= size)
+      {
+        throw new IndexOutOfBoundsException();
+      }
+      if (!reversed)
+      {
+        return array[index];
+      }
+      else
+      {
+        return array[size - index - 1];
+      }
+    }
+
+
+
+    public int remaining()
+    {
+      return array.length - size;
+    }
+
+
+
+    public void reverse()
+    {
+      reversed = !reversed;
+    }
+
+
+
+    public void set(final int index, final long value)
+    {
+      if (index >= size)
+      {
+        throw new IndexOutOfBoundsException();
+      }
+      if (!reversed)
+      {
+        array[index] = value;
+      }
+      else
+      {
+        array[size - index - 1] = value;
+      }
+    }
+
+
+
+    public void siftDown(final int start, final int end)
     {
       int root = start;
       int child;
@@ -918,7 +700,7 @@
 
 
 
-    public void siftUp(int start, int end)
+    public void siftUp(final int start, final int end)
     {
       int child = end;
       int parent;
@@ -939,11 +721,297 @@
 
 
 
-    private void swap(int i, int i2)
+    public int size()
     {
-      long temp = get(i);
+      return size;
+    }
+
+
+
+    private void swap(final int i, final int i2)
+    {
+      final long temp = get(i);
       set(i, get(i2));
       set(i2, temp);
     }
   }
+
+
+
+  private static final String[] EMPTY_STRINGS = new String[0];
+
+  private final AtomicInteger operationRecentCount = new AtomicInteger();
+
+  private final AtomicInteger successRecentCount = new AtomicInteger();
+
+  private final AtomicInteger failedRecentCount = new AtomicInteger();
+
+  private final AtomicLong waitRecentTime = new AtomicLong();
+
+  private final AtomicReference<ReversableArray> eTimeBuffer = new AtomicReference<ReversableArray>(
+      new ReversableArray(100000));
+
+  private final ConsoleApplication app;
+
+  private final ThreadLocal<DataSource[]> dataSources = new ThreadLocal<DataSource[]>();
+
+  private volatile boolean stopRequested;
+
+  private int numThreads;
+
+  private int numConnections;
+
+  private int targetThroughput;
+
+  private int maxIterations;
+
+  private boolean isAsync;
+
+  private boolean noRebind;
+
+  private int statsInterval;
+
+  private final IntegerArgument numThreadsArgument;
+
+  private final IntegerArgument maxIterationsArgument;
+
+  private final IntegerArgument statsIntervalArgument;
+
+  private final IntegerArgument targetThroughputArgument;
+
+  private final IntegerArgument numConnectionsArgument;
+
+  private final IntegerArgument percentilesArgument;
+
+  private final BooleanArgument keepConnectionsOpen;
+
+  private final BooleanArgument noRebindArgument;
+
+  private final BooleanArgument asyncArgument;
+
+  private final StringArgument arguments;
+
+
+
+  PerformanceRunner(final ArgumentParser argParser, final ConsoleApplication app)
+      throws ArgumentException
+  {
+    this.app = app;
+    numThreadsArgument = new IntegerArgument("numThreads", 't', "numThreads",
+        false, false, true, LocalizableMessage.raw("{numThreads}"), 1, null,
+        true, 1, false, 0, LocalizableMessage
+            .raw("number of search threads per connection"));
+    numThreadsArgument.setPropertyName("numThreads");
+    argParser.addArgument(numThreadsArgument);
+
+    numConnectionsArgument = new IntegerArgument("numConnections", 'c',
+        "numConnections", false, false, true, LocalizableMessage
+            .raw("{numConnections}"), 1, null, true, 1, false, 0,
+        LocalizableMessage.raw("number of connections"));
+    numThreadsArgument.setPropertyName("numConnections");
+    argParser.addArgument(numConnectionsArgument);
+
+    maxIterationsArgument = new IntegerArgument("maxIterations", 'm',
+        "maxIterations", false, false, true, LocalizableMessage
+            .raw("{maxIterations}"), 0, null, LocalizableMessage
+            .raw("max searches per thread, 0 for unlimited"));
+    numThreadsArgument.setPropertyName("maxIterations");
+    argParser.addArgument(maxIterationsArgument);
+
+    statsIntervalArgument = new IntegerArgument("statInterval", 'i',
+        "statInterval", false, false, true, LocalizableMessage
+            .raw("{statInterval}"), 5, null, true, 1, false, 0,
+        LocalizableMessage
+            .raw("Display results each specified number of seconds"));
+    numThreadsArgument.setPropertyName("statInterval");
+    argParser.addArgument(statsIntervalArgument);
+
+    targetThroughputArgument = new IntegerArgument("targetThroughput", 'M',
+        "targetThroughput", false, false, true, LocalizableMessage
+            .raw("{targetThroughput}"), 0, null, LocalizableMessage
+            .raw("Target average throughput to achieve"));
+    targetThroughputArgument.setPropertyName("targetThroughput");
+    argParser.addArgument(targetThroughputArgument);
+
+    percentilesArgument = new IntegerArgument("percentile", 'e', "percentile",
+        false, true, LocalizableMessage.raw("{percentile}"), true, 50, true,
+        100, LocalizableMessage.raw("Calculate max response time for a "
+            + "percentile of operations"));
+    percentilesArgument.setPropertyName("percentile");
+    argParser.addArgument(percentilesArgument);
+
+    keepConnectionsOpen = new BooleanArgument("keepConnectionsOpen", 'f',
+        "keepConnectionsOpen", LocalizableMessage.raw("keep connections open"));
+    keepConnectionsOpen.setPropertyName("keepConnectionsOpen");
+    argParser.addArgument(keepConnectionsOpen);
+
+    noRebindArgument = new BooleanArgument("noRebind", 'F', "noRebind",
+        LocalizableMessage.raw("keep connections open and don't rebind"));
+    keepConnectionsOpen.setPropertyName("noRebind");
+    argParser.addArgument(noRebindArgument);
+
+    asyncArgument = new BooleanArgument("asynchronous", 'A', "asynchronous",
+        LocalizableMessage.raw("asynch, don't wait for results"));
+    keepConnectionsOpen.setPropertyName("asynchronous");
+    argParser.addArgument(asyncArgument);
+
+    arguments = new StringArgument("arguments", 'g', "arguments", false, true,
+        true, LocalizableMessage.raw("{arguments}"), null, null,
+        LocalizableMessage
+            .raw("arguments for variables in the filter and/or base DN"));
+    arguments.setPropertyName("arguments");
+    argParser.addArgument(arguments);
+  }
+
+
+
+  public void connectionClosed()
+  {
+    // Ignore
+  }
+
+
+
+  public synchronized void connectionErrorOccurred(
+      final boolean isDisconnectNotification, final ErrorResultException error)
+  {
+    if (!stopRequested)
+    {
+      app.println(LocalizableMessage.raw("Error occurred on one or more "
+          + "connections: " + error.getResult().toString()));
+      if (error.getCause() != null && app.isVerbose())
+      {
+        error.getCause().printStackTrace(app.getErrorStream());
+      }
+      stopRequested = true;
+    }
+  }
+
+
+
+  public void connectionReceivedUnsolicitedNotification(
+      final ExtendedResult notification)
+  {
+    // Ignore
+  }
+
+
+
+  public void validate() throws ArgumentException
+  {
+    numConnections = numConnectionsArgument.getIntValue();
+    numThreads = numThreadsArgument.getIntValue();
+    maxIterations = maxIterationsArgument.getIntValue();
+    statsInterval = statsIntervalArgument.getIntValue() * 1000;
+    targetThroughput = targetThroughputArgument.getIntValue();
+
+    isAsync = asyncArgument.isPresent();
+    noRebind = noRebindArgument.isPresent();
+
+    if (!noRebindArgument.isPresent() && this.numThreads > 1)
+    {
+      throw new ArgumentException(LocalizableMessage.raw("--"
+          + noRebindArgument.getLongIdentifier() + " must be used if --"
+          + numThreadsArgument.getLongIdentifier() + " is > 1"));
+    }
+
+    if (!noRebindArgument.isPresent() && asyncArgument.isPresent())
+    {
+      throw new ArgumentException(LocalizableMessage.raw("--"
+          + noRebindArgument.getLongIdentifier()
+          + " must be used when using --" + asyncArgument.getLongIdentifier()));
+    }
+
+    try
+    {
+      DataSource.parse(arguments.getValues());
+    }
+    catch (final IOException ioe)
+    {
+      throw new ArgumentException(LocalizableMessage
+          .raw("Error occured while parsing arguments: " + ioe.toString()));
+    }
+  }
+
+
+
+  final DataSource[] getDataSources()
+  {
+    try
+    {
+      return DataSource.parse(arguments.getValues());
+    }
+    catch (final IOException ioe)
+    {
+      // Ignore as this shouldn've been handled eariler
+    }
+    return new DataSource[0];
+  }
+
+
+
+  abstract StatsThread newStatsThread();
+
+
+
+  abstract WorkerThread<?> newWorkerThread(AsynchronousConnection connection,
+      ConnectionFactory connectionFactory);
+
+
+
+  final int run(final ConnectionFactory connectionFactory)
+  {
+    final List<Thread> threads = new ArrayList<Thread>();
+    final List<AsynchronousConnection> connections = new ArrayList<AsynchronousConnection>();
+
+    AsynchronousConnection connection = null;
+    Thread thread;
+    try
+    {
+      for (int i = 0; i < numConnections; i++)
+      {
+        if (keepConnectionsOpen.isPresent() || noRebindArgument.isPresent())
+        {
+          connection = connectionFactory.getAsynchronousConnection(null).get();
+          connection.addConnectionEventListener(this);
+          connections.add(connection);
+        }
+        for (int j = 0; j < numThreads; j++)
+        {
+          thread = newWorkerThread(connection, connectionFactory);
+
+          threads.add(thread);
+          thread.start();
+        }
+      }
+
+      final Thread statsThread = newStatsThread();
+      statsThread.start();
+
+      for (final Thread t : threads)
+      {
+        t.join();
+      }
+      stopRequested = true;
+      statsThread.join();
+    }
+    catch (final InterruptedException e)
+    {
+      stopRequested = true;
+    }
+    catch (final ErrorResultException e)
+    {
+      stopRequested = true;
+      app.println(LocalizableMessage.raw(e.getResult().getDiagnosticMessage()));
+    }
+    finally
+    {
+      for (final AsynchronousConnection c : connections)
+      {
+        c.close();
+      }
+    }
+
+    return 0;
+  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/PromptingTrustManager.java b/sdk/src/com/sun/opends/sdk/tools/PromptingTrustManager.java
index ec74304..2274f92 100644
--- a/sdk/src/com/sun/opends/sdk/tools/PromptingTrustManager.java
+++ b/sdk/src/com/sun/opends/sdk/tools/PromptingTrustManager.java
@@ -57,22 +57,11 @@
 
 
 /**
- * A trust manager which prompts the user for the length of time that
- * they would like to trust a server certificate.
+ * A trust manager which prompts the user for the length of time that they would
+ * like to trust a server certificate.
  */
 final class PromptingTrustManager implements X509TrustManager
 {
-  static private final Logger LOG = Logger
-      .getLogger(PromptingTrustManager.class.getName());
-
-  static private final String DEFAULT_PATH = System
-      .getProperty("user.home")
-      + File.separator + ".opends" + File.separator + "keystore";
-
-  static private final char[] DEFAULT_PASSWORD = "OpenDS".toCharArray();
-
-
-
   /**
    * Enumeration description server certificate trust option.
    */
@@ -97,7 +86,7 @@
      * @param msg
      *          the message message.
      */
-    private TrustOption(int i, LocalizableMessage msg)
+    private TrustOption(final int i, final LocalizableMessage msg)
     {
       choice = i;
       this.msg = msg;
@@ -130,6 +119,14 @@
 
 
 
+  static private final Logger LOG = Logger
+      .getLogger(PromptingTrustManager.class.getName());
+
+  static private final String DEFAULT_PATH = System.getProperty("user.home")
+      + File.separator + ".opends" + File.separator + "keystore";
+
+  static private final char[] DEFAULT_PASSWORD = "OpenDS".toCharArray();
+
   private final KeyStore inMemoryTrustStore;
 
   private final KeyStore onDiskTrustStore;
@@ -144,28 +141,18 @@
 
 
 
-  PromptingTrustManager(ConsoleApplication app,
-      X509TrustManager sourceTrustManager) throws KeyStoreException,
-      IOException, NoSuchAlgorithmException, CertificateException
-  {
-    this(app, DEFAULT_PATH, sourceTrustManager);
-  }
-
-
-
-  PromptingTrustManager(ConsoleApplication app,
-      String acceptedStorePath, X509TrustManager sourceTrustManager)
+  PromptingTrustManager(final ConsoleApplication app,
+      final String acceptedStorePath, final X509TrustManager sourceTrustManager)
       throws KeyStoreException, IOException, NoSuchAlgorithmException,
       CertificateException
   {
     Validator.ensureNotNull(app, acceptedStorePath);
     this.app = app;
     this.nestedTrustManager = sourceTrustManager;
-    inMemoryTrustStore = KeyStore
-        .getInstance(KeyStore.getDefaultType());
+    inMemoryTrustStore = KeyStore.getInstance(KeyStore.getDefaultType());
     onDiskTrustStore = KeyStore.getInstance(KeyStore.getDefaultType());
 
-    File onDiskTrustStorePath = new File(acceptedStorePath);
+    final File onDiskTrustStorePath = new File(acceptedStorePath);
     inMemoryTrustStore.load(null, null);
     if (!onDiskTrustStorePath.exists())
     {
@@ -173,15 +160,15 @@
     }
     else
     {
-      FileInputStream fos = new FileInputStream(onDiskTrustStorePath);
+      final FileInputStream fos = new FileInputStream(onDiskTrustStorePath);
       onDiskTrustStore.load(fos, DEFAULT_PASSWORD);
     }
-    TrustManagerFactory tmf = TrustManagerFactory
+    final TrustManagerFactory tmf = TrustManagerFactory
         .getInstance(TrustManagerFactory.getDefaultAlgorithm());
 
     tmf.init(inMemoryTrustStore);
     X509TrustManager x509tm = null;
-    for (TrustManager tm : tmf.getTrustManagers())
+    for (final TrustManager tm : tmf.getTrustManagers())
     {
       if (tm instanceof X509TrustManager)
       {
@@ -197,7 +184,7 @@
 
     tmf.init(onDiskTrustStore);
     x509tm = null;
-    for (TrustManager tm : tmf.getTrustManagers())
+    for (final TrustManager tm : tmf.getTrustManagers())
     {
       if (tm instanceof X509TrustManager)
       {
@@ -214,20 +201,29 @@
 
 
 
-  public void checkClientTrusted(X509Certificate[] x509Certificates,
-      String s) throws CertificateException
+  PromptingTrustManager(final ConsoleApplication app,
+      final X509TrustManager sourceTrustManager) throws KeyStoreException,
+      IOException, NoSuchAlgorithmException, CertificateException
+  {
+    this(app, DEFAULT_PATH, sourceTrustManager);
+  }
+
+
+
+  public void checkClientTrusted(final X509Certificate[] x509Certificates,
+      final String s) throws CertificateException
   {
     try
     {
       inMemoryTrustManager.checkClientTrusted(x509Certificates, s);
     }
-    catch (Exception ce1)
+    catch (final Exception ce1)
     {
       try
       {
         onDiskTrustManager.checkClientTrusted(x509Certificates, s);
       }
-      catch (Exception ce2)
+      catch (final Exception ce2)
       {
         if (nestedTrustManager != null)
         {
@@ -235,7 +231,7 @@
           {
             nestedTrustManager.checkClientTrusted(x509Certificates, s);
           }
-          catch (Exception ce3)
+          catch (final Exception ce3)
           {
             checkManuallyTrusted(x509Certificates, ce3);
           }
@@ -250,20 +246,20 @@
 
 
 
-  public void checkServerTrusted(X509Certificate[] x509Certificates,
-      String s) throws CertificateException
+  public void checkServerTrusted(final X509Certificate[] x509Certificates,
+      final String s) throws CertificateException
   {
     try
     {
       inMemoryTrustManager.checkServerTrusted(x509Certificates, s);
     }
-    catch (Exception ce1)
+    catch (final Exception ce1)
     {
       try
       {
         onDiskTrustManager.checkServerTrusted(x509Certificates, s);
       }
-      catch (Exception ce2)
+      catch (final Exception ce2)
       {
         if (nestedTrustManager != null)
         {
@@ -271,7 +267,7 @@
           {
             nestedTrustManager.checkServerTrusted(x509Certificates, s);
           }
-          catch (Exception ce3)
+          catch (final Exception ce3)
           {
             checkManuallyTrusted(x509Certificates, ce3);
           }
@@ -298,33 +294,89 @@
 
 
   /**
+   * This method is called when the user accepted a certificate.
+   *
+   * @param chain
+   *          the certificate chain accepted by the user. certificate.
+   */
+  private void acceptCertificate(final X509Certificate[] chain,
+      final boolean permanent)
+  {
+    if (permanent)
+    {
+      LOG.log(Level.INFO, "Permanently accepting certificate chain to "
+          + "truststore");
+    }
+    else
+    {
+      LOG.log(Level.INFO, "Accepting certificate chain for this session");
+    }
+
+    for (final X509Certificate aChain : chain)
+    {
+      try
+      {
+        final String alias = aChain.getSubjectDN().getName();
+        inMemoryTrustStore.setCertificateEntry(alias, aChain);
+        if (permanent)
+        {
+          onDiskTrustStore.setCertificateEntry(alias, aChain);
+        }
+      }
+      catch (final Exception e)
+      {
+        LOG.log(Level.WARNING, "Error setting certificate to store: " + e
+            + "\nCert: " + aChain.toString());
+      }
+    }
+
+    if (permanent)
+    {
+      try
+      {
+        final File truststoreFile = new File(DEFAULT_PATH);
+        if (!truststoreFile.exists())
+        {
+          createFile(truststoreFile);
+        }
+        final FileOutputStream fos = new FileOutputStream(truststoreFile);
+        onDiskTrustStore.store(fos, DEFAULT_PASSWORD);
+        fos.close();
+      }
+      catch (final Exception e)
+      {
+        LOG.log(Level.WARNING, "Error saving store to disk: " + e);
+      }
+    }
+  }
+
+
+
+  /**
    * Indicate if the certificate chain can be trusted.
    *
    * @param chain
    *          The certificate chain to validate certificate.
    */
-  private void checkManuallyTrusted(X509Certificate[] chain,
-      Exception exception) throws CertificateException
+  private void checkManuallyTrusted(final X509Certificate[] chain,
+      final Exception exception) throws CertificateException
   {
     app.println();
-    app
-        .println(INFO_LDAP_CONN_PROMPT_SECURITY_SERVER_CERTIFICATE
-            .get());
+    app.println(INFO_LDAP_CONN_PROMPT_SECURITY_SERVER_CERTIFICATE.get());
     app.println();
-    for (int i = 0; i < chain.length; i++)
+    for (final X509Certificate element : chain)
     {
       // Certificate DN
       app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_USER_DN
-          .get(chain[i].getSubjectDN().toString()));
+          .get(element.getSubjectDN().toString()));
 
       // certificate validity
-      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_VALIDITY
-          .get(chain[i].getNotBefore().toString(), chain[i]
-              .getNotAfter().toString()));
+      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_VALIDITY.get(
+          element.getNotBefore().toString(), element.getNotAfter().toString()));
 
       // certificate Issuer
-      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER
-          .get(chain[i].getIssuerDN().toString()));
+      app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER.get(element
+          .getIssuerDN().toString()));
 
       app.println();
       app.println();
@@ -334,21 +386,20 @@
     app.println(INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION.get());
     app.println();
 
-    Map<String, TrustOption> menuOptions = new HashMap<String, TrustOption>();
-    for (TrustOption t : TrustOption.values())
+    final Map<String, TrustOption> menuOptions = new HashMap<String, TrustOption>();
+    for (final TrustOption t : TrustOption.values())
     {
       menuOptions.put(t.getChoice().toString(), t);
 
-      LocalizableMessageBuilder builder = new LocalizableMessageBuilder();
+      final LocalizableMessageBuilder builder = new LocalizableMessageBuilder();
       builder.append(t.getChoice());
       builder.append(") ");
       builder.append(t.getMenuMessage());
       app.println(builder.toMessage(), 2 /* Indent options */);
     }
 
-    TrustOption defaultTrustMethod = TrustOption.SESSION;
-    LocalizableMessage promptMsg = INFO_MENU_PROMPT_SINGLE_DEFAULT
-        .get(defaultTrustMethod.getChoice().toString());
+    final TrustOption defaultTrustMethod = TrustOption.SESSION;
+    final LocalizableMessage promptMsg = INFO_MENU_PROMPT_SINGLE.get();
 
     while (true)
     {
@@ -356,10 +407,10 @@
       String choice;
       try
       {
-        choice = app.readInput(promptMsg, defaultTrustMethod
-            .getChoice().toString());
+        choice = app.readInput(promptMsg, defaultTrustMethod.getChoice()
+            .toString());
       }
-      catch (CLIException e)
+      catch (final CLIException e)
       {
         // What can we do here?
         throw new CertificateException(exception);
@@ -369,7 +420,7 @@
         app.println();
       }
 
-      TrustOption option = menuOptions.get(choice.trim());
+      final TrustOption option = menuOptions.get(choice.trim());
       if (option == null)
       {
         app.println(ERR_MENU_BAD_CHOICE_SINGLE.get());
@@ -389,11 +440,11 @@
           throw new CertificateException(exception);
         }
       case CERTIFICATE_DETAILS:
-        for (X509Certificate aChain : chain)
+        for (final X509Certificate aChain : chain)
         {
           app.println();
-          app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE
-              .get(aChain.toString()));
+          app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE.get(aChain
+              .toString()));
           app.println();
         }
         break;
@@ -407,71 +458,12 @@
 
 
 
-  /**
-   * This method is called when the user accepted a certificate.
-   *
-   * @param chain
-   *          the certificate chain accepted by the user. certificate.
-   */
-  void acceptCertificate(X509Certificate[] chain, boolean permanent)
-  {
-    if (permanent)
-    {
-      LOG.log(Level.INFO, "Permanently accepting certificate chain to "
-          + "truststore");
-    }
-    else
-    {
-      LOG.log(Level.INFO,
-          "Accepting certificate chain for this session");
-    }
-
-    for (X509Certificate aChain : chain)
-    {
-      try
-      {
-        String alias = aChain.getSubjectDN().getName();
-        inMemoryTrustStore.setCertificateEntry(alias, aChain);
-        if (permanent)
-        {
-          onDiskTrustStore.setCertificateEntry(alias, aChain);
-        }
-      }
-      catch (Exception e)
-      {
-        LOG.log(Level.WARNING, "Error setting certificate to store: "
-            + e + "\nCert: " + aChain.toString());
-      }
-    }
-
-    if (permanent)
-    {
-      try
-      {
-        File truststoreFile = new File(DEFAULT_PATH);
-        if (!truststoreFile.exists())
-        {
-          createFile(truststoreFile);
-        }
-        FileOutputStream fos = new FileOutputStream(truststoreFile);
-        onDiskTrustStore.store(fos, DEFAULT_PASSWORD);
-        fos.close();
-      }
-      catch (Exception e)
-      {
-        LOG.log(Level.WARNING, "Error saving store to disk: " + e);
-      }
-    }
-  }
-
-
-
-  private boolean createFile(File f) throws IOException
+  private boolean createFile(final File f) throws IOException
   {
     boolean success = false;
     if (f != null)
     {
-      File parent = f.getParentFile();
+      final File parent = f.getParentFile();
       if (!parent.exists())
       {
         parent.mkdirs();
diff --git a/sdk/src/com/sun/opends/sdk/tools/SearchRate.java b/sdk/src/com/sun/opends/sdk/tools/SearchRate.java
index 81b3009..830a88a 100644
--- a/sdk/src/com/sun/opends/sdk/tools/SearchRate.java
+++ b/sdk/src/com/sun/opends/sdk/tools/SearchRate.java
@@ -31,7 +31,7 @@
 
 import static com.sun.opends.sdk.messages.Messages.*;
 import static com.sun.opends.sdk.tools.ToolConstants.*;
-import static com.sun.opends.sdk.tools.Utils.*;
+import static com.sun.opends.sdk.tools.Utils.filterExitCode;
 
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -49,14 +49,167 @@
 
 
 
-
 /**
- * A load generation tool that can be used to load a Directory Server
- * with Search requests using one or more LDAP connections.
+ * A load generation tool that can be used to load a Directory Server with
+ * Search requests using one or more LDAP connections.
  */
 public final class SearchRate extends ConsoleApplication
 {
-  private BooleanArgument verbose;
+  private final class SearchPerformanceRunner extends PerformanceRunner
+  {
+    private final class SearchStatsHandler extends
+        UpdateStatsResultHandler<Result> implements SearchResultHandler
+    {
+      private SearchStatsHandler(final long eTime)
+      {
+        super(eTime);
+      }
+
+
+
+      public boolean handleEntry(final SearchResultEntry entry)
+      {
+        entryRecentCount.getAndIncrement();
+        return true;
+      }
+
+
+
+      public boolean handleReference(final SearchResultReference reference)
+      {
+        return true;
+      }
+    }
+
+
+
+    private final class SearchStatsThread extends StatsThread
+    {
+      private long totalEntryCount;
+
+      private final String[] extraColumn;
+
+
+
+      private SearchStatsThread()
+      {
+        super(new String[] { "Entries/Srch" });
+        extraColumn = new String[1];
+      }
+
+
+
+      @Override
+      String[] getAdditionalColumns()
+      {
+        final int entryCount = entryRecentCount.getAndSet(0);
+        totalEntryCount += entryCount;
+        if (successCount > 0)
+        {
+          extraColumn[0] = String.format("%.1f", (double) entryCount
+              / successCount);
+        }
+        else
+        {
+          extraColumn[0] = String.format("%.1f", 0.0);
+        }
+        return extraColumn;
+      }
+    }
+
+
+
+    private final class SearchWorkerThread extends
+        WorkerThread<SearchStatsHandler>
+    {
+      private SearchRequest sr;
+
+      private Object[] data;
+
+
+
+      private SearchWorkerThread(final AsynchronousConnection connection,
+          final ConnectionFactory connectionFactory)
+      {
+        super(connection, connectionFactory);
+      }
+
+
+
+      @Override
+      public SearchStatsHandler getHandler(final long startTime)
+      {
+        return new SearchStatsHandler(startTime);
+      }
+
+
+
+      @Override
+      public FutureResult<?> performOperation(
+          final AsynchronousConnection connection,
+          final SearchStatsHandler handler, final DataSource[] dataSources)
+      {
+        if (sr == null)
+        {
+          if (dataSources == null)
+          {
+            sr = Requests.newSearchRequest(baseDN, scope, filter, attributes);
+          }
+          else
+          {
+            data = DataSource.generateData(dataSources, data);
+            sr = Requests.newSearchRequest(String.format(baseDN, data), scope,
+                String.format(filter, data), attributes);
+          }
+          sr.setDereferenceAliasesPolicy(dereferencesAliasesPolicy);
+        }
+        else if (dataSources != null)
+        {
+          data = DataSource.generateData(dataSources, data);
+          sr.setFilter(String.format(filter, data));
+          sr.setName(String.format(baseDN, data));
+        }
+        return connection.search(sr, handler, handler);
+      }
+    }
+
+
+
+    private String filter;
+
+    private String baseDN;
+
+    private SearchScope scope;
+
+    private DereferenceAliasesPolicy dereferencesAliasesPolicy;
+
+    private String[] attributes;
+
+
+
+    private SearchPerformanceRunner(final ArgumentParser argParser,
+        final ConsoleApplication app) throws ArgumentException
+    {
+      super(argParser, app);
+    }
+
+
+
+    @Override
+    StatsThread newStatsThread()
+    {
+      return new SearchStatsThread();
+    }
+
+
+
+    @Override
+    WorkerThread<?> newWorkerThread(final AsynchronousConnection connection,
+        final ConnectionFactory connectionFactory)
+    {
+      return new SearchWorkerThread(connection, connectionFactory);
+    }
+  }
 
 
 
@@ -67,25 +220,24 @@
    *          The command-line arguments provided to this program.
    */
 
-  public static void main(String[] args)
+  public static void main(final String[] args)
   {
-    int retCode = mainSearchRate(args, System.in, System.out,
-        System.err);
+    final int retCode = mainSearchRate(args, System.in, System.out, System.err);
     System.exit(filterExitCode(retCode));
   }
 
 
 
   /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the ldapsearch tool.
+   * Parses the provided command-line arguments and uses that information to run
+   * the ldapsearch tool.
    *
    * @param args
    *          The command-line arguments provided to this program.
    * @return The error code.
    */
 
-  static int mainSearchRate(String[] args)
+  static int mainSearchRate(final String[] args)
   {
     return mainSearchRate(args, System.in, System.out, System.err);
   }
@@ -93,25 +245,25 @@
 
 
   /**
-   * Parses the provided command-line arguments and uses that
-   * information to run the ldapsearch tool.
+   * Parses the provided command-line arguments and uses that information to run
+   * the ldapsearch tool.
    *
    * @param args
    *          The command-line arguments provided to this program.
    * @param inStream
-   *          The input stream to use for standard input, or
-   *          <CODE>null</CODE> if standard input is not needed.
+   *          The input stream to use for standard input, or <CODE>null</CODE>
+   *          if standard input is not needed.
    * @param outStream
-   *          The output stream to use for standard output, or
-   *          <CODE>null</CODE> if standard output is not needed.
+   *          The output stream to use for standard output, or <CODE>null</CODE>
+   *          if standard output is not needed.
    * @param errStream
-   *          The output stream to use for standard error, or
-   *          <CODE>null</CODE> if standard error is not needed.
+   *          The output stream to use for standard error, or <CODE>null</CODE>
+   *          if standard error is not needed.
    * @return The error code.
    */
 
-  static int mainSearchRate(String[] args, InputStream inStream,
-      OutputStream outStream, OutputStream errStream)
+  static int mainSearchRate(final String[] args, final InputStream inStream,
+      final OutputStream outStream, final OutputStream errStream)
 
   {
     return new SearchRate(inStream, outStream, errStream).run(args);
@@ -119,7 +271,14 @@
 
 
 
-  private SearchRate(InputStream in, OutputStream out, OutputStream err)
+  private BooleanArgument verbose;
+
+  private final AtomicInteger entryRecentCount = new AtomicInteger();
+
+
+
+  private SearchRate(final InputStream in, final OutputStream out,
+      final OutputStream err)
   {
     super(in, out, err);
 
@@ -127,15 +286,98 @@
 
 
 
-  private int run(String[] args)
+  /**
+   * Indicates whether or not the user has requested advanced mode.
+   *
+   * @return Returns <code>true</code> if the user has requested advanced mode.
+   */
+  @Override
+  public boolean isAdvancedMode()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested interactive behavior.
+   *
+   * @return Returns <code>true</code> if the user has requested interactive
+   *         behavior.
+   */
+  @Override
+  public boolean isInteractive()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not this console application is running in its
+   * menu-driven mode. This can be used to dictate whether output should go to
+   * the error stream or not. In addition, it may also dictate whether or not
+   * sub-menus should display a cancel option as well as a quit option.
+   *
+   * @return Returns <code>true</code> if this console application is running in
+   *         its menu-driven mode.
+   */
+  @Override
+  public boolean isMenuDrivenMode()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested quiet output.
+   *
+   * @return Returns <code>true</code> if the user has requested quiet output.
+   */
+  @Override
+  public boolean isQuiet()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested script-friendly output.
+   *
+   * @return Returns <code>true</code> if the user has requested script-friendly
+   *         output.
+   */
+  @Override
+  public boolean isScriptFriendly()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * Indicates whether or not the user has requested verbose output.
+   *
+   * @return Returns <code>true</code> if the user has requested verbose output.
+   */
+  @Override
+  public boolean isVerbose()
+  {
+    return verbose.isPresent();
+  }
+
+
+
+  private int run(final String[] args)
   {
     // Create the command-line argument parser for use with this
     // program.
-    LocalizableMessage toolDescription = LocalizableMessage
-        .raw("This utility can be used to "
-            + "measure search performance");
+    final LocalizableMessage toolDescription = LocalizableMessage
+        .raw("This utility can be used to " + "measure search performance");
     // TODO: correct usage
-    ArgumentParser argParser = new ArgumentParser(SearchRate.class
+    final ArgumentParser argParser = new ArgumentParser(SearchRate.class
         .getName(), toolDescription, false, true, 1, 0,
         "[filter] [attributes ...]");
 
@@ -151,12 +393,11 @@
 
     try
     {
-      connectionFactory = new ArgumentParserConnectionFactory(
-          argParser, this);
+      connectionFactory = new ArgumentParserConnectionFactory(argParser, this);
       runner = new SearchPerformanceRunner(argParser, this);
 
-      propertiesFileArgument = new StringArgument("propertiesFilePath",
-          null, OPTION_LONG_PROP_FILE_PATH, false, false, true,
+      propertiesFileArgument = new StringArgument("propertiesFilePath", null,
+          OPTION_LONG_PROP_FILE_PATH, false, false, true,
           INFO_PROP_FILE_PATH_PLACEHOLDER.get(), null, null,
           INFO_DESCRIPTION_PROP_FILE_PATH.get());
       argParser.addArgument(propertiesFileArgument);
@@ -174,25 +415,24 @@
       argParser.setUsageArgument(showUsage, getOutputStream());
 
       baseDN = new StringArgument("baseDN", OPTION_SHORT_BASEDN,
-          OPTION_LONG_BASEDN, true, false, true,
-          INFO_BASEDN_PLACEHOLDER.get(), null, null,
-          INFO_SEARCH_DESCRIPTION_BASEDN.get());
+          OPTION_LONG_BASEDN, true, false, true, INFO_BASEDN_PLACEHOLDER.get(),
+          null, null, INFO_SEARCH_DESCRIPTION_BASEDN.get());
       baseDN.setPropertyName(OPTION_LONG_BASEDN);
       argParser.addArgument(baseDN);
 
-      searchScope = new MultiChoiceArgument<SearchScope>("searchScope",
-          's', "searchScope", false, true,
-          INFO_SEARCH_SCOPE_PLACEHOLDER.get(), SearchScope.values(),
-          false, INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE.get());
+      searchScope = new MultiChoiceArgument<SearchScope>("searchScope", 's',
+          "searchScope", false, true, INFO_SEARCH_SCOPE_PLACEHOLDER.get(),
+          SearchScope.values(), false, INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE
+              .get());
       searchScope.setPropertyName("searchScope");
       searchScope.setDefaultValue(SearchScope.WHOLE_SUBTREE);
       argParser.addArgument(searchScope);
 
       dereferencePolicy = new MultiChoiceArgument<DereferenceAliasesPolicy>(
           "derefpolicy", 'a', "dereferencePolicy", false, true,
-          INFO_DEREFERENCE_POLICE_PLACEHOLDER.get(),
-          DereferenceAliasesPolicy.values(), false,
-          INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY.get());
+          INFO_DEREFERENCE_POLICE_PLACEHOLDER.get(), DereferenceAliasesPolicy
+              .values(), false, INFO_SEARCH_DESCRIPTION_DEREFERENCE_POLICY
+              .get());
       dereferencePolicy.setPropertyName("dereferencePolicy");
       dereferencePolicy.setDefaultValue(DereferenceAliasesPolicy.NEVER);
       argParser.addArgument(dereferencePolicy);
@@ -202,9 +442,10 @@
       verbose.setPropertyName("verbose");
       argParser.addArgument(verbose);
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
+      final LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(ae
+          .getMessage());
       println(message);
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
     }
@@ -216,9 +457,10 @@
       connectionFactory.validate();
       runner.validate();
     }
-    catch (ArgumentException ae)
+    catch (final ArgumentException ae)
     {
-      LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
+      final LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(ae
+          .getMessage());
       println(message);
       println(argParser.getUsageMessage());
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -231,8 +473,8 @@
       return 0;
     }
 
-    List<String> attributes = new LinkedList<String>();
-    ArrayList<String> filterAndAttributeStrings = argParser
+    final List<String> attributes = new LinkedList<String>();
+    final ArrayList<String> filterAndAttributeStrings = argParser
         .getTrailingArguments();
     if (filterAndAttributeStrings.size() > 0)
     {
@@ -241,21 +483,19 @@
       // considered the filter, the other as attributes.
       runner.filter = filterAndAttributeStrings.remove(0);
       // The rest are attributes
-      for (String s : filterAndAttributeStrings)
+      for (final String s : filterAndAttributeStrings)
       {
         attributes.add(s);
       }
     }
-    runner.attributes = attributes
-        .toArray(new String[attributes.size()]);
+    runner.attributes = attributes.toArray(new String[attributes.size()]);
     runner.baseDN = baseDN.getValue();
     try
     {
       runner.scope = searchScope.getTypedValue();
-      runner.dereferencesAliasesPolicy = dereferencePolicy
-          .getTypedValue();
+      runner.dereferencesAliasesPolicy = dereferencePolicy.getTypedValue();
     }
-    catch (ArgumentException ex1)
+    catch (final ArgumentException ex1)
     {
       println(ex1.getMessageObject());
       return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
@@ -265,12 +505,12 @@
     {
       // Try it out to make sure the format string and data sources
       // match.
-      Object[] data = DataSource.generateData(runner.getDataSources(),
+      final Object[] data = DataSource.generateData(runner.getDataSources(),
           null);
       String.format(runner.filter, data);
       String.format(runner.baseDN, data);
     }
-    catch (Exception ex1)
+    catch (final Exception ex1)
     {
       println(LocalizableMessage.raw("Error formatting filter or base DN: "
           + ex1.toString()));
@@ -279,237 +519,4 @@
 
     return runner.run(connectionFactory);
   }
-
-
-
-  private final AtomicInteger entryRecentCount = new AtomicInteger();
-
-
-
-  private class SearchPerformanceRunner extends PerformanceRunner
-  {
-    private String filter;
-
-    private String baseDN;
-
-    private SearchScope scope;
-
-    private DereferenceAliasesPolicy dereferencesAliasesPolicy;
-
-    private String[] attributes;
-
-
-
-    private SearchPerformanceRunner(ArgumentParser argParser,
-        ConsoleApplication app) throws ArgumentException
-    {
-      super(argParser, app);
-    }
-
-
-
-    WorkerThread<?> newWorkerThread(AsynchronousConnection connection,
-        ConnectionFactory connectionFactory)
-    {
-      return new SearchWorkerThread(connection, connectionFactory);
-    }
-
-
-
-    StatsThread newStatsThread()
-    {
-      return new SearchStatsThread();
-    }
-
-
-
-    private class SearchStatsHandler extends
-        UpdateStatsResultHandler<Result> implements SearchResultHandler
-    {
-      private SearchStatsHandler(long eTime)
-      {
-        super(eTime);
-      }
-
-
-
-      public void handleEntry(SearchResultEntry entry)
-      {
-        entryRecentCount.getAndIncrement();
-      }
-
-
-
-      public void handleReference(SearchResultReference reference)
-      {
-      }
-    }
-
-
-
-    private class SearchWorkerThread extends
-        WorkerThread<SearchStatsHandler>
-    {
-      private SearchRequest sr;
-
-      private Object[] data;
-
-
-
-      private SearchWorkerThread(AsynchronousConnection connection,
-          ConnectionFactory connectionFactory)
-      {
-        super(connection, connectionFactory);
-      }
-
-
-
-      public SearchStatsHandler getHandler(long startTime)
-      {
-        return new SearchStatsHandler(startTime);
-      }
-
-
-
-      public FutureResult<?> performOperation(
-          AsynchronousConnection connection,
-          SearchStatsHandler handler, DataSource[] dataSources)
-      {
-        if (sr == null)
-        {
-          if (dataSources == null)
-          {
-            sr = Requests.newSearchRequest(baseDN, scope, filter,
-                attributes);
-          }
-          else
-          {
-            data = DataSource.generateData(dataSources, data);
-            sr = Requests.newSearchRequest(String.format(baseDN, data),
-                scope, String.format(filter, data), attributes);
-          }
-          sr.setDereferenceAliasesPolicy(dereferencesAliasesPolicy);
-        }
-        else if (dataSources != null)
-        {
-          data = DataSource.generateData(dataSources, data);
-          sr.setFilter(String.format(filter, data));
-          sr.setName(String.format(baseDN, data));
-        }
-        return connection.search(sr, handler, handler);
-      }
-    }
-
-
-
-    private class SearchStatsThread extends StatsThread
-    {
-      private long totalEntryCount;
-
-      private final String[] extraColumn;
-
-
-
-      private SearchStatsThread()
-      {
-        super(new String[] { "Entries/Srch" });
-        extraColumn = new String[1];
-      }
-
-
-
-      String[] getAdditionalColumns()
-      {
-        int entryCount = entryRecentCount.getAndSet(0);
-        totalEntryCount += entryCount;
-        extraColumn[0] = String.format("%.1f", (double) entryCount
-            / successCount);
-        return extraColumn;
-      }
-    }
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested advanced mode.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         advanced mode.
-   */
-  public boolean isAdvancedMode()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested interactive
-   * behavior.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         interactive behavior.
-   */
-  public boolean isInteractive()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not this console application is running in its
-   * menu-driven mode. This can be used to dictate whether output should
-   * go to the error stream or not. In addition, it may also dictate
-   * whether or not sub-menus should display a cancel option as well as
-   * a quit option.
-   *
-   * @return Returns <code>true</code> if this console application is
-   *         running in its menu-driven mode.
-   */
-  public boolean isMenuDrivenMode()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested quiet output.
-   *
-   * @return Returns <code>true</code> if the user has requested quiet
-   *         output.
-   */
-  public boolean isQuiet()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested script-friendly
-   * output.
-   *
-   * @return Returns <code>true</code> if the user has requested
-   *         script-friendly output.
-   */
-  public boolean isScriptFriendly()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * Indicates whether or not the user has requested verbose output.
-   *
-   * @return Returns <code>true</code> if the user has requested verbose
-   *         output.
-   */
-  public boolean isVerbose()
-  {
-    return verbose.isPresent();
-  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/SelectableCertificateKeyManager.java b/sdk/src/com/sun/opends/sdk/tools/SelectableCertificateKeyManager.java
deleted file mode 100755
index d412d7b..0000000
--- a/sdk/src/com/sun/opends/sdk/tools/SelectableCertificateKeyManager.java
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2008-2009 Sun Microsystems, Inc.
- */
-package com.sun.opends.sdk.tools;
-
-
-
-import java.net.Socket;
-import java.security.Principal;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.X509ExtendedKeyManager;
-import javax.net.ssl.X509KeyManager;
-
-
-
-/**
- * This class implements an X.509 key manager that will be used to wrap
- * an existing key manager and makes it possible to configure which
- * certificate(s) should be used for client and/or server operations.
- * The certificate selection will be based on the alias (also called the
- * nickname) of the certificate.
- */
-final class SelectableCertificateKeyManager extends
-    X509ExtendedKeyManager
-{
-  // The alias of the certificate that should be selected from the key
-  // manager.
-  private String alias;
-
-  // The key manager that is wrapped by this key manager.
-  private X509KeyManager keyManager;
-
-
-
-  /**
-   * Creates a new instance of this key manager that will wrap the
-   * provided key manager and use the certificate with the specified
-   * alias.
-   *
-   * @param keyManager
-   *          The key manager to be wrapped by this key manager.
-   * @param alias
-   *          The nickname of the certificate that should be selected
-   *          for operations involving this key manager.
-   */
-  SelectableCertificateKeyManager(X509KeyManager keyManager,
-      String alias)
-  {
-    this.keyManager = keyManager;
-    this.alias = alias;
-  }
-
-
-
-  /**
-   * Chooses the alias of the client certificate that should be used
-   * based on the provided critieria. This will either return the
-   * preferred alias configured for this key manager, or {@code null} if
-   * no client certificate with that alias is configured in the
-   * underlying key manager.
-   *
-   * @param keyType
-   *          The set of key algorithm names, ordered with the most
-   *          preferred key type first.
-   * @param issuers
-   *          The list of acceptable issuer subject names, or {@code
-   *          null} if any issuer may be used.
-   * @param socket
-   *          The socket to be used for this connection.
-   * @return The alias configured for this key manager, or {@code null}
-   *         if no such client certificate is available with that alias.
-   */
-  public String chooseClientAlias(String[] keyType,
-      Principal[] issuers, Socket socket)
-  {
-    for (String type : keyType)
-    {
-      String[] clientAliases = keyManager.getClientAliases(type,
-          issuers);
-      if (clientAliases != null)
-      {
-        for (String clientAlias : clientAliases)
-        {
-          if (clientAlias.equals(alias))
-          {
-            return alias;
-          }
-        }
-      }
-    }
-
-    return null;
-  }
-
-
-
-  /**
-   * Chooses the alias of the client certificate that should be used
-   * based on the provided critieria. This will either return the
-   * preferred alias configured for this key manager, or {@code null} if
-   * no client certificate with that alias is configured in the
-   * underlying key manager.
-   *
-   * @param keyType
-   *          The set of key algorithm names, ordered with the most
-   *          preferred key type first.
-   * @param issuers
-   *          The list of acceptable issuer subject names, or {@code
-   *          null} if any issuer may be used.
-   * @param engine
-   *          The SSL engine to be used for this connection.
-   * @return The alias configured for this key manager, or {@code null}
-   *         if no such client certificate is available with that alias.
-   */
-  public String chooseEngineClientAlias(String[] keyType,
-      Principal[] issuers, SSLEngine engine)
-  {
-    for (String type : keyType)
-    {
-      String[] clientAliases = keyManager.getClientAliases(type,
-          issuers);
-      if (clientAliases != null)
-      {
-        for (String clientAlias : clientAliases)
-        {
-          if (clientAlias.equals(alias))
-          {
-            return alias;
-          }
-        }
-      }
-    }
-
-    return null;
-  }
-
-
-
-  /**
-   * Chooses the alias of the server certificate that should be used
-   * based on the provided critieria. This will either return the
-   * preferred alias configured for this key manager, or {@code null} if
-   * no server certificate with that alias is configured in the
-   * underlying key manager.
-   *
-   * @param keyType
-   *          The public key type for the certificate.
-   * @param issuers
-   *          The list of acceptable issuer subject names, or {@code
-   *          null} if any issuer may be used.
-   * @param socket
-   *          The socket to be used for this connection.
-   * @return The alias configured for this key manager, or {@code null}
-   *         if no such server certificate is available with that alias.
-   */
-  public String chooseServerAlias(String keyType, Principal[] issuers,
-      Socket socket)
-  {
-    String[] serverAliases = keyManager.getServerAliases(keyType,
-        issuers);
-    if (serverAliases != null)
-    {
-      for (String serverAlias : serverAliases)
-      {
-        if (serverAlias.equals(alias))
-        {
-          return alias;
-        }
-      }
-    }
-
-    return null;
-  }
-
-
-
-  /**
-   * Chooses the alias of the server certificate that should be used
-   * based on the provided critieria. This will either return the
-   * preferred alias configured for this key manager, or {@code null} if
-   * no server certificate with that alias is configured in the
-   * underlying key manager. Note that the returned alias can be
-   * transformed in lowercase, depending on the KeyStore implementation.
-   * It is recommended not to use aliases in a KeyStore that only differ
-   * in case.
-   *
-   * @param keyType
-   *          The public key type for the certificate.
-   * @param issuers
-   *          The list of acceptable issuer subject names, or {@code
-   *          null} if any issuer may be used.
-   * @param engine
-   *          The SSL engine to be used for this connection.
-   * @return The alias configured for this key manager, or {@code null}
-   *         if no such server certificate is available with that alias.
-   */
-  public String chooseEngineServerAlias(String keyType,
-      Principal[] issuers, SSLEngine engine)
-  {
-    String[] serverAliases = keyManager.getServerAliases(keyType,
-        issuers);
-    if (serverAliases != null)
-    {
-      for (String serverAlias : serverAliases)
-      {
-        if (serverAlias.equalsIgnoreCase(alias))
-        {
-          return serverAlias;
-        }
-      }
-    }
-
-    return null;
-  }
-
-
-
-  /**
-   * Retrieves the certificate chain for the provided alias.
-   *
-   * @param alias
-   *          The alias for the certificate chain to retrieve.
-   * @return The certificate chain for the provided alias, or {@code
-   *         null} if no certificate is associated with the provided
-   *         alias.
-   */
-  public X509Certificate[] getCertificateChain(String alias)
-  {
-    return keyManager.getCertificateChain(alias);
-  }
-
-
-
-  /**
-   * Retrieves the set of certificate aliases that may be used for
-   * client authentication with the given public key type and set of
-   * issuers.
-   *
-   * @param keyType
-   *          The public key type for the aliases to retrieve.
-   * @param issuers
-   *          The list of acceptable issuer subject names, or {@code
-   *          null} if any issuer may be used.
-   * @return The set of certificate aliases that may be used for client
-   *         authentication with the given public key type and set of
-   *         issuers, or {@code null} if there were none.
-   */
-  public String[] getClientAliases(String keyType, Principal[] issuers)
-  {
-    return keyManager.getClientAliases(keyType, issuers);
-  }
-
-
-
-  /**
-   * Retrieves the private key for the provided alias.
-   *
-   * @param alias
-   *          The alias for the private key to return.
-   * @return The private key for the provided alias, or {@code null} if
-   *         no private key is available for the provided alias.
-   */
-  public PrivateKey getPrivateKey(String alias)
-  {
-    return keyManager.getPrivateKey(alias);
-  }
-
-
-
-  /**
-   * Retrieves the set of certificate aliases that may be used for
-   * server authentication with the given public key type and set of
-   * issuers.
-   *
-   * @param keyType
-   *          The public key type for the aliases to retrieve.
-   * @param issuers
-   *          The list of acceptable issuer subject names, or {@code
-   *          null} if any issuer may be used.
-   * @return The set of certificate aliases that may be used for server
-   *         authentication with the given public key type and set of
-   *         issuers, or {@code null} if there were none.
-   */
-  public String[] getServerAliases(String keyType, Principal[] issuers)
-  {
-    return keyManager.getServerAliases(keyType, issuers);
-  }
-}
diff --git a/sdk/src/com/sun/opends/sdk/tools/StringArgument.java b/sdk/src/com/sun/opends/sdk/tools/StringArgument.java
index 832ec24..0c07572 100644
--- a/sdk/src/com/sun/opends/sdk/tools/StringArgument.java
+++ b/sdk/src/com/sun/opends/sdk/tools/StringArgument.java
@@ -34,97 +34,93 @@
 
 
 /**
- * This class defines an argument type that will accept any string
- * value.
+ * This class defines an argument type that will accept any string value.
  */
 final class StringArgument extends Argument
 {
   /**
    * Creates a new string argument with the provided information.
-   * 
+   *
    * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
+   *          The generic name that should be used to refer to this argument.
    * @param shortIdentifier
    *          The single-character identifier for this argument, or
    *          <CODE>null</CODE> if there is none.
    * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
    * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
+   *          Indicates whether this argument must be specified on the command
+   *          line.
+   * @param isMultiValued
+   *          Indicates whether this argument may be specified more than once to
+   *          provide multiple values.
    * @param needsValue
    *          Indicates whether this argument requires a value.
    * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
+   * @param defaultValue
+   *          The default value that should be used for this argument if none is
+   *          provided in a properties file or on the command line. This may be
+   *          <CODE>null</CODE> if there is no generic default.
+   * @param propertyName
+   *          The name of the property in a property file that may be used to
+   *          override the default value but will be overridden by a
+   *          command-line argument.
    * @param description
    *          LocalizableMessage for the description of this argument.
    * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
    */
-  public StringArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean needsValue,
-      LocalizableMessage valuePlaceholder, LocalizableMessage description)
+  public StringArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final boolean isMultiValued, final boolean needsValue,
+      final LocalizableMessage valuePlaceholder, final String defaultValue,
+      final String propertyName, final LocalizableMessage description)
       throws ArgumentException
   {
-    super(name, shortIdentifier, longIdentifier, isRequired, false,
-        needsValue, valuePlaceholder, null, null, description);
+    super(name, shortIdentifier, longIdentifier, isRequired, isMultiValued,
+        needsValue, valuePlaceholder, defaultValue, propertyName, description);
   }
 
 
 
   /**
    * Creates a new string argument with the provided information.
-   * 
+   *
    * @param name
-   *          The generic name that should be used to refer to this
-   *          argument.
+   *          The generic name that should be used to refer to this argument.
    * @param shortIdentifier
    *          The single-character identifier for this argument, or
    *          <CODE>null</CODE> if there is none.
    * @param longIdentifier
-   *          The long identifier for this argument, or
-   *          <CODE>null</CODE> if there is none.
+   *          The long identifier for this argument, or <CODE>null</CODE> if
+   *          there is none.
    * @param isRequired
-   *          Indicates whether this argument must be specified on the
-   *          command line.
-   * @param isMultiValued
-   *          Indicates whether this argument may be specified more than
-   *          once to provide multiple values.
+   *          Indicates whether this argument must be specified on the command
+   *          line.
    * @param needsValue
    *          Indicates whether this argument requires a value.
    * @param valuePlaceholder
-   *          The placeholder for the argument value that will be
-   *          displayed in usage information, or <CODE>null</CODE> if
-   *          this argument does not require a value.
-   * @param defaultValue
-   *          The default value that should be used for this argument if
-   *          none is provided in a properties file or on the command
-   *          line. This may be <CODE>null</CODE> if there is no generic
-   *          default.
-   * @param propertyName
-   *          The name of the property in a property file that may be
-   *          used to override the default value but will be overridden
-   *          by a command-line argument.
+   *          The placeholder for the argument value that will be displayed in
+   *          usage information, or <CODE>null</CODE> if this argument does not
+   *          require a value.
    * @param description
    *          LocalizableMessage for the description of this argument.
    * @throws ArgumentException
-   *           If there is a problem with any of the parameters used to
-   *           create this argument.
+   *           If there is a problem with any of the parameters used to create
+   *           this argument.
    */
-  public StringArgument(String name, Character shortIdentifier,
-      String longIdentifier, boolean isRequired, boolean isMultiValued,
-      boolean needsValue, LocalizableMessage valuePlaceholder,
-      String defaultValue, String propertyName, LocalizableMessage description)
-      throws ArgumentException
+  public StringArgument(final String name, final Character shortIdentifier,
+      final String longIdentifier, final boolean isRequired,
+      final boolean needsValue, final LocalizableMessage valuePlaceholder,
+      final LocalizableMessage description) throws ArgumentException
   {
-    super(name, shortIdentifier, longIdentifier, isRequired,
-        isMultiValued, needsValue, valuePlaceholder, defaultValue,
-        propertyName, description);
+    super(name, shortIdentifier, longIdentifier, isRequired, false, needsValue,
+        valuePlaceholder, null, null, description);
   }
 
 
@@ -132,17 +128,18 @@
   /**
    * Indicates whether the provided value is acceptable for use in this
    * argument.
-   * 
+   *
    * @param valueString
    *          The value for which to make the determination.
    * @param invalidReason
-   *          A buffer into which the invalid reason may be written if
-   *          the value is not acceptable.
-   * @return <CODE>true</CODE> if the value is acceptable, or
-   *         <CODE>false</CODE> if it is not.
+   *          A buffer into which the invalid reason may be written if the value
+   *          is not acceptable.
+   * @return <CODE>true</CODE> if the value is acceptable, or <CODE>false</CODE>
+   *         if it is not.
    */
-  public boolean valueIsAcceptable(String valueString,
-      LocalizableMessageBuilder invalidReason)
+  @Override
+  public boolean valueIsAcceptable(final String valueString,
+      final LocalizableMessageBuilder invalidReason)
   {
     // All values will be acceptable for this argument.
     return true;
diff --git a/sdk/src/com/sun/opends/sdk/tools/ToolConstants.java b/sdk/src/com/sun/opends/sdk/tools/ToolConstants.java
index 54b9c87..b62fd4a 100755
--- a/sdk/src/com/sun/opends/sdk/tools/ToolConstants.java
+++ b/sdk/src/com/sun/opends/sdk/tools/ToolConstants.java
@@ -26,20 +26,14 @@
  */
 package com.sun.opends.sdk.tools;
 
+
+
 /**
- * This class defines a number of constants used in one or more
- * Directory Server tools.
+ * This class defines a number of constants used in one or more Directory Server
+ * tools.
  */
 final class ToolConstants
 {
-  // Prevent instantiation.
-  private ToolConstants()
-  {
-
-  }
-
-
-
   /**
    * The name of the SASL property that can be used to provide the
    * authentication ID for the bind.
@@ -47,38 +41,38 @@
   static final String SASL_PROPERTY_AUTHID = "authid";
 
   /**
-   * The name of the SASL property that can be used to provide the
-   * authorization ID for the bind.
+   * The name of the SASL property that can be used to provide the authorization
+   * ID for the bind.
    */
   static final String SASL_PROPERTY_AUTHZID = "authzid";
 
   /**
-   * The name of the SASL property that can be used to provide the
-   * digest URI for the bind.
+   * The name of the SASL property that can be used to provide the digest URI
+   * for the bind.
    */
   static final String SASL_PROPERTY_DIGEST_URI = "digest-uri";
 
   /**
-   * The name of the SASL property that can be used to provide the KDC
-   * for use in Kerberos authentication.
+   * The name of the SASL property that can be used to provide the KDC for use
+   * in Kerberos authentication.
    */
   static final String SASL_PROPERTY_KDC = "kdc";
 
   /**
-   * The name of the SASL property that can be used to provide the
-   * quality of protection for the bind.
+   * The name of the SASL property that can be used to provide the quality of
+   * protection for the bind.
    */
   static final String SASL_PROPERTY_QOP = "qop";
 
   /**
-   * The name of the SASL property that can be used to provide the realm
-   * for the bind.
+   * The name of the SASL property that can be used to provide the realm for the
+   * bind.
    */
   static final String SASL_PROPERTY_REALM = "realm";
 
   /**
-   * The name of the SASL property that can be used to provide trace
-   * information for a SASL ANONYMOUS request.
+   * The name of the SASL property that can be used to provide trace information
+   * for a SASL ANONYMOUS request.
    */
   static final String SASL_PROPERTY_TRACE = "trace";
 
@@ -89,8 +83,7 @@
   static final String SASL_PROPERTY_MECH = "mech";
 
   /**
-   * The name of the opends configuration direction in the user home
-   * directory.
+   * The name of the opends configuration direction in the user home directory.
    */
   static final String DEFAULT_OPENDS_CONFIG_DIR = ".opends";
 
@@ -380,14 +373,13 @@
   static final String OPTION_LONG_EFFECTIVERIGHTSUSER = "getEffectiveRightsAuthzid";
 
   /**
-   * The value for the short option geteffectiveights control
-   * attributes.
+   * The value for the short option geteffectiveights control attributes.
    */
   static final char OPTION_SHORT_EFFECTIVERIGHTSATTR = 'e';
 
   /**
-   * The value for the long option geteffectiverights control specific
-   * attribute list.
+   * The value for the long option geteffectiverights control specific attribute
+   * list.
    */
   static final String OPTION_LONG_EFFECTIVERIGHTSATTR = "getEffectiveRightsAttribute";
 
@@ -611,4 +603,12 @@
    */
   static final String LIST_TABLE_SEPARATOR = ":";
 
+
+
+  // Prevent instantiation.
+  private ToolConstants()
+  {
+
+  }
+
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/TrustAllTrustManager.java b/sdk/src/com/sun/opends/sdk/tools/TrustAllTrustManager.java
deleted file mode 100644
index 5facfc5..0000000
--- a/sdk/src/com/sun/opends/sdk/tools/TrustAllTrustManager.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2008 Sun Microsystems, Inc.
- */
-
-package com.sun.opends.sdk.tools;
-
-
-
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-
-import javax.net.ssl.X509TrustManager;
-
-
-
-/**
- * An X509TrustManager which trusts everything.
- */
-final class TrustAllTrustManager implements X509TrustManager
-{
-
-  /**
-   * {@inheritDoc}
-   */
-  public void checkClientTrusted(X509Certificate[] chain,
-      String authType) throws CertificateException
-  {
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public void checkServerTrusted(X509Certificate[] chain,
-      String authType) throws CertificateException
-  {
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public X509Certificate[] getAcceptedIssuers()
-  {
-    return new X509Certificate[0];
-  }
-}
diff --git a/sdk/src/com/sun/opends/sdk/tools/TrustStoreTrustManager.java b/sdk/src/com/sun/opends/sdk/tools/TrustStoreTrustManager.java
deleted file mode 100644
index fe4525d..0000000
--- a/sdk/src/com/sun/opends/sdk/tools/TrustStoreTrustManager.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2008-2009 Sun Microsystems, Inc.
- *      Portions Copyright 2009 Parametric Technology Corporation (PTC)
- */
-
-package com.sun.opends.sdk.tools;
-
-
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.security.cert.CertificateExpiredException;
-import java.security.cert.CertificateNotYetValidException;
-import java.security.cert.X509Certificate;
-import java.util.Date;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
-
-import org.opends.sdk.DN;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class is in charge of checking whether the certificates that are
- * presented are trusted or not. This implementation tries to check also
- * that the subject DN of the certificate corresponds to the host passed
- * using the setHostName method. This implementation also checks to make
- * sure the certificate is in the validity period. The constructor tries
- * to use a default TrustManager from the system and if it cannot be
- * retrieved this class will only accept the certificates explicitly
- * accepted by the user (and specified by calling acceptCertificate).
- */
-class TrustStoreTrustManager implements X509TrustManager
-{
-  static private final Logger LOG = Logger
-      .getLogger(TrustStoreTrustManager.class.getName());
-
-  private final X509TrustManager trustManager;
-
-  private final KeyStore truststore;
-
-  private final File truststoreFile;
-
-  private final char[] truststorePassword;
-
-  private final String hostname;
-
-
-
-  /**
-   * The default constructor.
-   */
-  TrustStoreTrustManager(String truststorePath,
-      String truststorePassword, String hostname,
-      boolean checkValidityDates) throws KeyStoreException,
-      IOException, NoSuchAlgorithmException, CertificateException
-  {
-    Validator.ensureNotNull(truststorePath);
-    this.truststoreFile = new File(truststorePath);
-    if (truststorePassword != null)
-    {
-      this.truststorePassword = truststorePassword.toCharArray();
-    }
-    else
-    {
-      this.truststorePassword = null;
-    }
-    truststore = KeyStore.getInstance(KeyStore.getDefaultType());
-
-    FileInputStream fos = new FileInputStream(truststoreFile);
-    truststore.load(fos, this.truststorePassword);
-    TrustManagerFactory tmf = TrustManagerFactory
-        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
-
-    tmf.init(truststore);
-    X509TrustManager x509tm = null;
-    for (TrustManager tm : tmf.getTrustManagers())
-    {
-      if (tm instanceof X509TrustManager)
-      {
-        x509tm = (X509TrustManager) tm;
-        break;
-      }
-    }
-    if (x509tm == null)
-    {
-      throw new NoSuchAlgorithmException();
-    }
-    this.trustManager = x509tm;
-    this.hostname = hostname;
-    // this.checkValidityDates = checkValidityDates;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public void checkClientTrusted(X509Certificate[] chain,
-      String authType) throws CertificateException
-  {
-    verifyExpiration(chain);
-    verifyHostName(chain);
-    trustManager.checkClientTrusted(chain, authType);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public void checkServerTrusted(X509Certificate[] chain,
-      String authType) throws CertificateException
-  {
-    verifyExpiration(chain);
-    verifyHostName(chain);
-    trustManager.checkClientTrusted(chain, authType);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public X509Certificate[] getAcceptedIssuers()
-  {
-    if (trustManager != null)
-    {
-      return trustManager.getAcceptedIssuers();
-    }
-    else
-    {
-      return new X509Certificate[0];
-    }
-  }
-
-
-
-  private void verifyExpiration(X509Certificate[] chain)
-      throws CertificateException
-  {
-    Date currentDate = new Date();
-    for (X509Certificate c : chain)
-    {
-      try
-      {
-        c.checkValidity(currentDate);
-      }
-      catch (CertificateExpiredException cee)
-      {
-        LOG.log(Level.WARNING, "Refusing to trust security"
-            + " certificate \"" + c.getSubjectDN().getName()
-            + "\" because it" + " expired on "
-            + String.valueOf(c.getNotAfter()));
-
-        throw cee;
-      }
-      catch (CertificateNotYetValidException cnyve)
-      {
-        LOG.log(Level.WARNING, "Refusing to trust security"
-            + " certificate \"" + c.getSubjectDN().getName()
-            + "\" because it" + " is not valid until "
-            + String.valueOf(c.getNotBefore()));
-
-        throw cnyve;
-      }
-    }
-  }
-
-
-
-  /**
-   * Verifies that the provided certificate chains subject DN
-   * corresponds to the host name specified with the setHost method.
-   *
-   * @param chain
-   *          the certificate chain to analyze.
-   * @throws HostnameMismatchCertificateException
-   *           if the subject DN of the certificate does not match with
-   *           the host name specified with the method setHost.
-   */
-  private void verifyHostName(X509Certificate[] chain)
-      throws HostnameMismatchCertificateException
-  {
-    if (hostname != null)
-    {
-      try
-      {
-        DN dn = DN.valueOf(
-            chain[0].getSubjectX500Principal().getName(), Schema
-                .getCoreSchema());
-        String value = dn.iterator().next().iterator().next()
-            .getAttributeValue().toString();
-        if (!hostMatch(value, hostname))
-        {
-          throw new HostnameMismatchCertificateException(
-              "Hostname mismatch between host name " + hostname
-                  + " and subject DN: "
-                  + chain[0].getSubjectX500Principal(), hostname,
-              chain[0].getSubjectX500Principal().getName());
-        }
-      }
-      catch (Throwable t)
-      {
-        LOG.log(Level.WARNING, "Error parsing subject dn: "
-            + chain[0].getSubjectX500Principal(), t);
-      }
-    }
-  }
-
-
-
-  /**
-   * Checks whether two host names match. It accepts the use of wildcard
-   * in the host name.
-   *
-   * @param host1
-   *          the first host name.
-   * @param host2
-   *          the second host name.
-   * @return <CODE>true</CODE> if the host match and <CODE>false</CODE>
-   *         otherwise.
-   */
-  private boolean hostMatch(String host1, String host2)
-  {
-    if (host1 == null)
-    {
-      throw new IllegalArgumentException(
-          "The host1 parameter cannot be null");
-    }
-    if (host2 == null)
-    {
-      throw new IllegalArgumentException(
-          "The host2 parameter cannot be null");
-    }
-    String[] h1 = host1.split("\\.");
-    String[] h2 = host2.split("\\.");
-
-    boolean hostMatch = h1.length == h2.length;
-    for (int i = 0; i < h1.length && hostMatch; i++)
-    {
-      if (!h1[i].equals("*") && !h2[i].equals("*"))
-      {
-        hostMatch = h1[i].equalsIgnoreCase(h2[i]);
-      }
-    }
-    return hostMatch;
-  }
-}
diff --git a/sdk/src/com/sun/opends/sdk/tools/Utils.java b/sdk/src/com/sun/opends/sdk/tools/Utils.java
index 342ce11..d8ba7cc 100644
--- a/sdk/src/com/sun/opends/sdk/tools/Utils.java
+++ b/sdk/src/com/sun/opends/sdk/tools/Utils.java
@@ -29,7 +29,7 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.util.StaticUtils.EOL;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -40,6 +40,7 @@
 import org.opends.sdk.controls.*;
 import org.opends.sdk.responses.BindResult;
 
+import com.sun.opends.sdk.controls.AccountUsabilityRequestControl;
 import com.sun.opends.sdk.tools.AuthenticatedConnectionFactory.AuthenticatedConnection;
 import com.sun.opends.sdk.util.StaticUtils;
 
@@ -50,36 +51,28 @@
  */
 final class Utils
 {
-  // Prevent instantiation.
-  private Utils()
-  {
-    // Do nothing.
-  }
-
-
-
   /**
    * The name of a command-line script used to launch a tool.
    */
   static final String PROPERTY_SCRIPT_NAME = "com.sun.opends.sdk.tools.scriptName";
 
   /**
-   * The column at which to wrap long lines of output in the
-   * command-line tools.
+   * The column at which to wrap long lines of output in the command-line tools.
    */
   static final int MAX_LINE_WIDTH;
+
   static
   {
     int columns = 80;
     try
     {
-      String s = System.getenv("COLUMNS");
+      final String s = System.getenv("COLUMNS");
       if (s != null)
       {
         columns = Integer.parseInt(s);
       }
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
       // Do nothing.
     }
@@ -89,20 +82,450 @@
 
 
   /**
-   * Inserts line breaks into the provided buffer to wrap text at no
-   * more than the specified column width. Wrapping will only be done at
-   * space boundaries and if there are no spaces within the specified
-   * width, then wrapping will be performed at the first space after the
-   * specified column.
+   * Filters the provided value to ensure that it is appropriate for use as an
+   * exit code. Exit code values are generally only allowed to be between 0 and
+   * 255, so any value outside of this range will be converted to 255, which is
+   * the typical exit code used to indicate an overflow value.
+   *
+   * @param exitCode
+   *          The exit code value to be processed.
+   * @return An integer value between 0 and 255, inclusive. If the provided exit
+   *         code was already between 0 and 255, then the original value will be
+   *         returned. If the provided value was out of this range, then 255
+   *         will be returned.
+   */
+  static int filterExitCode(final int exitCode)
+  {
+    if (exitCode < 0)
+    {
+      return 255;
+    }
+    else if (exitCode > 255)
+    {
+      return 255;
+    }
+    else
+    {
+      return exitCode;
+    }
+  }
+
+
+
+  /**
+   * Parse the specified command line argument to create the appropriate
+   * LDAPControl. The argument string should be in the format
+   * controloid[:criticality[:value|::b64value|:&lt;fileurl]]
+   *
+   * @param argString
+   *          The argument string containing the encoded control information.
+   * @return The control decoded from the provided string, or <CODE>null</CODE>
+   *         if an error occurs while parsing the argument value.
+   * @throws org.opends.sdk.DecodeException
+   *           If an error occurs.
+   */
+  static GenericControl getControl(final String argString)
+      throws DecodeException
+  {
+    String controlOID = null;
+    boolean controlCriticality = false;
+    ByteString controlValue = null;
+
+    int idx = argString.indexOf(":");
+
+    if (idx < 0)
+    {
+      controlOID = argString;
+    }
+    else
+    {
+      controlOID = argString.substring(0, idx);
+    }
+
+    final String lowerOID = StaticUtils.toLowerCase(controlOID);
+    if (lowerOID.equals("accountusable") || lowerOID.equals("accountusability"))
+    {
+      controlOID = AccountUsabilityRequestControl.OID;
+    }
+    else if (lowerOID.equals("authzid")
+        || lowerOID.equals("authorizationidentity"))
+    {
+      controlOID = AuthorizationIdentityRequestControl.OID;
+    }
+    else if (lowerOID.equals("noop") || lowerOID.equals("no-op"))
+    {
+      // controlOID = OID_LDAP_NOOP_OPENLDAP_ASSIGNED;
+    }
+    else if (lowerOID.equals("subentries"))
+    {
+      // controlOID = OID_LDAP_SUBENTRIES;
+    }
+    else if (lowerOID.equals("managedsait"))
+    {
+      // controlOID = OID_MANAGE_DSAIT_CONTROL;
+    }
+    else if (lowerOID.equals("pwpolicy") || lowerOID.equals("passwordpolicy"))
+    {
+      controlOID = PasswordPolicyRequestControl.OID;
+    }
+    else if (lowerOID.equals("subtreedelete") || lowerOID.equals("treedelete"))
+    {
+      controlOID = SubtreeDeleteRequestControl.OID;
+    }
+    else if (lowerOID.equals("realattrsonly")
+        || lowerOID.equals("realattributesonly"))
+    {
+      // controlOID = OID_REAL_ATTRS_ONLY;
+    }
+    else if (lowerOID.equals("virtualattrsonly")
+        || lowerOID.equals("virtualattributesonly"))
+    {
+      // controlOID = OID_VIRTUAL_ATTRS_ONLY;
+    }
+    else if (lowerOID.equals("effectiverights")
+        || lowerOID.equals("geteffectiverights"))
+    {
+      controlOID = GetEffectiveRightsRequestControl.OID;
+    }
+
+    if (idx < 0)
+    {
+      return GenericControl.newControl(controlOID);
+    }
+
+    final String remainder = argString.substring(idx + 1, argString.length());
+
+    idx = remainder.indexOf(":");
+    if (idx == -1)
+    {
+      if (remainder.equalsIgnoreCase("true"))
+      {
+        controlCriticality = true;
+      }
+      else if (remainder.equalsIgnoreCase("false"))
+      {
+        controlCriticality = false;
+      }
+      else
+      {
+        // TODO: I18N
+        throw DecodeException.error(LocalizableMessage
+            .raw("Invalid format for criticality value:" + remainder));
+      }
+      return GenericControl.newControl(controlOID, controlCriticality);
+
+    }
+
+    final String critical = remainder.substring(0, idx);
+    if (critical.equalsIgnoreCase("true"))
+    {
+      controlCriticality = true;
+    }
+    else if (critical.equalsIgnoreCase("false"))
+    {
+      controlCriticality = false;
+    }
+    else
+    {
+      // TODO: I18N
+      throw DecodeException.error(LocalizableMessage
+          .raw("Invalid format for criticality value:" + critical));
+    }
+
+    final String valString = remainder.substring(idx + 1, remainder.length());
+    if (valString.charAt(0) == ':')
+    {
+      controlValue = ByteString.valueOf(valString.substring(1, valString
+          .length()));
+    }
+    else if (valString.charAt(0) == '<')
+    {
+      // Read data from the file.
+      final String filePath = valString.substring(1, valString.length());
+      try
+      {
+        final byte[] val = readBytesFromFile(filePath);
+        controlValue = ByteString.wrap(val);
+      }
+      catch (final Exception e)
+      {
+        return null;
+      }
+    }
+    else
+    {
+      controlValue = ByteString.valueOf(valString);
+    }
+
+    return GenericControl.newControl(controlOID, controlCriticality,
+        controlValue);
+  }
+
+
+
+  /**
+   * Prints a multi-line error message with the provided information to the
+   * given print stream.
+   *
+   * @param app
+   *          The console app to use to write the error message.
+   * @param ere
+   *          The error result.
+   * @return The error code.
+   */
+  static int printErrorMessage(final ConsoleApplication app,
+      final ErrorResultException ere)
+  {
+    // if ((ere.getMessage() != null) && (ere.getMessage().length() >
+    // 0))
+    // {
+    // app.println(LocalizableMessage.raw(ere.getMessage()));
+    // }
+
+    if (ere.getResult().getResultCode().intValue() >= 0)
+    {
+      app.println(ERR_TOOL_RESULT_CODE.get(ere.getResult().getResultCode()
+          .intValue(), ere.getResult().getResultCode().toString()));
+    }
+
+    if ((ere.getResult().getDiagnosticMessage() != null)
+        && (ere.getResult().getDiagnosticMessage().length() > 0))
+    {
+      app.println(ERR_TOOL_ERROR_MESSAGE.get(ere.getResult()
+          .getDiagnosticMessage()));
+    }
+
+    if (ere.getResult().getMatchedDN() != null
+        && ere.getResult().getMatchedDN().length() > 0)
+    {
+      app.println(ERR_TOOL_MATCHED_DN.get(ere.getResult().getMatchedDN()));
+    }
+
+    if (app.isVerbose() && ere.getResult().getCause() != null)
+    {
+      ere.getResult().getCause().printStackTrace(app.getErrorStream());
+    }
+
+    return ere.getResult().getResultCode().intValue();
+  }
+
+
+
+  static void printPasswordPolicyResults(final ConsoleApplication app,
+      final Connection connection)
+  {
+    if (connection instanceof AuthenticatedConnection)
+    {
+      final AuthenticatedConnection conn = (AuthenticatedConnection) connection;
+      final BindResult result = conn.getAuthenticatedBindResult();
+
+      try
+      {
+        final AuthorizationIdentityResponseControl control = result.getControl(
+            AuthorizationIdentityResponseControl.DECODER, new DecodeOptions());
+        if (control != null)
+        {
+          final LocalizableMessage message = INFO_BIND_AUTHZID_RETURNED
+              .get(control.getAuthorizationID());
+          app.println(message);
+        }
+      }
+      catch (final DecodeException e)
+      {
+        app.println(ERR_DECODE_CONTROL_FAILURE.get(e.getLocalizedMessage()));
+      }
+
+      try
+      {
+        final PasswordExpiredResponseControl control = result.getControl(
+            PasswordExpiredResponseControl.DECODER, new DecodeOptions());
+        if (control != null)
+        {
+          final LocalizableMessage message = INFO_BIND_PASSWORD_EXPIRED.get();
+          app.println(message);
+        }
+      }
+      catch (final DecodeException e)
+      {
+        app.println(ERR_DECODE_CONTROL_FAILURE.get(e.getLocalizedMessage()));
+      }
+
+      try
+      {
+        final PasswordExpiringResponseControl control = result.getControl(
+            PasswordExpiringResponseControl.DECODER, new DecodeOptions());
+        if (control != null)
+        {
+          final LocalizableMessage timeString = Utils
+              .secondsToTimeString(control.getSecondsUntilExpiration());
+          final LocalizableMessage message = INFO_BIND_PASSWORD_EXPIRING
+              .get(timeString);
+          app.println(message);
+        }
+      }
+      catch (final DecodeException e)
+      {
+        app.println(ERR_DECODE_CONTROL_FAILURE.get(e.getLocalizedMessage()));
+      }
+
+      try
+      {
+        final PasswordPolicyResponseControl control = result.getControl(
+            PasswordPolicyResponseControl.DECODER, new DecodeOptions());
+        if (control != null)
+        {
+          final PasswordPolicyErrorType errorType = control.getErrorType();
+          if (errorType == PasswordPolicyErrorType.PASSWORD_EXPIRED)
+          {
+            final LocalizableMessage message = INFO_BIND_PASSWORD_EXPIRED.get();
+            app.println(message);
+          }
+          else if (errorType == PasswordPolicyErrorType.ACCOUNT_LOCKED)
+          {
+            final LocalizableMessage message = INFO_BIND_ACCOUNT_LOCKED.get();
+            app.println(message);
+          }
+          else if (errorType == PasswordPolicyErrorType.CHANGE_AFTER_RESET)
+          {
+
+            final LocalizableMessage message = INFO_BIND_MUST_CHANGE_PASSWORD
+                .get();
+            app.println(message);
+          }
+
+          final PasswordPolicyWarningType warningType = control
+              .getWarningType();
+          if (warningType == PasswordPolicyWarningType.TIME_BEFORE_EXPIRATION)
+          {
+            final LocalizableMessage timeString = Utils
+                .secondsToTimeString(control.getWarningValue());
+            final LocalizableMessage message = INFO_BIND_PASSWORD_EXPIRING
+                .get(timeString);
+            app.println(message);
+          }
+          else if (warningType == PasswordPolicyWarningType.GRACE_LOGINS_REMAINING)
+          {
+            final LocalizableMessage message = INFO_BIND_GRACE_LOGINS_REMAINING
+                .get(control.getWarningValue());
+            app.println(message);
+          }
+        }
+      }
+      catch (final DecodeException e)
+      {
+        app.println(ERR_DECODE_CONTROL_FAILURE.get(e.getLocalizedMessage()));
+      }
+    }
+  }
+
+
+
+  /**
+   * Read the data from the specified file and return it in a byte array.
+   *
+   * @param filePath
+   *          The path to the file that should be read.
+   * @return A byte array containing the contents of the requested file.
+   * @throws IOException
+   *           If a problem occurs while trying to read the specified file.
+   */
+  static byte[] readBytesFromFile(final String filePath) throws IOException
+  {
+    byte[] val = null;
+    FileInputStream fis = null;
+    try
+    {
+      final File file = new File(filePath);
+      fis = new FileInputStream(file);
+      final long length = file.length();
+      val = new byte[(int) length];
+      // Read in the bytes
+      int offset = 0;
+      int numRead = 0;
+      while (offset < val.length
+          && (numRead = fis.read(val, offset, val.length - offset)) >= 0)
+      {
+        offset += numRead;
+      }
+
+      // Ensure all the bytes have been read in
+      if (offset < val.length)
+      {
+        throw new IOException("Could not completely read file " + filePath);
+      }
+
+      return val;
+    }
+    finally
+    {
+      if (fis != null)
+      {
+        fis.close();
+      }
+    }
+  }
+
+
+
+  /**
+   * Retrieves a user-friendly string that indicates the length of time (in
+   * days, hours, minutes, and seconds) in the specified number of seconds.
+   *
+   * @param numSeconds
+   *          The number of seconds to be converted to a more user-friendly
+   *          value.
+   * @return The user-friendly representation of the specified number of
+   *         seconds.
+   */
+  static LocalizableMessage secondsToTimeString(final int numSeconds)
+  {
+    if (numSeconds < 60)
+    {
+      // We can express it in seconds.
+      return INFO_TIME_IN_SECONDS.get(numSeconds);
+    }
+    else if (numSeconds < 3600)
+    {
+      // We can express it in minutes and seconds.
+      final int m = numSeconds / 60;
+      final int s = numSeconds % 60;
+      return INFO_TIME_IN_MINUTES_SECONDS.get(m, s);
+    }
+    else if (numSeconds < 86400)
+    {
+      // We can express it in hours, minutes, and seconds.
+      final int h = numSeconds / 3600;
+      final int m = (numSeconds % 3600) / 60;
+      final int s = numSeconds % 3600 % 60;
+      return INFO_TIME_IN_HOURS_MINUTES_SECONDS.get(h, m, s);
+    }
+    else
+    {
+      // We can express it in days, hours, minutes, and seconds.
+      final int d = numSeconds / 86400;
+      final int h = (numSeconds % 86400) / 3600;
+      final int m = (numSeconds % 86400 % 3600) / 60;
+      final int s = numSeconds % 86400 % 3600 % 60;
+      return INFO_TIME_IN_DAYS_HOURS_MINUTES_SECONDS.get(d, h, m, s);
+    }
+  }
+
+
+
+  /**
+   * Inserts line breaks into the provided buffer to wrap text at no more than
+   * the specified column width. Wrapping will only be done at space boundaries
+   * and if there are no spaces within the specified width, then wrapping will
+   * be performed at the first space after the specified column.
    *
    * @param message
    *          The message to be wrapped.
    * @param width
-   *          The maximum number of characters to allow on a line if
-   *          there is a suitable breaking point.
+   *          The maximum number of characters to allow on a line if there is a
+   *          suitable breaking point.
    * @return The wrapped text.
    */
-  static String wrapText(LocalizableMessage message, int width)
+  static String wrapText(final LocalizableMessage message, final int width)
   {
     return wrapText(message.toString(), width, 0);
   }
@@ -110,45 +533,23 @@
 
 
   /**
-   * Inserts line breaks into the provided buffer to wrap text at no
-   * more than the specified column width. Wrapping will only be done at
-   * space boundaries and if there are no spaces within the specified
-   * width, then wrapping will be performed at the first space after the
-   * specified column.
-   *
-   * @param text
-   *          The text to be wrapped.
-   * @param width
-   *          The maximum number of characters to allow on a line if
-   *          there is a suitable breaking point.
-   * @return The wrapped text.
-   */
-  static String wrapText(String text, int width)
-  {
-    return wrapText(text, width, 0);
-  }
-
-
-
-  /**
-   * Inserts line breaks into the provided buffer to wrap text at no
-   * more than the specified column width. Wrapping will only be done at
-   * space boundaries and if there are no spaces within the specified
-   * width, then wrapping will be performed at the first space after the
-   * specified column. In addition each line will be indented by the
-   * specified amount.
+   * Inserts line breaks into the provided buffer to wrap text at no more than
+   * the specified column width. Wrapping will only be done at space boundaries
+   * and if there are no spaces within the specified width, then wrapping will
+   * be performed at the first space after the specified column. In addition
+   * each line will be indented by the specified amount.
    *
    * @param message
    *          The message to be wrapped.
    * @param width
-   *          The maximum number of characters to allow on a line if
-   *          there is a suitable breaking point (including any
-   *          indentation).
+   *          The maximum number of characters to allow on a line if there is a
+   *          suitable breaking point (including any indentation).
    * @param indent
    *          The number of columns to indent each line.
    * @return The wrapped text.
    */
-  static String wrapText(LocalizableMessage message, int width, int indent)
+  static String wrapText(final LocalizableMessage message, final int width,
+      final int indent)
   {
     return wrapText(message.toString(), width, indent);
   }
@@ -156,42 +557,60 @@
 
 
   /**
-   * Inserts line breaks into the provided buffer to wrap text at no
-   * more than the specified column width. Wrapping will only be done at
-   * space boundaries and if there are no spaces within the specified
-   * width, then wrapping will be performed at the first space after the
-   * specified column. In addition each line will be indented by the
-   * specified amount.
+   * Inserts line breaks into the provided buffer to wrap text at no more than
+   * the specified column width. Wrapping will only be done at space boundaries
+   * and if there are no spaces within the specified width, then wrapping will
+   * be performed at the first space after the specified column.
    *
    * @param text
    *          The text to be wrapped.
    * @param width
-   *          The maximum number of characters to allow on a line if
-   *          there is a suitable breaking point (including any
-   *          indentation).
+   *          The maximum number of characters to allow on a line if there is a
+   *          suitable breaking point.
+   * @return The wrapped text.
+   */
+  static String wrapText(final String text, final int width)
+  {
+    return wrapText(text, width, 0);
+  }
+
+
+
+  /**
+   * Inserts line breaks into the provided buffer to wrap text at no more than
+   * the specified column width. Wrapping will only be done at space boundaries
+   * and if there are no spaces within the specified width, then wrapping will
+   * be performed at the first space after the specified column. In addition
+   * each line will be indented by the specified amount.
+   *
+   * @param text
+   *          The text to be wrapped.
+   * @param width
+   *          The maximum number of characters to allow on a line if there is a
+   *          suitable breaking point (including any indentation).
    * @param indent
    *          The number of columns to indent each line.
    * @return The wrapped text.
    */
-  static String wrapText(String text, int width, int indent)
+  static String wrapText(final String text, int width, final int indent)
   {
     // Calculate the real width and indentation padding.
     width -= indent;
-    StringBuilder pb = new StringBuilder();
+    final StringBuilder pb = new StringBuilder();
     for (int i = 0; i < indent; i++)
     {
       pb.append(' ');
     }
-    String padding = pb.toString();
+    final String padding = pb.toString();
 
-    StringBuilder buffer = new StringBuilder();
+    final StringBuilder buffer = new StringBuilder();
     if (text != null)
     {
-      StringTokenizer lineTokenizer = new StringTokenizer(text, "\r\n",
+      final StringTokenizer lineTokenizer = new StringTokenizer(text, "\r\n",
           true);
       while (lineTokenizer.hasMoreTokens())
       {
-        String line = lineTokenizer.nextToken();
+        final String line = lineTokenizer.nextToken();
         if (line.equals("\r") || line.equals("\n"))
         {
           // It's an end-of-line character, so append it as-is.
@@ -210,11 +629,11 @@
           // wrapped. Do so at space boundaries.
           StringBuilder lineBuffer = new StringBuilder();
           StringBuilder delimBuffer = new StringBuilder();
-          StringTokenizer wordTokenizer = new StringTokenizer(line,
-              " ", true);
+          final StringTokenizer wordTokenizer = new StringTokenizer(line, " ",
+              true);
           while (wordTokenizer.hasMoreTokens())
           {
-            String word = wordTokenizer.nextToken();
+            final String word = wordTokenizer.nextToken();
             if (word.equals(" "))
             {
               // It's a space, so add it to the delim buffer only if the
@@ -261,7 +680,7 @@
             {
               // It's not a space, so see if we can fit it on the curent
               // line.
-              int newLineLength = lineBuffer.length()
+              final int newLineLength = lineBuffer.length()
                   + delimBuffer.length() + word.length();
               if (newLineLength < width)
               {
@@ -306,412 +725,9 @@
 
 
 
-  /**
-   * Parse the specified command line argument to create the appropriate
-   * LDAPControl. The argument string should be in the format
-   * controloid[:criticality[:value|::b64value|:&lt;fileurl]]
-   *
-   * @param argString
-   *          The argument string containing the encoded control
-   *          information.
-   * @return The control decoded from the provided string, or
-   *         <CODE>null</CODE> if an error occurs while parsing the
-   *         argument value.
-   * @throws org.opends.sdk.DecodeException
-   *           If an error occurs.
-   */
-  static GenericControl getControl(String argString)
-      throws DecodeException
+  // Prevent instantiation.
+  private Utils()
   {
-    String controlOID = null;
-    boolean controlCriticality = false;
-    ByteString controlValue = null;
-
-    int idx = argString.indexOf(":");
-
-    if (idx < 0)
-    {
-      controlOID = argString;
-    }
-    else
-    {
-      controlOID = argString.substring(0, idx);
-    }
-
-    String lowerOID = StaticUtils.toLowerCase(controlOID);
-    if (lowerOID.equals("accountusable")
-        || lowerOID.equals("accountusability"))
-    {
-      controlOID = AccountUsabilityControl.OID_ACCOUNT_USABLE_CONTROL;
-    }
-    else if (lowerOID.equals("authzid")
-        || lowerOID.equals("authorizationidentity"))
-    {
-      controlOID = AuthorizationIdentityControl.OID_AUTHZID_REQUEST;
-    }
-    else if (lowerOID.equals("noop") || lowerOID.equals("no-op"))
-    {
-      // controlOID = OID_LDAP_NOOP_OPENLDAP_ASSIGNED;
-    }
-    else if (lowerOID.equals("subentries"))
-    {
-      // controlOID = OID_LDAP_SUBENTRIES;
-    }
-    else if (lowerOID.equals("managedsait"))
-    {
-      // controlOID = OID_MANAGE_DSAIT_CONTROL;
-    }
-    else if (lowerOID.equals("pwpolicy")
-        || lowerOID.equals("passwordpolicy"))
-    {
-      controlOID = PasswordPolicyControl.OID_PASSWORD_POLICY_CONTROL;
-    }
-    else if (lowerOID.equals("subtreedelete")
-        || lowerOID.equals("treedelete"))
-    {
-      controlOID = SubtreeDeleteControl.OID_SUBTREE_DELETE_CONTROL;
-    }
-    else if (lowerOID.equals("realattrsonly")
-        || lowerOID.equals("realattributesonly"))
-    {
-      // controlOID = OID_REAL_ATTRS_ONLY;
-    }
-    else if (lowerOID.equals("virtualattrsonly")
-        || lowerOID.equals("virtualattributesonly"))
-    {
-      // controlOID = OID_VIRTUAL_ATTRS_ONLY;
-    }
-    else if (lowerOID.equals("effectiverights")
-        || lowerOID.equals("geteffectiverights"))
-    {
-      controlOID = GetEffectiveRightsRequestControl.OID_GET_EFFECTIVE_RIGHTS;
-    }
-
-    if (idx < 0)
-    {
-      return new GenericControl(controlOID);
-    }
-
-    String remainder = argString.substring(idx + 1, argString.length());
-
-    idx = remainder.indexOf(":");
-    if (idx == -1)
-    {
-      if (remainder.equalsIgnoreCase("true"))
-      {
-        controlCriticality = true;
-      }
-      else if (remainder.equalsIgnoreCase("false"))
-      {
-        controlCriticality = false;
-      }
-      else
-      {
-        // TODO: I18N
-        throw DecodeException.error(LocalizableMessage
-            .raw("Invalid format for criticality value:" + remainder));
-      }
-      return new GenericControl(controlOID, controlCriticality);
-
-    }
-
-    String critical = remainder.substring(0, idx);
-    if (critical.equalsIgnoreCase("true"))
-    {
-      controlCriticality = true;
-    }
-    else if (critical.equalsIgnoreCase("false"))
-    {
-      controlCriticality = false;
-    }
-    else
-    {
-      // TODO: I18N
-      throw DecodeException.error(LocalizableMessage
-          .raw("Invalid format for criticality value:" + critical));
-    }
-
-    String valString = remainder.substring(idx + 1, remainder.length());
-    if (valString.charAt(0) == ':')
-    {
-      controlValue = ByteString.valueOf(valString.substring(1,
-          valString.length()));
-    }
-    else if (valString.charAt(0) == '<')
-    {
-      // Read data from the file.
-      String filePath = valString.substring(1, valString.length());
-      try
-      {
-        byte[] val = readBytesFromFile(filePath);
-        controlValue = ByteString.wrap(val);
-      }
-      catch (Exception e)
-      {
-        return null;
-      }
-    }
-    else
-    {
-      controlValue = ByteString.valueOf(valString);
-    }
-
-    return new GenericControl(controlOID, controlCriticality,
-        controlValue);
-  }
-
-
-
-  /**
-   * Read the data from the specified file and return it in a byte
-   * array.
-   *
-   * @param filePath
-   *          The path to the file that should be read.
-   * @return A byte array containing the contents of the requested file.
-   * @throws IOException
-   *           If a problem occurs while trying to read the specified
-   *           file.
-   */
-  static byte[] readBytesFromFile(String filePath) throws IOException
-  {
-    byte[] val = null;
-    FileInputStream fis = null;
-    try
-    {
-      File file = new File(filePath);
-      fis = new FileInputStream(file);
-      long length = file.length();
-      val = new byte[(int) length];
-      // Read in the bytes
-      int offset = 0;
-      int numRead = 0;
-      while (offset < val.length
-          && (numRead = fis.read(val, offset, val.length - offset)) >= 0)
-      {
-        offset += numRead;
-      }
-
-      // Ensure all the bytes have been read in
-      if (offset < val.length)
-      {
-        throw new IOException("Could not completely read file "
-            + filePath);
-      }
-
-      return val;
-    }
-    finally
-    {
-      if (fis != null)
-      {
-        fis.close();
-      }
-    }
-  }
-
-
-
-  /**
-   * Prints a multi-line error message with the provided information to
-   * the given print stream.
-   *
-   * @param app
-   *          The console app to use to write the error message.
-   * @param ere
-   *          The error result.
-   * @return The error code.
-   */
-  static int printErrorMessage(ConsoleApplication app,
-      ErrorResultException ere)
-  {
-    // if ((ere.getMessage() != null) && (ere.getMessage().length() >
-    // 0))
-    // {
-    // app.println(LocalizableMessage.raw(ere.getMessage()));
-    // }
-
-    if (ere.getResult().getResultCode().intValue() >= 0)
-    {
-      app.println(ERR_TOOL_RESULT_CODE.get(ere.getResult()
-          .getResultCode().intValue(), ere.getResult().getResultCode()
-          .toString()));
-    }
-
-    if ((ere.getResult().getDiagnosticMessage() != null)
-        && (ere.getResult().getDiagnosticMessage().length() > 0))
-    {
-      app.println(ERR_TOOL_ERROR_MESSAGE.get(ere.getResult()
-          .getDiagnosticMessage()));
-    }
-
-    if (ere.getResult().getMatchedDN() != null
-        && ere.getResult().getMatchedDN().length() > 0)
-    {
-      app.println(ERR_TOOL_MATCHED_DN.get(ere.getResult()
-          .getMatchedDN()));
-    }
-
-    if (app.isVerbose() && ere.getResult().getCause() != null)
-    {
-      ere.getResult().getCause().printStackTrace(app.getErrorStream());
-    }
-
-    return ere.getResult().getResultCode().intValue();
-  }
-
-
-
-  /**
-   * Retrieves a user-friendly string that indicates the length of time
-   * (in days, hours, minutes, and seconds) in the specified number of
-   * seconds.
-   *
-   * @param numSeconds
-   *          The number of seconds to be converted to a more
-   *          user-friendly value.
-   * @return The user-friendly representation of the specified number of
-   *         seconds.
-   */
-  static LocalizableMessage secondsToTimeString(int numSeconds)
-  {
-    if (numSeconds < 60)
-    {
-      // We can express it in seconds.
-      return INFO_TIME_IN_SECONDS.get(numSeconds);
-    }
-    else if (numSeconds < 3600)
-    {
-      // We can express it in minutes and seconds.
-      int m = numSeconds / 60;
-      int s = numSeconds % 60;
-      return INFO_TIME_IN_MINUTES_SECONDS.get(m, s);
-    }
-    else if (numSeconds < 86400)
-    {
-      // We can express it in hours, minutes, and seconds.
-      int h = numSeconds / 3600;
-      int m = (numSeconds % 3600) / 60;
-      int s = numSeconds % 3600 % 60;
-      return INFO_TIME_IN_HOURS_MINUTES_SECONDS.get(h, m, s);
-    }
-    else
-    {
-      // We can express it in days, hours, minutes, and seconds.
-      int d = numSeconds / 86400;
-      int h = (numSeconds % 86400) / 3600;
-      int m = (numSeconds % 86400 % 3600) / 60;
-      int s = numSeconds % 86400 % 3600 % 60;
-      return INFO_TIME_IN_DAYS_HOURS_MINUTES_SECONDS.get(d, h, m, s);
-    }
-  }
-
-
-
-  static void printPasswordPolicyResults(ConsoleApplication app,
-      Connection connection)
-  {
-    if (connection instanceof AuthenticatedConnection)
-    {
-      AuthenticatedConnection conn = (AuthenticatedConnection) connection;
-      BindResult result = conn.getAuthenticatedBindResult();
-
-      Control control = result
-          .getControl(AuthorizationIdentityControl.OID_AUTHZID_RESPONSE);
-      if (control != null)
-      {
-        AuthorizationIdentityControl.Response dc = (AuthorizationIdentityControl.Response) control;
-        LocalizableMessage message = INFO_BIND_AUTHZID_RETURNED.get(dc
-            .getAuthorizationID());
-        app.println(message);
-      }
-      control = result
-          .getControl(PasswordExpiredControl.OID_NS_PASSWORD_EXPIRED);
-      if (control != null)
-      {
-        LocalizableMessage message = INFO_BIND_PASSWORD_EXPIRED.get();
-        app.println(message);
-      }
-      control = result
-          .getControl(PasswordExpiringControl.OID_NS_PASSWORD_EXPIRING);
-      if (control != null)
-      {
-        PasswordExpiringControl dc = (PasswordExpiringControl) control;
-        LocalizableMessage timeString = Utils.secondsToTimeString(dc
-            .getSecondsUntilExpiration());
-        LocalizableMessage message = INFO_BIND_PASSWORD_EXPIRING.get(timeString);
-        app.println(message);
-      }
-      control = result
-          .getControl(PasswordPolicyControl.OID_PASSWORD_POLICY_CONTROL);
-      if (control != null)
-      {
-        PasswordPolicyControl.Response dc = (PasswordPolicyControl.Response) control;
-        PasswordPolicyErrorType errorType = dc.getErrorType();
-        if (errorType == PasswordPolicyErrorType.PASSWORD_EXPIRED)
-        {
-          LocalizableMessage message = INFO_BIND_PASSWORD_EXPIRED.get();
-          app.println(message);
-        }
-        else if (errorType == PasswordPolicyErrorType.ACCOUNT_LOCKED)
-        {
-          LocalizableMessage message = INFO_BIND_ACCOUNT_LOCKED.get();
-          app.println(message);
-        }
-        else if (errorType == PasswordPolicyErrorType.CHANGE_AFTER_RESET)
-        {
-
-          LocalizableMessage message = INFO_BIND_MUST_CHANGE_PASSWORD.get();
-          app.println(message);
-        }
-
-        PasswordPolicyWarningType warningType = dc.getWarningType();
-        if (warningType == PasswordPolicyWarningType.TIME_BEFORE_EXPIRATION)
-        {
-          LocalizableMessage timeString = Utils.secondsToTimeString(dc
-              .getWarningValue());
-          LocalizableMessage message = INFO_BIND_PASSWORD_EXPIRING.get(timeString);
-          app.println(message);
-        }
-        else if (warningType == PasswordPolicyWarningType.GRACE_LOGINS_REMAINING)
-        {
-          LocalizableMessage message = INFO_BIND_GRACE_LOGINS_REMAINING.get(dc
-              .getWarningValue());
-          app.println(message);
-        }
-      }
-    }
-  }
-
-
-
-  /**
-   * Filters the provided value to ensure that it is appropriate for use
-   * as an exit code. Exit code values are generally only allowed to be
-   * between 0 and 255, so any value outside of this range will be
-   * converted to 255, which is the typical exit code used to indicate
-   * an overflow value.
-   *
-   * @param exitCode
-   *          The exit code value to be processed.
-   * @return An integer value between 0 and 255, inclusive. If the
-   *         provided exit code was already between 0 and 255, then the
-   *         original value will be returned. If the provided value was
-   *         out of this range, then 255 will be returned.
-   */
-  static int filterExitCode(int exitCode)
-  {
-    if (exitCode < 0)
-    {
-      return 255;
-    }
-    else if (exitCode > 255)
-    {
-      return 255;
-    }
-    else
-    {
-      return exitCode;
-    }
+    // Do nothing.
   }
 }
diff --git a/sdk/src/com/sun/opends/sdk/tools/package-info.java b/sdk/src/com/sun/opends/sdk/tools/package-info.java
index 66ea32f..227eb18 100755
--- a/sdk/src/com/sun/opends/sdk/tools/package-info.java
+++ b/sdk/src/com/sun/opends/sdk/tools/package-info.java
@@ -29,3 +29,6 @@
  * Classes implementing the OpenDS SDK client tools.
  */
 package com.sun.opends.sdk.tools;
+
+
+
diff --git a/sdk/src/com/sun/opends/sdk/util/ASCIICharProp.java b/sdk/src/com/sun/opends/sdk/util/ASCIICharProp.java
index 106864b..f1ed00a 100644
--- a/sdk/src/com/sun/opends/sdk/util/ASCIICharProp.java
+++ b/sdk/src/com/sun/opends/sdk/util/ASCIICharProp.java
@@ -30,32 +30,41 @@
 
 
 /**
- * A {@code ASCIICharProp} provides fast access to ASCII character
- * properties. In particular, the ability to query whether or not a
- * character is a letter, a digit, hexadecimal character, as well as
- * various methods for performing character conversions.
+ * A {@code ASCIICharProp} provides fast access to ASCII character properties.
+ * In particular, the ability to query whether or not a character is a letter, a
+ * digit, hexadecimal character, as well as various methods for performing
+ * character conversions.
  * <p>
- * The methods in this class do not perform memory allocations nor
- * calculations and so can be used safely in high performance
- * situations.
+ * The methods in this class do not perform memory allocations nor calculations
+ * and so can be used safely in high performance situations.
  */
 public final class ASCIICharProp implements Comparable<ASCIICharProp>
 {
   private final char c;
+
   private final char upperCaseChar;
+
   private final char lowerCaseChar;
+
   private final boolean isUpperCaseChar;
+
   private final boolean isLowerCaseChar;
+
   private final boolean isDigit;
+
   private final boolean isLetter;
+
   private final boolean isKeyChar;
+
   private final boolean isHexChar;
+
   private final int hexValue;
+
   private final int decimalValue;
+
   private final String stringValue;
 
-  private static final ASCIICharProp[] CHAR_PROPS =
-      new ASCIICharProp[128];
+  private static final ASCIICharProp[] CHAR_PROPS = new ASCIICharProp[128];
 
   static
   {
@@ -68,17 +77,15 @@
 
 
   /**
-   * Returns the character properties for the provided ASCII character.
-   * If a non-ASCII character is provided then this method returns
-   * {@code null}.
-   * 
+   * Returns the character properties for the provided ASCII character. If a
+   * non-ASCII character is provided then this method returns {@code null}.
+   *
    * @param c
    *          The ASCII character.
-   * @return The character properties for the provided ASCII character,
-   *         or {@code null} if {@code c} is greater than {@code \u007F}
-   *         .
+   * @return The character properties for the provided ASCII character, or
+   *         {@code null} if {@code c} is greater than {@code \u007F} .
    */
-  public static ASCIICharProp valueOf(char c)
+  public static ASCIICharProp valueOf(final char c)
   {
     if (c < 128)
     {
@@ -93,17 +100,16 @@
 
 
   /**
-   * Returns the character properties for the provided ASCII character.
-   * If a non-ASCII character is provided then this method returns
-   * {@code null}.
-   * 
+   * Returns the character properties for the provided ASCII character. If a
+   * non-ASCII character is provided then this method returns {@code null}.
+   *
    * @param c
    *          The ASCII character.
-   * @return The character properties for the provided ASCII character,
-   *         or {@code null} if {@code c} is less than zero or greater
-   *         than {@code \u007F} .
+   * @return The character properties for the provided ASCII character, or
+   *         {@code null} if {@code c} is less than zero or greater than {@code
+   *         \u007F} .
    */
-  public static ASCIICharProp valueOf(int c)
+  public static ASCIICharProp valueOf(final int c)
   {
     if (c >= 0 && c < 128)
     {
@@ -117,7 +123,7 @@
 
 
 
-  private ASCIICharProp(char c)
+  private ASCIICharProp(final char c)
   {
     this.c = c;
     this.stringValue = new String(new char[] { c });
@@ -196,7 +202,7 @@
 
   /**
    * Returns the char value associated with this {@code ASCIICharProp}.
-   * 
+   *
    * @return The char value associated with this {@code ASCIICharProp}.
    */
   public char charValue()
@@ -209,7 +215,7 @@
   /**
    * {@inheritDoc}
    */
-  public int compareTo(ASCIICharProp o)
+  public int compareTo(final ASCIICharProp o)
   {
     return c - o.c;
   }
@@ -217,12 +223,11 @@
 
 
   /**
-   * Returns the decimal value associated with this {@code
-   * ASCIICharProp}, or {@code -1} if the value is not a decimal digit.
-   * 
-   * @return The decimal value associated with this {@code
-   *         ASCIICharProp}, or {@code -1} if the value is not a decimal
-   *         digit.
+   * Returns the decimal value associated with this {@code ASCIICharProp}, or
+   * {@code -1} if the value is not a decimal digit.
+   *
+   * @return The decimal value associated with this {@code ASCIICharProp}, or
+   *         {@code -1} if the value is not a decimal digit.
    */
   public int decimalValue()
   {
@@ -232,13 +237,33 @@
 
 
   /**
-   * Returns the hexadecimal value associated with this {@code
-   * ASCIICharProp} , or {@code -1} if the value is not a hexadecimal
-   * digit.
-   * 
-   * @return The hexadecimal value associated with this {@code
-   *         ASCIICharProp} , or {@code -1} if the value is not a
-   *         hexadecimal digit.
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean equals(final Object obj)
+  {
+    return this == obj;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int hashCode()
+  {
+    return c;
+  }
+
+
+
+  /**
+   * Returns the hexadecimal value associated with this {@code ASCIICharProp} ,
+   * or {@code -1} if the value is not a hexadecimal digit.
+   *
+   * @return The hexadecimal value associated with this {@code ASCIICharProp} ,
+   *         or {@code -1} if the value is not a hexadecimal digit.
    */
   public int hexValue()
   {
@@ -248,9 +273,9 @@
 
 
   /**
-   * Indicates whether or not the char value associated with this
-   * {@code ASCIICharProp} is a decimal digit.
-   * 
+   * Indicates whether or not the char value associated with this {@code
+   * ASCIICharProp} is a decimal digit.
+   *
    * @return {@code true} if the char value associated with this {@code
    *         ASCIICharProp} is a decimal digit.
    */
@@ -262,9 +287,9 @@
 
 
   /**
-   * Indicates whether or not the char value associated with this
-   * {@code ASCIICharProp} is a hexadecimal digit.
-   * 
+   * Indicates whether or not the char value associated with this {@code
+   * ASCIICharProp} is a hexadecimal digit.
+   *
    * @return {@code true} if the char value associated with this {@code
    *         ASCIICharProp} is a hexadecimal digit.
    */
@@ -276,10 +301,10 @@
 
 
   /**
-   * Indicates whether or not the char value associated with this
-   * {@code ASCIICharProp} is a {@code keychar} as defined in RFC 4512.
-   * A {@code keychar} is a letter, a digit, or a hyphen.
-   * 
+   * Indicates whether or not the char value associated with this {@code
+   * ASCIICharProp} is a {@code keychar} as defined in RFC 4512. A {@code
+   * keychar} is a letter, a digit, or a hyphen.
+   *
    * @return {@code true} if the char value associated with this {@code
    *         ASCIICharProp} is a {@code keychar}.
    */
@@ -291,9 +316,9 @@
 
 
   /**
-   * Indicates whether or not the char value associated with this
-   * {@code ASCIICharProp} is a letter.
-   * 
+   * Indicates whether or not the char value associated with this {@code
+   * ASCIICharProp} is a letter.
+   *
    * @return {@code true} if the char value associated with this {@code
    *         ASCIICharProp} is a letter.
    */
@@ -305,9 +330,9 @@
 
 
   /**
-   * Indicates whether or not the char value associated with this
-   * {@code ASCIICharProp} is a lower-case character.
-   * 
+   * Indicates whether or not the char value associated with this {@code
+   * ASCIICharProp} is a lower-case character.
+   *
    * @return {@code true} if the char value associated with this {@code
    *         ASCIICharProp} is a lower-case character.
    */
@@ -319,9 +344,9 @@
 
 
   /**
-   * Indicates whether or not the char value associated with this
-   * {@code ASCIICharProp} is an upper-case character.
-   * 
+   * Indicates whether or not the char value associated with this {@code
+   * ASCIICharProp} is an upper-case character.
+   *
    * @return {@code true} if the char value associated with this {@code
    *         ASCIICharProp} is an upper-case character.
    */
@@ -335,7 +360,7 @@
   /**
    * Returns the lower-case char value associated with this {@code
    * ASCIICharProp}.
-   * 
+   *
    * @return The lower-case char value associated with this {@code
    *         ASCIICharProp}.
    */
@@ -360,7 +385,7 @@
   /**
    * Returns the upper-case char value associated with this {@code
    * ASCIICharProp}.
-   * 
+   *
    * @return The upper-case char value associated with this {@code
    *         ASCIICharProp}.
    */
diff --git a/sdk/src/com/sun/opends/sdk/util/AbstractFutureResult.java b/sdk/src/com/sun/opends/sdk/util/AbstractFutureResult.java
index cca5877..a0b0120 100644
--- a/sdk/src/com/sun/opends/sdk/util/AbstractFutureResult.java
+++ b/sdk/src/com/sun/opends/sdk/util/AbstractFutureResult.java
@@ -40,37 +40,34 @@
 
 
 /**
- * This class provides a skeletal implementation of the {@code
- * FutureResult} interface, to minimize the effort required to implement
- * this interface.
+ * This class provides a skeletal implementation of the {@code FutureResult}
+ * interface, to minimize the effort required to implement this interface.
  * <p>
- * This {@code FutureResult} implementation provides the following
- * features:
+ * This {@code FutureResult} implementation provides the following features:
  * <ul>
- * <li>The {@link #get} methods throw {@link ErrorResultException}s
- * instead of the more generic {@code ExecutionException}s.
- * <li>The {@link #get} methods never throw {@code
- * CancellationException} since requests in this SDK can usually be
- * cancelled via other external means (e.g. the {@code Cancel} extended
- * operation) for which there are well defined error results. Therefore
- * cancellation is always signalled by throwing a
- * {@link CancelledResultException} in order to be consistent with other
- * error results.
- * <li>A {@link ResultHandler} can be provided to the constructor. The
- * result handler will be invoked immediately after the result or error
- * is received but before threads blocked on {@link #get} are released.
- * More specifically, result handler invocation <i>happens-before</i> a
- * call to {@link #get}. <b>NOTE:</b> a result handler which attempts to
- * call {@link #get} will deadlock.
- * <li>Sub-classes may choose to implement specific cancellation cleanup
- * by implementing the {@link #handleCancelRequest} method.
+ * <li>The {@link #get} methods throw {@link ErrorResultException}s instead of
+ * the more generic {@code ExecutionException}s.
+ * <li>The {@link #get} methods never throw {@code CancellationException} since
+ * requests in this SDK can usually be cancelled via other external means (e.g.
+ * the {@code Cancel} extended operation) for which there are well defined error
+ * results. Therefore cancellation is always signalled by throwing a
+ * {@link CancelledResultException} in order to be consistent with other error
+ * results.
+ * <li>A {@link ResultHandler} can be provided to the constructor. The result
+ * handler will be invoked immediately after the result or error is received but
+ * before threads blocked on {@link #get} are released. More specifically,
+ * result handler invocation <i>happens-before</i> a call to {@link #get}.
+ * <b>NOTE:</b> a result handler which attempts to call {@link #get} will
+ * deadlock.
+ * <li>Sub-classes may choose to implement specific cancellation cleanup by
+ * implementing the {@link #handleCancelRequest} method.
  * </ul>
  *
  * @param <M>
  *          The type of result returned by this completion future.
  */
-public abstract class AbstractFutureResult<M> implements
-    FutureResult<M>, ResultHandler<M>
+public abstract class AbstractFutureResult<M> implements FutureResult<M>,
+    ResultHandler<M>
 {
   @SuppressWarnings("serial")
   private final class Sync extends AbstractQueuedSynchronizer
@@ -101,44 +98,11 @@
 
 
 
-    private M get0() throws ErrorResultException
-    {
-      if (errorResult != null)
-      {
-        // State must be FAILED or CANCELLED.
-        throw errorResult;
-      }
-      else
-      {
-        // State must be SUCCESS.
-        return result;
-      }
-    }
-
-
-
-    private boolean setStatePending()
-    {
-      for (;;)
-      {
-        final int s = getState();
-        if (s != WAITING)
-        {
-          return false;
-        }
-        if (compareAndSetState(s, PENDING))
-        {
-          return true;
-        }
-      }
-    }
-
-
-
     /**
      * Allow all threads to acquire if future has completed.
      */
-    protected int tryAcquireShared(int ignore)
+    @Override
+    protected int tryAcquireShared(final int ignore)
     {
       return innerIsDone() ? 1 : -1;
     }
@@ -146,10 +110,11 @@
 
 
     /**
-     * Signal that the future has completed and threads waiting on get()
-     * can be released.
+     * Signal that the future has completed and threads waiting on get() can be
+     * released.
      */
-    protected boolean tryReleaseShared(int finalState)
+    @Override
+    protected boolean tryReleaseShared(final int finalState)
     {
       // Ensures that errorResult/result is published.
       setState(finalState);
@@ -158,7 +123,7 @@
 
 
 
-    boolean innerCancel(boolean mayInterruptIfRunning)
+    boolean innerCancel(final boolean mayInterruptIfRunning)
     {
       if (!setStatePending())
       {
@@ -201,7 +166,7 @@
 
 
 
-    M innerGet(long nanosTimeout) throws ErrorResultException,
+    M innerGet(final long nanosTimeout) throws ErrorResultException,
         TimeoutException, InterruptedException
     {
       if (!tryAcquireSharedNanos(0, nanosTimeout))
@@ -230,7 +195,7 @@
 
 
 
-    void innerSetErrorResult(ErrorResultException errorResult)
+    void innerSetErrorResult(final ErrorResultException errorResult)
     {
       if (setStatePending())
       {
@@ -253,7 +218,7 @@
 
 
 
-    void innerSetResult(M result)
+    void innerSetResult(final M result)
     {
       if (setStatePending())
       {
@@ -273,6 +238,40 @@
         }
       }
     }
+
+
+
+    private M get0() throws ErrorResultException
+    {
+      if (errorResult != null)
+      {
+        // State must be FAILED or CANCELLED.
+        throw errorResult;
+      }
+      else
+      {
+        // State must be SUCCESS.
+        return result;
+      }
+    }
+
+
+
+    private boolean setStatePending()
+    {
+      for (;;)
+      {
+        final int s = getState();
+        if (s != WAITING)
+        {
+          return false;
+        }
+        if (compareAndSetState(s, PENDING))
+        {
+          return true;
+        }
+      }
+    }
   }
 
 
@@ -284,14 +283,13 @@
 
 
   /**
-   * Creates a new abstract future result with the provided result
-   * handler.
+   * Creates a new abstract future result with the provided result handler.
    *
    * @param handler
-   *          A result handler which will be forwarded the result or
-   *          error when it arrives.
+   *          A result handler which will be forwarded the result or error when
+   *          it arrives.
    */
-  protected AbstractFutureResult(ResultHandler<? super M> handler)
+  protected AbstractFutureResult(final ResultHandler<? super M> handler)
   {
     this.handler = handler;
   }
@@ -301,7 +299,7 @@
   /**
    * {@inheritDoc}
    */
-  public final boolean cancel(boolean mayInterruptIfRunning)
+  public final boolean cancel(final boolean mayInterruptIfRunning)
   {
     return sync.innerCancel(mayInterruptIfRunning);
   }
@@ -311,8 +309,7 @@
   /**
    * {@inheritDoc}
    */
-  public final M get() throws ErrorResultException,
-      InterruptedException
+  public final M get() throws ErrorResultException, InterruptedException
   {
     return sync.innerGet();
   }
@@ -322,9 +319,8 @@
   /**
    * {@inheritDoc}
    */
-  public final M get(long timeout, TimeUnit unit)
-      throws ErrorResultException, TimeoutException,
-      InterruptedException
+  public final M get(final long timeout, final TimeUnit unit)
+      throws ErrorResultException, TimeoutException, InterruptedException
   {
     return sync.innerGet(unit.toNanos(timeout));
   }
@@ -332,16 +328,15 @@
 
 
   /**
-   * Sets the error result associated with this future. If ({@code
-   * isDone() == true}) then the error result will be ignored, otherwise
-   * the result handler will be invoked if one was provided and, on
-   * return, any threads waiting on {@link #get} will be released and
-   * the provided error result will be thrown.
+   * Sets the error result associated with this future. If ({@code isDone() ==
+   * true}) then the error result will be ignored, otherwise the result handler
+   * will be invoked if one was provided and, on return, any threads waiting on
+   * {@link #get} will be released and the provided error result will be thrown.
    *
    * @param errorResult
    *          The error result.
    */
-  public final void handleErrorResult(ErrorResultException errorResult)
+  public final void handleErrorResult(final ErrorResultException errorResult)
   {
     sync.innerSetErrorResult(errorResult);
   }
@@ -349,16 +344,15 @@
 
 
   /**
-   * Sets the result associated with this future. If ({@code isDone() ==
-   * true}) then the result will be ignored, otherwise the result
-   * handler will be invoked if one was provided and, on return, any
-   * threads waiting on {@link #get} will be released and the provided
-   * result will be returned.
+   * Sets the result associated with this future. If ({@code isDone() == true})
+   * then the result will be ignored, otherwise the result handler will be
+   * invoked if one was provided and, on return, any threads waiting on
+   * {@link #get} will be released and the provided result will be returned.
    *
    * @param result
    *          The result.
    */
-  public final void handleResult(M result)
+  public final void handleResult(final M result)
   {
     sync.innerSetResult(result);
   }
@@ -386,33 +380,46 @@
 
 
   /**
-   * Invoked when {@link #cancel} is called and {@code isDone() ==
-   * false} and immediately before any threads waiting on {@link #get}
-   * are released. Implementations may choose to return a custom error
-   * result if needed or return {@code null} if the following default
-   * error result is acceptable:
+   * Invoked when {@link #cancel} is called and {@code isDone() == false} and
+   * immediately before any threads waiting on {@link #get} are released.
+   * Implementations may choose to return a custom error result if needed or
+   * return {@code null} if the following default error result is acceptable:
    *
    * <pre>
-   * Result result = Responses
-   *     .newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED);
+   * Result result = Responses.newResult(ResultCode.CLIENT_SIDE_USER_CANCELLED);
    * </pre>
    *
-   * In addition, implementations may perform other cleanup, for
-   * example, by issuing an LDAP abandon request. The default
-   * implementation is to do nothing.
+   * In addition, implementations may perform other cleanup, for example, by
+   * issuing an LDAP abandon request. The default implementation is to do
+   * nothing.
    *
    * @param mayInterruptIfRunning
-   *          {@code true} if the thread executing executing the
-   *          response handler should be interrupted; otherwise,
-   *          in-progress response handlers are allowed to complete.
+   *          {@code true} if the thread executing executing the response
+   *          handler should be interrupted; otherwise, in-progress response
+   *          handlers are allowed to complete.
    * @return The custom error result, or {@code null} if the default is
    *         acceptable.
    */
   protected ErrorResultException handleCancelRequest(
-      boolean mayInterruptIfRunning)
+      final boolean mayInterruptIfRunning)
   {
     // Do nothing by default.
     return null;
   }
 
+
+
+  /**
+   * Appends a string representation of this future's state to the provided
+   * builder.
+   *
+   * @param sb
+   *          The string builder.
+   */
+  protected void toString(final StringBuilder sb)
+  {
+    sb.append(" state = ");
+    sb.append(sync);
+  }
+
 }
diff --git a/sdk/src/com/sun/opends/sdk/util/Base64.java b/sdk/src/com/sun/opends/sdk/util/Base64.java
index 446962e..2ae7a8e 100755
--- a/sdk/src/com/sun/opends/sdk/util/Base64.java
+++ b/sdk/src/com/sun/opends/sdk/util/Base64.java
@@ -28,92 +28,27 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.Validator.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_BASE64_DECODE_INVALID_CHARACTER;
+import static com.sun.opends.sdk.messages.Messages.ERR_BASE64_DECODE_INVALID_LENGTH;
+import static com.sun.opends.sdk.util.Validator.ensureNotNull;
 
 import org.opends.sdk.*;
 
 
 
-
 /**
- * This class provides methods for performing base64 encoding and
- * decoding. Base64 is a mechanism for encoding binary data in ASCII
- * form by converting sets of three bytes with eight significant bits
- * each to sets of four bytes with six significant bits each.
+ * This class provides methods for performing base64 encoding and decoding.
+ * Base64 is a mechanism for encoding binary data in ASCII form by converting
+ * sets of three bytes with eight significant bits each to sets of four bytes
+ * with six significant bits each.
  */
 public final class Base64
 {
   /**
    * The set of characters that may be used in base64-encoded values.
    */
-  private static final char[] BASE64_ALPHABET =
-      ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-          + "0123456789+/").toCharArray();
-
-
-
-  /**
-   * Prevent instance creation.
-   */
-  private Base64()
-  {
-    // No implementation required.
-  }
-
-
-
-  /**
-   * Encodes the provided data as a base64 string.
-   *
-   * @param bytes
-   *          The data to be encoded.
-   * @return The base64 encoded representation of {@code bytes}.
-   * @throws NullPointerException
-   *           If {@code bytes} was {@code null}.
-   */
-  public static String encode(ByteSequence bytes)
-      throws NullPointerException
-  {
-    ensureNotNull(bytes);
-
-    StringBuilder buffer = new StringBuilder(4 * bytes.length() / 3);
-
-    int pos = 0;
-    int iterations = bytes.length() / 3;
-    for (int i = 0; i < iterations; i++)
-    {
-      int value =
-          ((bytes.byteAt(pos++) & 0xFF) << 16)
-              | ((bytes.byteAt(pos++) & 0xFF) << 8)
-              | (bytes.byteAt(pos++) & 0xFF);
-
-      buffer.append(BASE64_ALPHABET[(value >>> 18) & 0x3F]);
-      buffer.append(BASE64_ALPHABET[(value >>> 12) & 0x3F]);
-      buffer.append(BASE64_ALPHABET[(value >>> 6) & 0x3F]);
-      buffer.append(BASE64_ALPHABET[value & 0x3F]);
-    }
-
-    switch (bytes.length() % 3)
-    {
-    case 1:
-      buffer.append(BASE64_ALPHABET[(bytes.byteAt(pos) >>> 2) & 0x3F]);
-      buffer.append(BASE64_ALPHABET[(bytes.byteAt(pos) << 4) & 0x3F]);
-      buffer.append("==");
-      break;
-    case 2:
-      int value =
-          ((bytes.byteAt(pos++) & 0xFF) << 8)
-              | (bytes.byteAt(pos) & 0xFF);
-      buffer.append(BASE64_ALPHABET[(value >>> 10) & 0x3F]);
-      buffer.append(BASE64_ALPHABET[(value >>> 4) & 0x3F]);
-      buffer.append(BASE64_ALPHABET[(value << 2) & 0x3F]);
-      buffer.append("=");
-      break;
-    }
-
-    return buffer.toString();
-  }
+  private static final char[] BASE64_ALPHABET = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+      + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/").toCharArray();
 
 
 
@@ -124,26 +59,26 @@
    *          The base64 encoded data.
    * @return The decoded data.
    * @throws LocalizedIllegalArgumentException
-   *           If a problem occurs while attempting to decode {@code
-   *           base64}.
+   *           If a problem occurs while attempting to decode {@code base64}.
    * @throws NullPointerException
    *           If {@code base64} was {@code null}.
    */
-  public static ByteString decode(String base64)
+  public static ByteString decode(final String base64)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     ensureNotNull(base64);
 
     // The encoded value must have length that is a multiple of four
     // bytes.
-    int length = base64.length();
+    final int length = base64.length();
     if ((length % 4) != 0)
     {
-      LocalizableMessage message = ERR_BASE64_DECODE_INVALID_LENGTH.get(base64);
+      final LocalizableMessage message = ERR_BASE64_DECODE_INVALID_LENGTH
+          .get(base64);
       throw new LocalizedIllegalArgumentException(message);
     }
 
-    ByteStringBuilder builder = new ByteStringBuilder(length);
+    final ByteStringBuilder builder = new ByteStringBuilder(length);
     for (int i = 0; i < length; i += 4)
     {
       boolean append = true;
@@ -359,9 +294,8 @@
           }
           break;
         default:
-          LocalizableMessage message =
-              ERR_BASE64_DECODE_INVALID_CHARACTER.get(base64, base64
-                  .charAt(i + j));
+          final LocalizableMessage message = ERR_BASE64_DECODE_INVALID_CHARACTER
+              .get(base64, base64.charAt(i + j));
           throw new LocalizedIllegalArgumentException(message);
         }
 
@@ -385,4 +319,65 @@
 
     return builder.toByteString();
   }
+
+
+
+  /**
+   * Encodes the provided data as a base64 string.
+   *
+   * @param bytes
+   *          The data to be encoded.
+   * @return The base64 encoded representation of {@code bytes}.
+   * @throws NullPointerException
+   *           If {@code bytes} was {@code null}.
+   */
+  public static String encode(final ByteSequence bytes)
+      throws NullPointerException
+  {
+    ensureNotNull(bytes);
+
+    final StringBuilder buffer = new StringBuilder(4 * bytes.length() / 3);
+
+    int pos = 0;
+    final int iterations = bytes.length() / 3;
+    for (int i = 0; i < iterations; i++)
+    {
+      final int value = ((bytes.byteAt(pos++) & 0xFF) << 16)
+          | ((bytes.byteAt(pos++) & 0xFF) << 8) | (bytes.byteAt(pos++) & 0xFF);
+
+      buffer.append(BASE64_ALPHABET[(value >>> 18) & 0x3F]);
+      buffer.append(BASE64_ALPHABET[(value >>> 12) & 0x3F]);
+      buffer.append(BASE64_ALPHABET[(value >>> 6) & 0x3F]);
+      buffer.append(BASE64_ALPHABET[value & 0x3F]);
+    }
+
+    switch (bytes.length() % 3)
+    {
+    case 1:
+      buffer.append(BASE64_ALPHABET[(bytes.byteAt(pos) >>> 2) & 0x3F]);
+      buffer.append(BASE64_ALPHABET[(bytes.byteAt(pos) << 4) & 0x3F]);
+      buffer.append("==");
+      break;
+    case 2:
+      final int value = ((bytes.byteAt(pos++) & 0xFF) << 8)
+          | (bytes.byteAt(pos) & 0xFF);
+      buffer.append(BASE64_ALPHABET[(value >>> 10) & 0x3F]);
+      buffer.append(BASE64_ALPHABET[(value >>> 4) & 0x3F]);
+      buffer.append(BASE64_ALPHABET[(value << 2) & 0x3F]);
+      buffer.append("=");
+      break;
+    }
+
+    return buffer.toString();
+  }
+
+
+
+  /**
+   * Prevent instance creation.
+   */
+  private Base64()
+  {
+    // No implementation required.
+  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/util/ByteSequenceOutputStream.java b/sdk/src/com/sun/opends/sdk/util/ByteSequenceOutputStream.java
index 6b4c784..018c0ea 100644
--- a/sdk/src/com/sun/opends/sdk/util/ByteSequenceOutputStream.java
+++ b/sdk/src/com/sun/opends/sdk/util/ByteSequenceOutputStream.java
@@ -26,90 +26,119 @@
  */
 package com.sun.opends.sdk.util;
 
+
+
 import java.io.IOException;
 import java.io.OutputStream;
 
 import org.opends.sdk.ByteStringBuilder;
 
+
+
 /**
- * An adapter class that allows writing to an byte string builder
- * with the outputstream interface.
+ * An adapter class that allows writing to an byte string builder with the
+ * outputstream interface.
  */
-public final class ByteSequenceOutputStream extends OutputStream {
+public final class ByteSequenceOutputStream extends OutputStream
+{
 
   private final ByteStringBuilder buffer;
 
+
+
   /**
    * Creates a new byte string builder output stream.
    *
    * @param buffer
    *          The underlying byte string builder.
    */
-  public ByteSequenceOutputStream(ByteStringBuilder buffer)
+  public ByteSequenceOutputStream(final ByteStringBuilder buffer)
   {
     this.buffer = buffer;
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  public void write(int i) throws IOException {
-    buffer.append(((byte) (i & 0xFF)));
-  }
+
 
   /**
    * {@inheritDoc}
    */
-  public void write(byte[] bytes) throws IOException {
-    buffer.append(bytes);
+  @Override
+  public void close() throws IOException
+  {
+    buffer.clear();
   }
 
-  /**
-   * {@inheritDoc}
-   */
-  public void write(byte[] bytes, int i, int i1) throws IOException {
-    buffer.append(bytes, i, i1);
-  }
+
 
   /**
    * Gets the length of the underlying byte string builder.
    *
    * @return The length of the underlying byte string builder.
    */
-  public int length() {
+  public int length()
+  {
     return buffer.length();
   }
 
 
 
   /**
-   * Writes the content of the underlying byte string builder to the
-   * provided output stream.
-   *
-   * @param stream
-   *          The output stream.
-   * @throws IOException
-   *           If an I/O error occurs. In particular, an {@code
-   *           IOException} is thrown if the output stream is closed.
-   */
-  public void writeTo(OutputStream stream) throws IOException
-  {
-    buffer.copyTo(stream);
-  }
-
-  /**
-   * Resets this output stream such that the underlying byte string
-   * builder is empty.
+   * Resets this output stream such that the underlying byte string builder is
+   * empty.
    */
   public void reset()
   {
     buffer.clear();
   }
 
+
+
   /**
    * {@inheritDoc}
    */
-  public void close() throws IOException {
-    buffer.clear();
+  @Override
+  public void write(final byte[] bytes) throws IOException
+  {
+    buffer.append(bytes);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void write(final byte[] bytes, final int i, final int i1)
+      throws IOException
+  {
+    buffer.append(bytes, i, i1);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public void write(final int i) throws IOException
+  {
+    buffer.append(((byte) (i & 0xFF)));
+  }
+
+
+
+  /**
+   * Writes the content of the underlying byte string builder to the provided
+   * output stream.
+   *
+   * @param stream
+   *          The output stream.
+   * @throws IOException
+   *           If an I/O error occurs. In particular, an {@code IOException} is
+   *           thrown if the output stream is closed.
+   */
+  public void writeTo(final OutputStream stream) throws IOException
+  {
+    buffer.copyTo(stream);
   }
 }
diff --git a/sdk/src/com/sun/opends/sdk/util/Collections2.java b/sdk/src/com/sun/opends/sdk/util/Collections2.java
index 847aa4e..27a7724 100644
--- a/sdk/src/com/sun/opends/sdk/util/Collections2.java
+++ b/sdk/src/com/sun/opends/sdk/util/Collections2.java
@@ -54,9 +54,9 @@
 
 
 
-    private TransformedCollection(Collection<M> collection,
-        Function<? super M, ? extends N, P> funcMtoN,
-        Function<? super N, ? extends M, P> funcNtoM, P p)
+    private TransformedCollection(final Collection<M> collection,
+        final Function<? super M, ? extends N, P> funcMtoN,
+        final Function<? super N, ? extends M, P> funcNtoM, final P p)
     {
       this.collection = collection;
       this.funcMtoN = funcMtoN;
@@ -69,7 +69,8 @@
     /**
      * {@inheritDoc}
      */
-    public boolean add(N e)
+    @Override
+    public boolean add(final N e)
     {
       return collection.add(funcNtoM.apply(e, p));
     }
@@ -79,6 +80,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public void clear()
     {
       collection.clear();
@@ -89,10 +91,11 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     @SuppressWarnings("unchecked")
-    public boolean contains(Object o)
+    public boolean contains(final Object o)
     {
-      N tmp = (N) o;
+      final N tmp = (N) o;
       return collection.contains(funcNtoM.apply(tmp, p));
     }
 
@@ -101,6 +104,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean isEmpty()
     {
       return collection.isEmpty();
@@ -111,6 +115,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public Iterator<N> iterator()
     {
       return Iterators.transform(collection.iterator(), funcMtoN, p);
@@ -121,10 +126,11 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     @SuppressWarnings("unchecked")
-    public boolean remove(Object o)
+    public boolean remove(final Object o)
     {
-      N tmp = (N) o;
+      final N tmp = (N) o;
       return collection.remove(funcNtoM.apply(tmp, p));
     }
 
@@ -133,6 +139,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public int size()
     {
       return collection.size();
@@ -143,49 +150,47 @@
 
 
   /**
-   * Returns a view of {@code collection} whose values have been mapped
-   * to elements of type {@code N} using {@code funcMtoN}. The returned
-   * collection supports all operations.
+   * Returns a view of {@code collection} whose values have been mapped to
+   * elements of type {@code N} using {@code funcMtoN}. The returned collection
+   * supports all operations.
    *
    * @param <M>
    *          The type of elements contained in {@code collection}.
    * @param <N>
    *          The type of elements contained in the returned collection.
    * @param <P>
-   *          The type of the additional parameter to the function's
-   *          {@code apply} method. Use {@link java.lang.Void} for
-   *          functions that do not need an additional parameter.
+   *          The type of the additional parameter to the function's {@code
+   *          apply} method. Use {@link java.lang.Void} for functions that do
+   *          not need an additional parameter.
    * @param collection
    *          The collection to be transformed.
    * @param funcMtoN
-   *          A function which maps values of type {@code M} to values
-   *          of type {@code N}. This function will be used when
-   *          retrieving values from {@code collection}.
+   *          A function which maps values of type {@code M} to values of type
+   *          {@code N}. This function will be used when retrieving values from
+   *          {@code collection}.
    * @param funcNtoM
-   *          A function which maps values of type {@code N} to values
-   *          of type {@code M}. This function will be used when
-   *          performing queries and adding values to {@code collection}
-   *          .
+   *          A function which maps values of type {@code N} to values of type
+   *          {@code M}. This function will be used when performing queries and
+   *          adding values to {@code collection} .
    * @param p
    *          A predicate specified parameter.
-   * @return A view of {@code collection} whose values have been mapped
-   *         to elements of type {@code N} using {@code funcMtoN}.
+   * @return A view of {@code collection} whose values have been mapped to
+   *         elements of type {@code N} using {@code funcMtoN}.
    */
   public static <M, N, P> Collection<N> transform(
-      Collection<M> collection,
-      Function<? super M, ? extends N, P> funcMtoN,
-      Function<? super N, ? extends M, P> funcNtoM, P p)
+      final Collection<M> collection,
+      final Function<? super M, ? extends N, P> funcMtoN,
+      final Function<? super N, ? extends M, P> funcNtoM, final P p)
   {
-    return new TransformedCollection<M, N, P>(collection, funcMtoN,
-        funcNtoM, p);
+    return new TransformedCollection<M, N, P>(collection, funcMtoN, funcNtoM, p);
   }
 
 
 
   /**
-   * Returns a view of {@code collection} whose values have been mapped
-   * to elements of type {@code N} using {@code funcMtoN}. The returned
-   * collection supports all operations.
+   * Returns a view of {@code collection} whose values have been mapped to
+   * elements of type {@code N} using {@code funcMtoN}. The returned collection
+   * supports all operations.
    *
    * @param <M>
    *          The type of elements contained in {@code collection}.
@@ -194,21 +199,19 @@
    * @param collection
    *          The collection to be transformed.
    * @param funcMtoN
-   *          A function which maps values of type {@code M} to values
-   *          of type {@code N}. This function will be used when
-   *          retrieving values from {@code collection}.
+   *          A function which maps values of type {@code M} to values of type
+   *          {@code N}. This function will be used when retrieving values from
+   *          {@code collection}.
    * @param funcNtoM
-   *          A function which maps values of type {@code N} to values
-   *          of type {@code M}. This function will be used when
-   *          performing queries and adding values to {@code collection}
-   *          .
-   * @return A view of {@code collection} whose values have been mapped
-   *         to elements of type {@code N} using {@code funcMtoN}.
+   *          A function which maps values of type {@code N} to values of type
+   *          {@code M}. This function will be used when performing queries and
+   *          adding values to {@code collection} .
+   * @return A view of {@code collection} whose values have been mapped to
+   *         elements of type {@code N} using {@code funcMtoN}.
    */
-  public static <M, N> Collection<N> transform(
-      Collection<M> collection,
-      Function<? super M, ? extends N, Void> funcMtoN,
-      Function<? super N, ? extends M, Void> funcNtoM)
+  public static <M, N> Collection<N> transform(final Collection<M> collection,
+      final Function<? super M, ? extends N, Void> funcMtoN,
+      final Function<? super N, ? extends M, Void> funcNtoM)
   {
     return new TransformedCollection<M, N, Void>(collection, funcMtoN,
         funcNtoM, null);
diff --git a/sdk/src/com/sun/opends/sdk/util/CompletedFutureResult.java b/sdk/src/com/sun/opends/sdk/util/CompletedFutureResult.java
index 83d254d..756d461 100644
--- a/sdk/src/com/sun/opends/sdk/util/CompletedFutureResult.java
+++ b/sdk/src/com/sun/opends/sdk/util/CompletedFutureResult.java
@@ -38,9 +38,9 @@
 
 
 /**
- * An implementation of {@code FutureResult} which can be used in cases
- * where the result is known in advance, for example, if the result is
- * obtained synchronously.
+ * An implementation of {@code FutureResult} which can be used in cases where
+ * the result is known in advance, for example, if the result is obtained
+ * synchronously.
  *
  * @param <S>
  *          The type of result returned by this future.
@@ -56,29 +56,15 @@
 
 
   /**
-   * Creates a new completed future which will return the provided
-   * result and request ID of {@code -1}.
-   *
-   * @param result
-   *          The result, which may be {@code null}.
-   */
-  public CompletedFutureResult(S result)
-  {
-    this(result, -1);
-  }
-
-
-
-  /**
-   * Creates a new completed future which will throw the provided error
-   * result and request ID of {@code -1}.
+   * Creates a new completed future which will throw the provided error result
+   * and request ID of {@code -1}.
    *
    * @param errorResult
    *          The error result.
    * @throws NullPointerException
    *           If {@code errorResult} was {@code null}.
    */
-  public CompletedFutureResult(ErrorResultException errorResult)
+  public CompletedFutureResult(final ErrorResultException errorResult)
       throws NullPointerException
   {
     this(errorResult, -1);
@@ -87,26 +73,8 @@
 
 
   /**
-   * Creates a new completed future which will return the provided
-   * result and request ID.
-   *
-   * @param result
-   *          The result, which may be {@code null}.
-   * @param requestID
-   *          The request ID.
-   */
-  public CompletedFutureResult(S result, int requestID)
-  {
-    this.result = result;
-    this.errorResult = null;
-    this.requestID = requestID;
-  }
-
-
-
-  /**
-   * Creates a new completed future which will throw the provided error
-   * result and request ID.
+   * Creates a new completed future which will throw the provided error result
+   * and request ID.
    *
    * @param errorResult
    *          The error result.
@@ -115,8 +83,8 @@
    * @throws NullPointerException
    *           If {@code errorResult} was {@code null}.
    */
-  public CompletedFutureResult(ErrorResultException errorResult,
-      int requestID) throws NullPointerException
+  public CompletedFutureResult(final ErrorResultException errorResult,
+      final int requestID) throws NullPointerException
   {
     Validator.ensureNotNull(errorResult);
     this.result = null;
@@ -126,13 +94,51 @@
 
 
 
-  public boolean cancel(boolean mayInterruptIfRunning)
+  /**
+   * Creates a new completed future which will return the provided result and
+   * request ID of {@code -1}.
+   *
+   * @param result
+   *          The result, which may be {@code null}.
+   */
+  public CompletedFutureResult(final S result)
+  {
+    this(result, -1);
+  }
+
+
+
+  /**
+   * Creates a new completed future which will return the provided result and
+   * request ID.
+   *
+   * @param result
+   *          The result, which may be {@code null}.
+   * @param requestID
+   *          The request ID.
+   */
+  public CompletedFutureResult(final S result, final int requestID)
+  {
+    this.result = result;
+    this.errorResult = null;
+    this.requestID = requestID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean cancel(final boolean mayInterruptIfRunning)
   {
     return false;
   }
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   public S get() throws ErrorResultException, InterruptedException
   {
     if (errorResult == null)
@@ -148,15 +154,20 @@
 
 
 
-  public S get(long timeout, TimeUnit unit)
-      throws ErrorResultException, TimeoutException,
-      InterruptedException
+  /**
+   * {@inheritDoc}
+   */
+  public S get(final long timeout, final TimeUnit unit)
+      throws ErrorResultException, TimeoutException, InterruptedException
   {
     return get();
   }
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   public int getRequestID()
   {
     return requestID;
@@ -164,6 +175,9 @@
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   public boolean isCancelled()
   {
     return false;
@@ -171,6 +185,9 @@
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   public boolean isDone()
   {
     return true;
diff --git a/sdk/src/com/sun/opends/sdk/util/Function.java b/sdk/src/com/sun/opends/sdk/util/Function.java
index 01e77dd..eb20f63 100644
--- a/sdk/src/com/sun/opends/sdk/util/Function.java
+++ b/sdk/src/com/sun/opends/sdk/util/Function.java
@@ -30,23 +30,23 @@
 
 
 /**
- * Functions transform input values of type {@code M} to output values
- * of type {@code N}.
+ * Functions transform input values of type {@code M} to output values of type
+ * {@code N}.
  *
  * @param <M>
  *          The type of input values transformed by this function.
  * @param <N>
  *          The type of output values return by this function.
  * @param <P>
- *          The type of the additional parameter to this function's
- *          {@code apply} method. Use {@link java.lang.Void} for
- *          functions that do not need an additional parameter.
+ *          The type of the additional parameter to this function's {@code
+ *          apply} method. Use {@link java.lang.Void} for functions that do not
+ *          need an additional parameter.
  */
 public interface Function<M, N, P>
 {
   /**
-   * Applies this function to the provided input value of type {@code M}
-   * , returning an output value of type {@code N}.
+   * Applies this function to the provided input value of type {@code M} ,
+   * returning an output value of type {@code N}.
    *
    * @param value
    *          The value to be transformed.
diff --git a/sdk/src/com/sun/opends/sdk/util/Functions.java b/sdk/src/com/sun/opends/sdk/util/Functions.java
index 3353564..d90d987 100644
--- a/sdk/src/com/sun/opends/sdk/util/Functions.java
+++ b/sdk/src/com/sun/opends/sdk/util/Functions.java
@@ -51,7 +51,7 @@
 
 
 
-    private FixedFunction(Function<M, N, P> function, P p)
+    private FixedFunction(final Function<M, N, P> function, final P p)
     {
       this.function = function;
       this.parameter = p;
@@ -62,7 +62,7 @@
     /**
      * {@inheritDoc}
      */
-    public N apply(M value, Void p)
+    public N apply(final M value, final Void p)
     {
       return function.apply(value, parameter);
     }
@@ -71,22 +71,25 @@
 
 
 
-  private static final Function<ByteString, AttributeDescription, Schema> BYTESTRING_TO_ATTRIBUTE_DESCRIPTION = new Function<ByteString, AttributeDescription, Schema>()
+  private static final Function<ByteString, AttributeDescription, Schema>
+    BYTESTRING_TO_ATTRIBUTE_DESCRIPTION =
+      new Function<ByteString, AttributeDescription, Schema>()
   {
 
-    public AttributeDescription apply(ByteString value, Schema p)
+    public AttributeDescription apply(final ByteString value, final Schema p)
     {
       // FIXME: what should we do if parsing fails?
       return AttributeDescription.valueOf(value.toString(), p);
     }
   };
 
-  private static final Function<ByteString, Boolean, Void> BYTESTRING_TO_BOOLEAN = new Function<ByteString, Boolean, Void>()
+  private static final Function<ByteString, Boolean, Void>
+    BYTESTRING_TO_BOOLEAN = new Function<ByteString, Boolean, Void>()
   {
 
-    public Boolean apply(ByteString value, Void p)
+    public Boolean apply(final ByteString value, final Void p)
     {
-      String valueString = StaticUtils.toLowerCase(value.toString());
+      final String valueString = StaticUtils.toLowerCase(value.toString());
 
       if (valueString.equals("true") || valueString.equals("yes")
           || valueString.equals("on") || valueString.equals("1"))
@@ -106,10 +109,11 @@
     }
   };
 
-  private static final Function<ByteString, DN, Schema> BYTESTRING_TO_DN = new Function<ByteString, DN, Schema>()
+  private static final Function<ByteString, DN, Schema> BYTESTRING_TO_DN =
+    new Function<ByteString, DN, Schema>()
   {
 
-    public DN apply(ByteString value, Schema p)
+    public DN apply(final ByteString value, final Schema p)
     {
       // FIXME: what should we do if parsing fails?
 
@@ -118,48 +122,53 @@
     }
   };
 
-  private static final Function<ByteString, Integer, Void> BYTESTRING_TO_INTEGER = new Function<ByteString, Integer, Void>()
+  private static final Function<ByteString, Integer, Void>
+    BYTESTRING_TO_INTEGER = new Function<ByteString, Integer, Void>()
   {
 
-    public Integer apply(ByteString value, Void p)
+    public Integer apply(final ByteString value, final Void p)
     {
       // We do not use ByteString.toInt() as we are string based.
       return Integer.valueOf(value.toString());
     }
   };
 
-  private static final Function<ByteString, Long, Void> BYTESTRING_TO_LONG = new Function<ByteString, Long, Void>()
+  private static final Function<ByteString, Long, Void> BYTESTRING_TO_LONG =
+    new Function<ByteString, Long, Void>()
   {
 
-    public Long apply(ByteString value, Void p)
+    public Long apply(final ByteString value, final Void p)
     {
       // We do not use ByteString.toLong() as we are string based.
       return Long.valueOf(value.toString());
     }
   };
 
-  private static final Function<ByteString, String, Void> BYTESTRING_TO_STRING = new Function<ByteString, String, Void>()
+  private static final Function<ByteString, String, Void> BYTESTRING_TO_STRING =
+    new Function<ByteString, String, Void>()
   {
 
-    public String apply(ByteString value, Void p)
+    public String apply(final ByteString value, final Void p)
     {
       return value.toString();
     }
   };
 
-  private static final Function<Object, ByteString, Void> OBJECT_TO_BYTESTRING = new Function<Object, ByteString, Void>()
+  private static final Function<Object, ByteString, Void> OBJECT_TO_BYTESTRING =
+    new Function<Object, ByteString, Void>()
   {
 
-    public ByteString apply(Object value, Void p)
+    public ByteString apply(final Object value, final Void p)
     {
       return ByteString.valueOf(value);
     }
   };
 
-  private static final Function<String, String, Void> NORMALIZE_STRING = new Function<String, String, Void>()
+  private static final Function<String, String, Void> NORMALIZE_STRING =
+    new Function<String, String, Void>()
   {
 
-    public String apply(String value, Void p)
+    public String apply(final String value, final Void p)
     {
       return StaticUtils.toLowerCase(value).trim();
     }
@@ -168,27 +177,26 @@
 
 
   /**
-   * Returns a function which which always invokes {@code function} with
-   * {@code p}.
+   * Returns a function which which always invokes {@code function} with {@code
+   * p}.
    *
    * @param <M>
    *          The type of input values transformed by this function.
    * @param <N>
    *          The type of output values return by this function.
    * @param <P>
-   *          The type of the additional parameter to this function's
-   *          {@code apply} method. Use {@link java.lang.Void} for
-   *          functions that do not need an additional parameter.
+   *          The type of the additional parameter to this function's {@code
+   *          apply} method. Use {@link java.lang.Void} for functions that do
+   *          not need an additional parameter.
    * @param function
    *          The function to wrap.
    * @param p
-   *          The parameter which will always be passed to {@code
-   *          function}.
-   * @return A function which which always invokes {@code function} with
-   *         {@code p}.
+   *          The parameter which will always be passed to {@code function}.
+   * @return A function which which always invokes {@code function} with {@code
+   *         p}.
    */
   public static <M, N, P> Function<M, N, Void> fixedFunction(
-      Function<M, N, P> function, P p)
+      final Function<M, N, P> function, final P p)
   {
     return new FixedFunction<M, N, P>(function, p);
   }
@@ -196,11 +204,11 @@
 
 
   /**
-   * Returns a function which converts a {@code String} to lower case
-   * using {@link StaticUtils#toLowerCase} and then trims it.
+   * Returns a function which converts a {@code String} to lower case using
+   * {@link StaticUtils#toLowerCase} and then trims it.
    *
-   * @return A function which converts a {@code String} to lower case
-   *         using {@link StaticUtils#toLowerCase} and then trims it.
+   * @return A function which converts a {@code String} to lower case using
+   *         {@link StaticUtils#toLowerCase} and then trims it.
    */
   public static Function<String, String, Void> normalizeString()
   {
@@ -210,13 +218,26 @@
 
 
   /**
-   * Returns a function which parses the string representation of a
-   * {@code ByteString} as an {@code AttributeDescription} using the
-   * default schema. Invalid values will result in a {@code
-   * LocalizedIllegalArgumentException}.
+   * Returns a function which converts an {@code Object} to a {@code ByteString}
+   * using the {@link ByteString#valueOf(Object)} method.
    *
-   * @return A function which parses the string representation of a
-   *         {@code ByteString} as an {@code AttributeDescription}.
+   * @return A function which converts an {@code Object} to a {@code ByteString}
+   *         .
+   */
+  public static Function<Object, ByteString, Void> objectToByteString()
+  {
+    return OBJECT_TO_BYTESTRING;
+  }
+
+
+
+  /**
+   * Returns a function which parses the string representation of a {@code
+   * ByteString} as an {@code AttributeDescription} using the default schema.
+   * Invalid values will result in a {@code LocalizedIllegalArgumentException}.
+   *
+   * @return A function which parses the string representation of a {@code
+   *         ByteString} as an {@code AttributeDescription}.
    */
   public static Function<ByteString, AttributeDescription, Void> valueToAttributeDescription()
   {
@@ -227,18 +248,17 @@
 
 
   /**
-   * Returns a function which parses the string representation of a
-   * {@code ByteString} as an {@code AttributeDescription} using the
-   * provided schema. Invalid values will result in a {@code
-   * LocalizedIllegalArgumentException}.
+   * Returns a function which parses the string representation of a {@code
+   * ByteString} as an {@code AttributeDescription} using the provided schema.
+   * Invalid values will result in a {@code LocalizedIllegalArgumentException}.
    *
    * @param schema
    *          The schema to use for decoding attribute descriptions.
-   * @return A function which parses the string representation of a
-   *         {@code ByteString} as an {@code AttributeDescription}.
+   * @return A function which parses the string representation of a {@code
+   *         ByteString} as an {@code AttributeDescription}.
    */
   public static Function<ByteString, AttributeDescription, Void> valueToAttributeDescription(
-      Schema schema)
+      final Schema schema)
   {
     return fixedFunction(BYTESTRING_TO_ATTRIBUTE_DESCRIPTION, schema);
   }
@@ -246,14 +266,14 @@
 
 
   /**
-   * Returns a function which parses the string representation of a
-   * {@code ByteString} to a {@code Boolean}. The function will accept
-   * the values {@code 0}, {@code false}, {@code no}, {@code off},
-   * {@code 1}, {@code true}, {@code yes}, {@code on}. All other values
-   * will result in a {@code NumberFormatException}.
+   * Returns a function which parses the string representation of a {@code
+   * ByteString} to a {@code Boolean}. The function will accept the values
+   * {@code 0}, {@code false}, {@code no}, {@code off}, {@code 1}, {@code true},
+   * {@code yes}, {@code on}. All other values will result in a {@code
+   * NumberFormatException}.
    *
-   * @return A function which transforms a {@code ByteString} to a
-   *         {@code Boolean}.
+   * @return A function which transforms a {@code ByteString} to a {@code
+   *         Boolean}.
    */
   public static Function<ByteString, Boolean, Void> valueToBoolean()
   {
@@ -263,13 +283,12 @@
 
 
   /**
-   * Returns a function which parses the string representation of a
-   * {@code ByteString} as a {@code DN} using the default schema.
-   * Invalid values will result in a {@code
-   * LocalizedIllegalArgumentException}.
+   * Returns a function which parses the string representation of a {@code
+   * ByteString} as a {@code DN} using the default schema. Invalid values will
+   * result in a {@code LocalizedIllegalArgumentException}.
    *
-   * @return A function which parses the string representation of a
-   *         {@code ByteString} as an {@code DN}.
+   * @return A function which parses the string representation of a {@code
+   *         ByteString} as an {@code DN}.
    */
   public static Function<ByteString, DN, Void> valueToDN()
   {
@@ -279,17 +298,16 @@
 
 
   /**
-   * Returns a function which parses the string representation of a
-   * {@code ByteString} as a {@code DN} using the provided schema.
-   * Invalid values will result in a {@code
-   * LocalizedIllegalArgumentException}.
+   * Returns a function which parses the string representation of a {@code
+   * ByteString} as a {@code DN} using the provided schema. Invalid values will
+   * result in a {@code LocalizedIllegalArgumentException}.
    *
    * @param schema
    *          The schema to use for decoding DNs.
-   * @return A function which parses the string representation of a
-   *         {@code ByteString} as an {@code DN}.
+   * @return A function which parses the string representation of a {@code
+   *         ByteString} as an {@code DN}.
    */
-  public static Function<ByteString, DN, Void> valueToDN(Schema schema)
+  public static Function<ByteString, DN, Void> valueToDN(final Schema schema)
   {
     return fixedFunction(BYTESTRING_TO_DN, schema);
   }
@@ -297,12 +315,12 @@
 
 
   /**
-   * Returns a function which parses the string representation of a
-   * {@code ByteString} as an {@code Integer}. Invalid values will
-   * result in a {@code NumberFormatException}.
+   * Returns a function which parses the string representation of a {@code
+   * ByteString} as an {@code Integer}. Invalid values will result in a {@code
+   * NumberFormatException}.
    *
-   * @return A function which parses the string representation of a
-   *         {@code ByteString} as an {@code Integer}.
+   * @return A function which parses the string representation of a {@code
+   *         ByteString} as an {@code Integer}.
    */
   public static Function<ByteString, Integer, Void> valueToInteger()
   {
@@ -312,12 +330,12 @@
 
 
   /**
-   * Returns a function which parses the string representation of a
-   * {@code ByteString} as a {@code Long}. Invalid values will result in
-   * a {@code NumberFormatException}.
+   * Returns a function which parses the string representation of a {@code
+   * ByteString} as a {@code Long}. Invalid values will result in a {@code
+   * NumberFormatException}.
    *
-   * @return A function which parses the string representation of a
-   *         {@code ByteString} as a {@code Long}.
+   * @return A function which parses the string representation of a {@code
+   *         ByteString} as a {@code Long}.
    */
   public static Function<ByteString, Long, Void> valueToLong()
   {
@@ -327,11 +345,11 @@
 
 
   /**
-   * Returns a function which parses a {@code ByteString} as a UTF-8
-   * encoded {@code String}.
+   * Returns a function which parses a {@code ByteString} as a UTF-8 encoded
+   * {@code String}.
    *
-   * @return A function which parses the string representation of a
-   *         {@code ByteString} as a UTF-8 encoded {@code String}.
+   * @return A function which parses the string representation of a {@code
+   *         ByteString} as a UTF-8 encoded {@code String}.
    */
   public static Function<ByteString, String, Void> valueToString()
   {
@@ -340,20 +358,6 @@
 
 
 
-  /**
-   * Returns a function which converts an {@code Object} to a {@code
-   * ByteString} using the {@link ByteString#valueOf(Object)} method.
-   *
-   * @return A function which converts an {@code Object} to a {@code
-   *         ByteString}.
-   */
-  public static Function<Object, ByteString, Void> objectToByteString()
-  {
-    return OBJECT_TO_BYTESTRING;
-  }
-
-
-
   // Prevent instantiation
   private Functions()
   {
diff --git a/sdk/src/com/sun/opends/sdk/util/FutureResultTransformer.java b/sdk/src/com/sun/opends/sdk/util/FutureResultTransformer.java
index cb5491d..07ba47e 100644
--- a/sdk/src/com/sun/opends/sdk/util/FutureResultTransformer.java
+++ b/sdk/src/com/sun/opends/sdk/util/FutureResultTransformer.java
@@ -39,18 +39,17 @@
 
 
 /**
- * An implementation of the {@code FutureResult} interface which
- * transforms the result of an asynchronous operation from one type to
- * another. The implementation ensures that the transformed is computed
- * only once.
+ * An implementation of the {@code FutureResult} interface which transforms the
+ * result of an asynchronous operation from one type to another. The
+ * implementation ensures that the transformed is computed only once.
  *
  * @param <M>
  *          The type of the inner result.
  * @param <N>
  *          The type of the outer result.
  */
-public abstract class FutureResultTransformer<M, N> implements
-    FutureResult<N>, ResultHandler<M>
+public abstract class FutureResultTransformer<M, N> implements FutureResult<N>,
+    ResultHandler<M>
 {
 
   private final ResultHandler<? super N> handler;
@@ -66,13 +65,13 @@
 
 
   /**
-   * Creates a new result transformer which will transform the results
-   * of an inner asynchronous request.
+   * Creates a new result transformer which will transform the results of an
+   * inner asynchronous request.
    *
    * @param handler
    *          The outer result handler.
    */
-  protected FutureResultTransformer(ResultHandler<? super N> handler)
+  protected FutureResultTransformer(final ResultHandler<? super N> handler)
   {
     this.handler = handler;
   }
@@ -82,7 +81,7 @@
   /**
    * {@inheritDoc}
    */
-  public final boolean cancel(boolean mayInterruptIfRunning)
+  public final boolean cancel(final boolean mayInterruptIfRunning)
   {
     return future.cancel(mayInterruptIfRunning);
   }
@@ -92,8 +91,7 @@
   /**
    * {@inheritDoc}
    */
-  public final N get() throws ErrorResultException,
-      InterruptedException
+  public final N get() throws ErrorResultException, InterruptedException
   {
     future.get();
 
@@ -106,9 +104,8 @@
   /**
    * {@inheritDoc}
    */
-  public final N get(long timeout, TimeUnit unit)
-      throws ErrorResultException, TimeoutException,
-      InterruptedException
+  public final N get(final long timeout, final TimeUnit unit)
+      throws ErrorResultException, TimeoutException, InterruptedException
   {
     future.get(timeout, unit);
 
@@ -131,7 +128,7 @@
   /**
    * {@inheritDoc}
    */
-  public final void handleErrorResult(ErrorResultException error)
+  public final void handleErrorResult(final ErrorResultException error)
   {
     transformedErrorResult = transformErrorResult(error);
     if (handler != null)
@@ -145,7 +142,7 @@
   /**
    * {@inheritDoc}
    */
-  public final void handleResult(M result)
+  public final void handleResult(final M result)
   {
     try
     {
@@ -188,19 +185,49 @@
 
 
   /**
-   * Sets the inner future for this result transformer. This must be
-   * done before this future is published.
+   * Sets the inner future for this result transformer. This must be done before
+   * this future is published.
    *
    * @param future
    *          The inner future.
    */
-  public final void setFutureResult(FutureResult<? extends M> future)
+  public final void setFutureResult(final FutureResult<? extends M> future)
   {
     this.future = future;
   }
 
 
 
+  /**
+   * Transforms the inner error result to an outer error result. The default
+   * implementation is to return the inner error result.
+   *
+   * @param errorResult
+   *          The inner error result.
+   * @return The outer error result.
+   */
+  protected ErrorResultException transformErrorResult(
+      final ErrorResultException errorResult)
+  {
+    return errorResult;
+  }
+
+
+
+  /**
+   * Transforms the inner result to an outer result, possibly throwing an
+   * {@code ErrorResultException} if the transformation fails for some reason.
+   *
+   * @param result
+   *          The inner result.
+   * @return The outer result.
+   * @throws ErrorResultException
+   *           If the transformation fails for some reason.
+   */
+  protected abstract N transformResult(M result) throws ErrorResultException;
+
+
+
   private N get0() throws ErrorResultException
   {
     if (transformedErrorResult != null)
@@ -213,36 +240,4 @@
     }
   }
 
-
-
-  /**
-   * Transforms the inner error result to an outer error result. The
-   * default implementation is to return the inner error result.
-   *
-   * @param errorResult
-   *          The inner error result.
-   * @return The outer error result.
-   */
-  protected ErrorResultException transformErrorResult(
-      ErrorResultException errorResult)
-  {
-    return errorResult;
-  }
-
-
-
-  /**
-   * Transforms the inner result to an outer result, possibly throwing
-   * an {@code ErrorResultException} if the transformation fails for
-   * some reason.
-   *
-   * @param result
-   *          The inner result.
-   * @return The outer result.
-   * @throws ErrorResultException
-   *           If the transformation fails for some reason.
-   */
-  protected abstract N transformResult(M result)
-      throws ErrorResultException;
-
 }
diff --git a/sdk/src/com/sun/opends/sdk/util/Iterables.java b/sdk/src/com/sun/opends/sdk/util/Iterables.java
index 9acf838..84f2bc9 100644
--- a/sdk/src/com/sun/opends/sdk/util/Iterables.java
+++ b/sdk/src/com/sun/opends/sdk/util/Iterables.java
@@ -38,83 +38,6 @@
  */
 public final class Iterables
 {
-  private static final class EmptyIterable<M> implements Iterable<M>
-  {
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<M> iterator()
-    {
-      return Iterators.empty();
-    }
-
-  }
-
-
-
-  private static final class FilteredIterable<M, P> implements
-      Iterable<M>
-  {
-
-    private final Iterable<M> iterable;
-    private final P parameter;
-    private final Predicate<? super M, P> predicate;
-
-
-
-    // Constructed via factory methods.
-    private FilteredIterable(Iterable<M> iterable,
-        Predicate<? super M, P> predicate, P p)
-    {
-      this.iterable = iterable;
-      this.predicate = predicate;
-      this.parameter = p;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<M> iterator()
-    {
-      return Iterators
-          .filter(iterable.iterator(), predicate, parameter);
-    }
-
-  }
-
-
-
-  private static final class SingletonIterable<M> implements
-      Iterable<M>
-  {
-
-    private final M value;
-
-
-
-    // Constructed via factory methods.
-    private SingletonIterable(M value)
-    {
-      this.value = value;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Iterator<M> iterator()
-    {
-      return Iterators.singleton(value);
-    }
-
-  }
-
-
-
   private static final class ArrayIterable<M> implements Iterable<M>
   {
 
@@ -123,7 +46,7 @@
 
 
     // Constructed via factory methods.
-    private ArrayIterable(M[] a)
+    private ArrayIterable(final M[] a)
     {
       this.a = a;
     }
@@ -142,6 +65,80 @@
 
 
 
+  private static final class EmptyIterable<M> implements Iterable<M>
+  {
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<M> iterator()
+    {
+      return Iterators.empty();
+    }
+
+  }
+
+
+
+  private static final class FilteredIterable<M, P> implements Iterable<M>
+  {
+
+    private final Iterable<M> iterable;
+    private final P parameter;
+    private final Predicate<? super M, P> predicate;
+
+
+
+    // Constructed via factory methods.
+    private FilteredIterable(final Iterable<M> iterable,
+        final Predicate<? super M, P> predicate, final P p)
+    {
+      this.iterable = iterable;
+      this.predicate = predicate;
+      this.parameter = p;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<M> iterator()
+    {
+      return Iterators.filter(iterable.iterator(), predicate, parameter);
+    }
+
+  }
+
+
+
+  private static final class SingletonIterable<M> implements Iterable<M>
+  {
+
+    private final M value;
+
+
+
+    // Constructed via factory methods.
+    private SingletonIterable(final M value)
+    {
+      this.value = value;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Iterator<M> iterator()
+    {
+      return Iterators.singleton(value);
+    }
+
+  }
+
+
+
   private static final class TransformedIterable<M, N, P> implements
       Iterable<N>
   {
@@ -153,8 +150,8 @@
 
 
     // Constructed via factory methods.
-    private TransformedIterable(Iterable<M> iterable,
-        Function<? super M, ? extends N, P> function, P p)
+    private TransformedIterable(final Iterable<M> iterable,
+        final Function<? super M, ? extends N, P> function, final P p)
     {
       this.iterable = iterable;
       this.function = function;
@@ -168,16 +165,14 @@
      */
     public Iterator<N> iterator()
     {
-      return Iterators.transform(iterable.iterator(), function,
-          parameter);
+      return Iterators.transform(iterable.iterator(), function, parameter);
     }
 
   }
 
 
 
-  private static final class UnmodifiableIterable<M> implements
-      Iterable<M>
+  private static final class UnmodifiableIterable<M> implements Iterable<M>
   {
 
     private final Iterable<M> iterable;
@@ -185,7 +180,7 @@
 
 
     // Constructed via factory methods.
-    private UnmodifiableIterable(Iterable<M> iterable)
+    private UnmodifiableIterable(final Iterable<M> iterable)
     {
       this.iterable = iterable;
     }
@@ -202,8 +197,27 @@
 
   }
 
-  private static final Iterable<Object> EMPTY_ITERABLE =
-      new EmptyIterable<Object>();
+
+
+  private static final Iterable<Object> EMPTY_ITERABLE = new EmptyIterable<Object>();
+
+
+
+  /**
+   * Returns an iterable containing the elements of {@code a}. The returned
+   * iterable's iterator does not support element removal via the {@code
+   * remove()} method.
+   *
+   * @param <M>
+   *          The type of elements contained in {@code a}.
+   * @param a
+   *          The array of elements.
+   * @return An iterable containing the elements of {@code a}.
+   */
+  public static <M> Iterable<M> arrayIterable(final M[] a)
+  {
+    return new ArrayIterable<M>(a);
+  }
 
 
 
@@ -223,28 +237,28 @@
 
 
   /**
-   * Returns a filtered view of {@code iterable} containing only those
-   * elements which match {@code predicate}. The returned iterable's
-   * iterator supports element removal via the {@code remove()} method
-   * subject to any constraints imposed by {@code iterable}.
+   * Returns a filtered view of {@code iterable} containing only those elements
+   * which match {@code predicate}. The returned iterable's iterator supports
+   * element removal via the {@code remove()} method subject to any constraints
+   * imposed by {@code iterable}.
    *
    * @param <M>
    *          The type of elements contained in {@code iterable}.
    * @param <P>
-   *          The type of the additional parameter to the predicate's
-   *          {@code matches} method. Use {@link java.lang.Void} for
-   *          predicates that do not need an additional parameter.
+   *          The type of the additional parameter to the predicate's {@code
+   *          matches} method. Use {@link java.lang.Void} for predicates that do
+   *          not need an additional parameter.
    * @param iterable
    *          The iterable to be filtered.
    * @param predicate
    *          The predicate.
    * @param p
    *          A predicate specified parameter.
-   * @return A filtered view of {@code iterable} containing only those
-   *         elements which match {@code predicate}.
+   * @return A filtered view of {@code iterable} containing only those elements
+   *         which match {@code predicate}.
    */
-  public static <M, P> Iterable<M> filter(Iterable<M> iterable,
-      Predicate<? super M, P> predicate, P p)
+  public static <M, P> Iterable<M> filter(final Iterable<M> iterable,
+      final Predicate<? super M, P> predicate, final P p)
   {
     return new FilteredIterable<M, P>(iterable, predicate, p);
   }
@@ -252,10 +266,10 @@
 
 
   /**
-   * Returns a filtered view of {@code iterable} containing only those
-   * elements which match {@code predicate}. The returned iterable's
-   * iterator supports element removal via the {@code remove()} method
-   * subject to any constraints imposed by {@code iterable}.
+   * Returns a filtered view of {@code iterable} containing only those elements
+   * which match {@code predicate}. The returned iterable's iterator supports
+   * element removal via the {@code remove()} method subject to any constraints
+   * imposed by {@code iterable}.
    *
    * @param <M>
    *          The type of elements contained in {@code iterable}.
@@ -263,11 +277,11 @@
    *          The iterable to be filtered.
    * @param predicate
    *          The predicate.
-   * @return A filtered view of {@code iterable} containing only those
-   *         elements which match {@code predicate}.
+   * @return A filtered view of {@code iterable} containing only those elements
+   *         which match {@code predicate}.
    */
-  public static <M> Iterable<M> filter(Iterable<M> iterable,
-      Predicate<? super M, Void> predicate)
+  public static <M> Iterable<M> filter(final Iterable<M> iterable,
+      final Predicate<? super M, Void> predicate)
   {
     return new FilteredIterable<M, Void>(iterable, predicate, null);
   }
@@ -275,9 +289,9 @@
 
 
   /**
-   * Returns an iterable containing the single element {@code value}.
-   * The returned iterable's iterator does not support element removal
-   * via the {@code remove()} method.
+   * Returns an iterable containing the single element {@code value}. The
+   * returned iterable's iterator does not support element removal via the
+   * {@code remove()} method.
    *
    * @param <M>
    *          The type of the single element {@code value}.
@@ -285,7 +299,7 @@
    *          The single element.
    * @return An iterable containing the single element {@code value}.
    */
-  public static <M> Iterable<M> singleton(M value)
+  public static <M> Iterable<M> singleton(final M value)
   {
     return new SingletonIterable<M>(value);
   }
@@ -293,38 +307,19 @@
 
 
   /**
-   * Returns an iterable containing the elements of {@code a}. The
-   * returned iterable's iterator does not support element removal via
-   * the {@code remove()} method.
-   *
-   * @param <M>
-   *          The type of elements contained in {@code a}.
-   * @param a
-   *          The array of elements.
-   * @return An iterable containing the elements of {@code a}.
-   */
-  public static <M> Iterable<M> arrayIterable(M[] a)
-  {
-    return new ArrayIterable<M>(a);
-  }
-
-
-
-  /**
    * Returns a view of {@code iterable} whose values have been mapped to
-   * elements of type {@code N} using {@code function}. The returned
-   * iterable's iterator supports element removal via the {@code
-   * remove()} method subject to any constraints imposed by {@code
-   * iterable}.
+   * elements of type {@code N} using {@code function}. The returned iterable's
+   * iterator supports element removal via the {@code remove()} method subject
+   * to any constraints imposed by {@code iterable}.
    *
    * @param <M>
    *          The type of elements contained in {@code iterable}.
    * @param <N>
    *          The type of elements contained in the returned iterable.
    * @param <P>
-   *          The type of the additional parameter to the function's
-   *          {@code apply} method. Use {@link java.lang.Void} for
-   *          functions that do not need an additional parameter.
+   *          The type of the additional parameter to the function's {@code
+   *          apply} method. Use {@link java.lang.Void} for functions that do
+   *          not need an additional parameter.
    * @param iterable
    *          The iterable to be transformed.
    * @param function
@@ -334,8 +329,8 @@
    * @return A view of {@code iterable} whose values have been mapped to
    *         elements of type {@code N} using {@code function}.
    */
-  public static <M, N, P> Iterable<N> transform(Iterable<M> iterable,
-      Function<? super M, ? extends N, P> function, P p)
+  public static <M, N, P> Iterable<N> transform(final Iterable<M> iterable,
+      final Function<? super M, ? extends N, P> function, final P p)
   {
     return new TransformedIterable<M, N, P>(iterable, function, p);
   }
@@ -344,10 +339,9 @@
 
   /**
    * Returns a view of {@code iterable} whose values have been mapped to
-   * elements of type {@code N} using {@code function}. The returned
-   * iterable's iterator supports element removal via the {@code
-   * remove()} method subject to any constraints imposed by {@code
-   * iterable}.
+   * elements of type {@code N} using {@code function}. The returned iterable's
+   * iterator supports element removal via the {@code remove()} method subject
+   * to any constraints imposed by {@code iterable}.
    *
    * @param <M>
    *          The type of elements contained in {@code iterable}.
@@ -360,8 +354,8 @@
    * @return A view of {@code iterable} whose values have been mapped to
    *         elements of type {@code N} using {@code function}.
    */
-  public static <M, N> Iterable<N> transform(Iterable<M> iterable,
-      Function<? super M, ? extends N, Void> function)
+  public static <M, N> Iterable<N> transform(final Iterable<M> iterable,
+      final Function<? super M, ? extends N, Void> function)
   {
     return new TransformedIterable<M, N, Void>(iterable, function, null);
   }
@@ -369,19 +363,19 @@
 
 
   /**
-   * Returns a read-only view of {@code iterable} whose iterator does
-   * not support element removal via the {@code remove()}. Attempts to
-   * use the {@code remove()} method will result in a {@code
+   * Returns a read-only view of {@code iterable} whose iterator does not
+   * support element removal via the {@code remove()}. Attempts to use the
+   * {@code remove()} method will result in a {@code
    * UnsupportedOperationException}.
    *
    * @param <M>
    *          The type of elements contained in {@code iterable}.
    * @param iterable
    *          The iterable to be made read-only.
-   * @return A read-only view of {@code iterable} whose iterator does
-   *         not support element removal via the {@code remove()}.
+   * @return A read-only view of {@code iterable} whose iterator does not
+   *         support element removal via the {@code remove()}.
    */
-  public static <M> Iterable<M> unmodifiable(Iterable<M> iterable)
+  public static <M> Iterable<M> unmodifiable(final Iterable<M> iterable)
   {
     return new UnmodifiableIterable<M>(iterable);
   }
diff --git a/sdk/src/com/sun/opends/sdk/util/Iterators.java b/sdk/src/com/sun/opends/sdk/util/Iterators.java
index 639bcaf..b26f4e0 100644
--- a/sdk/src/com/sun/opends/sdk/util/Iterators.java
+++ b/sdk/src/com/sun/opends/sdk/util/Iterators.java
@@ -39,6 +39,60 @@
  */
 public final class Iterators
 {
+  private static final class ArrayIterator<M> implements Iterator<M>
+  {
+    private int i = 0;
+    private final M[] a;
+
+
+
+    // Constructed via factory methods.
+    private ArrayIterator(final M[] a)
+    {
+      this.a = a;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean hasNext()
+    {
+      return i < a.length;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public M next()
+    {
+      if (hasNext())
+      {
+        return a[i++];
+      }
+      else
+      {
+        throw new NoSuchElementException();
+      }
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void remove()
+    {
+      throw new UnsupportedOperationException();
+    }
+
+  };
+
+
+
   private static final class EmptyIterator<M> implements Iterator<M>
   {
     /**
@@ -68,12 +122,11 @@
     {
       throw new UnsupportedOperationException();
     }
-  };
+  }
 
 
 
-  private static final class FilteredIterator<M, P> implements
-      Iterator<M>
+  private static final class FilteredIterator<M, P> implements Iterator<M>
   {
 
     private boolean hasNextMustIterate = true;
@@ -86,8 +139,8 @@
 
 
     // Constructed via factory methods.
-    private FilteredIterator(Iterator<M> iterator,
-        Predicate<? super M, P> predicate, P p)
+    private FilteredIterator(final Iterator<M> iterator,
+        final Predicate<? super M, P> predicate, final P p)
     {
       this.iterator = iterator;
       this.predicate = predicate;
@@ -150,15 +203,14 @@
 
 
 
-  private static final class SingletonIterator<M> implements
-      Iterator<M>
+  private static final class SingletonIterator<M> implements Iterator<M>
   {
     private M value;
 
 
 
     // Constructed via factory methods.
-    private SingletonIterator(M value)
+    private SingletonIterator(final M value)
     {
       this.value = value;
     }
@@ -182,7 +234,7 @@
     {
       if (value != null)
       {
-        M tmp = value;
+        final M tmp = value;
         value = null;
         return tmp;
       }
@@ -206,60 +258,6 @@
 
 
 
-  private static final class ArrayIterator<M> implements Iterator<M>
-  {
-    private int i = 0;
-    private final M[] a;
-
-
-
-    // Constructed via factory methods.
-    private ArrayIterator(M[] a)
-    {
-      this.a = a;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean hasNext()
-    {
-      return i < a.length;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public M next()
-    {
-      if (hasNext())
-      {
-        return a[i++];
-      }
-      else
-      {
-        throw new NoSuchElementException();
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public void remove()
-    {
-      throw new UnsupportedOperationException();
-    }
-
-  }
-
-
-
   private static final class TransformedIterator<M, N, P> implements
       Iterator<N>
   {
@@ -271,8 +269,8 @@
 
 
     // Constructed via factory methods.
-    private TransformedIterator(Iterator<M> iterator,
-        Function<? super M, ? extends N, P> function, P p)
+    private TransformedIterator(final Iterator<M> iterator,
+        final Function<? super M, ? extends N, P> function, final P p)
     {
       this.iterator = iterator;
       this.function = function;
@@ -313,14 +311,13 @@
 
 
 
-  private static final class UnmodifiableIterator<M> implements
-      Iterator<M>
+  private static final class UnmodifiableIterator<M> implements Iterator<M>
   {
     private final Iterator<M> iterator;
 
 
 
-    private UnmodifiableIterator(Iterator<M> iterator)
+    private UnmodifiableIterator(final Iterator<M> iterator)
     {
       this.iterator = iterator;
     }
@@ -356,8 +353,26 @@
     }
   }
 
-  private static final Iterator<Object> EMPTY_ITERATOR =
-      new EmptyIterator<Object>();
+
+
+  private static final Iterator<Object> EMPTY_ITERATOR = new EmptyIterator<Object>();
+
+
+
+  /**
+   * Returns an iterator over the elements contained in {@code a}. The returned
+   * iterator does not support element removal via the {@code remove()} method.
+   *
+   * @param <M>
+   *          The type of elements contained in {@code a}.
+   * @param a
+   *          The array of elements to be returned by the iterator.
+   * @return An iterator over the elements contained in {@code a}.
+   */
+  public static <M> Iterator<M> arrayIterator(final M[] a)
+  {
+    return new ArrayIterator<M>(a);
+  }
 
 
 
@@ -377,28 +392,28 @@
 
 
   /**
-   * Returns a filtered view of {@code iterator} containing only those
-   * elements which match {@code predicate}. The returned iterator
-   * supports element removal via the {@code remove()} method subject to
-   * any constraints imposed by {@code iterator}.
+   * Returns a filtered view of {@code iterator} containing only those elements
+   * which match {@code predicate}. The returned iterator supports element
+   * removal via the {@code remove()} method subject to any constraints imposed
+   * by {@code iterator}.
    *
    * @param <M>
    *          The type of elements contained in {@code iterator}.
    * @param <P>
-   *          The type of the additional parameter to the predicate's
-   *          {@code matches} method. Use {@link java.lang.Void} for
-   *          predicates that do not need an additional parameter.
+   *          The type of the additional parameter to the predicate's {@code
+   *          matches} method. Use {@link java.lang.Void} for predicates that do
+   *          not need an additional parameter.
    * @param iterator
    *          The iterator to be filtered.
    * @param predicate
    *          The predicate.
    * @param p
    *          A predicate specified parameter.
-   * @return A filtered view of {@code iterator} containing only those
-   *         elements which match {@code predicate}.
+   * @return A filtered view of {@code iterator} containing only those elements
+   *         which match {@code predicate}.
    */
-  public static <M, P> Iterator<M> filter(Iterator<M> iterator,
-      Predicate<? super M, P> predicate, P p)
+  public static <M, P> Iterator<M> filter(final Iterator<M> iterator,
+      final Predicate<? super M, P> predicate, final P p)
   {
     return new FilteredIterator<M, P>(iterator, predicate, p);
   }
@@ -406,10 +421,10 @@
 
 
   /**
-   * Returns a filtered view of {@code iterator} containing only those
-   * elements which match {@code predicate}. The returned iterator
-   * supports element removal via the {@code remove()} method subject to
-   * any constraints imposed by {@code iterator}.
+   * Returns a filtered view of {@code iterator} containing only those elements
+   * which match {@code predicate}. The returned iterator supports element
+   * removal via the {@code remove()} method subject to any constraints imposed
+   * by {@code iterator}.
    *
    * @param <M>
    *          The type of elements contained in {@code iterator}.
@@ -417,11 +432,11 @@
    *          The iterator to be filtered.
    * @param predicate
    *          The predicate.
-   * @return A filtered view of {@code iterator} containing only those
-   *         elements which match {@code predicate}.
+   * @return A filtered view of {@code iterator} containing only those elements
+   *         which match {@code predicate}.
    */
-  public static <M> Iterator<M> filter(Iterator<M> iterator,
-      Predicate<? super M, Void> predicate)
+  public static <M> Iterator<M> filter(final Iterator<M> iterator,
+      final Predicate<? super M, Void> predicate)
   {
     return new FilteredIterator<M, Void>(iterator, predicate, null);
   }
@@ -429,9 +444,9 @@
 
 
   /**
-   * Returns an iterator containing the single element {@code value}.
-   * The returned iterator does not support element removal via the
-   * {@code remove()} method.
+   * Returns an iterator containing the single element {@code value}. The
+   * returned iterator does not support element removal via the {@code remove()}
+   * method.
    *
    * @param <M>
    *          The type of the single element {@code value}.
@@ -439,7 +454,7 @@
    *          The single element to be returned by the iterator.
    * @return An iterator containing the single element {@code value}.
    */
-  public static <M> Iterator<M> singleton(M value)
+  public static <M> Iterator<M> singleton(final M value)
   {
     return new SingletonIterator<M>(value);
   }
@@ -447,37 +462,19 @@
 
 
   /**
-   * Returns an iterator over the elements contained in {@code a}. The
-   * returned iterator does not support element removal via the {@code
-   * remove()} method.
-   *
-   * @param <M>
-   *          The type of elements contained in {@code a}.
-   * @param a
-   *          The array of elements to be returned by the iterator.
-   * @return An iterator over the elements contained in {@code a}.
-   */
-  public static <M> Iterator<M> arrayIterator(M[] a)
-  {
-    return new ArrayIterator<M>(a);
-  }
-
-
-
-  /**
    * Returns a view of {@code iterator} whose values have been mapped to
-   * elements of type {@code N} using {@code function}. The returned
-   * iterator supports element removal via the {@code remove()} method
-   * subject to any constraints imposed by {@code iterator}.
+   * elements of type {@code N} using {@code function}. The returned iterator
+   * supports element removal via the {@code remove()} method subject to any
+   * constraints imposed by {@code iterator}.
    *
    * @param <M>
    *          The type of elements contained in {@code iterator}.
    * @param <N>
    *          The type of elements contained in the returned iterator.
    * @param <P>
-   *          The type of the additional parameter to the function's
-   *          {@code apply} method. Use {@link java.lang.Void} for
-   *          functions that do not need an additional parameter.
+   *          The type of the additional parameter to the function's {@code
+   *          apply} method. Use {@link java.lang.Void} for functions that do
+   *          not need an additional parameter.
    * @param iterator
    *          The iterator to be transformed.
    * @param function
@@ -487,8 +484,8 @@
    * @return A view of {@code iterator} whose values have been mapped to
    *         elements of type {@code N} using {@code function}.
    */
-  public static <M, N, P> Iterator<N> transform(Iterator<M> iterator,
-      Function<? super M, ? extends N, P> function, P p)
+  public static <M, N, P> Iterator<N> transform(final Iterator<M> iterator,
+      final Function<? super M, ? extends N, P> function, final P p)
   {
     return new TransformedIterator<M, N, P>(iterator, function, p);
   }
@@ -497,9 +494,9 @@
 
   /**
    * Returns a view of {@code iterator} whose values have been mapped to
-   * elements of type {@code N} using {@code function}. The returned
-   * iterator supports element removal via the {@code remove()} method
-   * subject to any constraints imposed by {@code iterator}.
+   * elements of type {@code N} using {@code function}. The returned iterator
+   * supports element removal via the {@code remove()} method subject to any
+   * constraints imposed by {@code iterator}.
    *
    * @param <M>
    *          The type of elements contained in {@code iterator}.
@@ -512,8 +509,8 @@
    * @return A view of {@code iterator} whose values have been mapped to
    *         elements of type {@code N} using {@code function}.
    */
-  public static <M, N> Iterator<N> transform(Iterator<M> iterator,
-      Function<? super M, ? extends N, Void> function)
+  public static <M, N> Iterator<N> transform(final Iterator<M> iterator,
+      final Function<? super M, ? extends N, Void> function)
   {
     return new TransformedIterator<M, N, Void>(iterator, function, null);
   }
@@ -521,19 +518,18 @@
 
 
   /**
-   * Returns a read-only view of {@code iterator} which does not support
-   * element removal via the {@code remove()}. Attempts to use the
-   * {@code remove()} method will result in a {@code
-   * UnsupportedOperationException}.
+   * Returns a read-only view of {@code iterator} which does not support element
+   * removal via the {@code remove()}. Attempts to use the {@code remove()}
+   * method will result in a {@code UnsupportedOperationException}.
    *
    * @param <M>
    *          The type of elements contained in {@code iterator}.
    * @param iterator
    *          The iterator to be made read-only.
-   * @return A read-only view of {@code iterator} which does not support
-   *         element removal via the {@code remove()}.
+   * @return A read-only view of {@code iterator} which does not support element
+   *         removal via the {@code remove()}.
    */
-  public static <M> Iterator<M> unmodifiable(Iterator<M> iterator)
+  public static <M> Iterator<M> unmodifiable(final Iterator<M> iterator)
   {
     return new UnmodifiableIterator<M>(iterator);
   }
diff --git a/sdk/src/com/sun/opends/sdk/util/LocalizableMessageDescriptor.java b/sdk/src/com/sun/opends/sdk/util/LocalizableMessageDescriptor.java
index b276542..8bb04eb 100755
--- a/sdk/src/com/sun/opends/sdk/util/LocalizableMessageDescriptor.java
+++ b/sdk/src/com/sun/opends/sdk/util/LocalizableMessageDescriptor.java
@@ -48,9 +48,8 @@
   {
 
     /**
-     * Cached copy of the message created by this descriptor. We can get
-     * away with this for the zero argument message because it is
-     * immutable.
+     * Cached copy of the message created by this descriptor. We can get away
+     * with this for the zero argument message because it is immutable.
      */
     private final LocalizableMessage message;
 
@@ -68,7 +67,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public Arg0(String rbBase, String key, ClassLoader classLoader)
+    public Arg0(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
       message = newMessage(this);
@@ -92,6 +92,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return requiresFormat;
@@ -119,7 +120,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public Arg1(String rbBase, String key, ClassLoader classLoader)
+    public Arg1(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
     }
@@ -127,15 +129,15 @@
 
 
     /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
      *
      * @return LocalizableMessage object
      * @param a1
      *          message argument
      */
-    public LocalizableMessage get(T1 a1)
+    public LocalizableMessage get(final T1 a1)
     {
       return newMessage(this, a1);
     }
@@ -145,6 +147,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return true;
@@ -175,7 +178,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public Arg2(String rbBase, String key, ClassLoader classLoader)
+    public Arg2(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
     }
@@ -183,9 +187,9 @@
 
 
     /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
      *
      * @return LocalizableMessage object
      * @param a1
@@ -193,7 +197,7 @@
      * @param a2
      *          message argument
      */
-    public LocalizableMessage get(T1 a1, T2 a2)
+    public LocalizableMessage get(final T1 a1, final T2 a2)
     {
       return newMessage(this, a1, a2);
     }
@@ -203,6 +207,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return true;
@@ -222,7 +227,8 @@
    * @param <T3>
    *          The type of the third message argument.
    */
-  public static final class Arg3<T1, T2, T3> extends LocalizableMessageDescriptor
+  public static final class Arg3<T1, T2, T3> extends
+      LocalizableMessageDescriptor
   {
 
     /**
@@ -235,7 +241,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public Arg3(String rbBase, String key, ClassLoader classLoader)
+    public Arg3(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
     }
@@ -243,9 +250,9 @@
 
 
     /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
      *
      * @return LocalizableMessage object
      * @param a1
@@ -255,7 +262,7 @@
      * @param a3
      *          message argument
      */
-    public LocalizableMessage get(T1 a1, T2 a2, T3 a3)
+    public LocalizableMessage get(final T1 a1, final T2 a2, final T3 a3)
     {
       return newMessage(this, a1, a2, a3);
     }
@@ -265,6 +272,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return true;
@@ -300,7 +308,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public Arg4(String rbBase, String key, ClassLoader classLoader)
+    public Arg4(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
     }
@@ -308,9 +317,9 @@
 
 
     /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
      *
      * @return LocalizableMessage object
      * @param a1
@@ -322,7 +331,8 @@
      * @param a4
      *          message argument
      */
-    public LocalizableMessage get(T1 a1, T2 a2, T3 a3, T4 a4)
+    public LocalizableMessage get(final T1 a1, final T2 a2, final T3 a3,
+        final T4 a4)
     {
       return newMessage(this, a1, a2, a3, a4);
     }
@@ -332,6 +342,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return true;
@@ -369,7 +380,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public Arg5(String rbBase, String key, ClassLoader classLoader)
+    public Arg5(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
     }
@@ -377,9 +389,9 @@
 
 
     /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
      *
      * @return LocalizableMessage object
      * @param a1
@@ -393,7 +405,8 @@
      * @param a5
      *          message argument
      */
-    public LocalizableMessage get(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
+    public LocalizableMessage get(final T1 a1, final T2 a2, final T3 a3,
+        final T4 a4, final T5 a5)
     {
       return newMessage(this, a1, a2, a3, a4, a5);
     }
@@ -403,6 +416,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return true;
@@ -442,7 +456,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public Arg6(String rbBase, String key, ClassLoader classLoader)
+    public Arg6(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
     }
@@ -450,9 +465,9 @@
 
 
     /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
      *
      * @return LocalizableMessage object
      * @param a1
@@ -468,7 +483,8 @@
      * @param a6
      *          message argument
      */
-    public LocalizableMessage get(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6)
+    public LocalizableMessage get(final T1 a1, final T2 a2, final T3 a3,
+        final T4 a4, final T5 a5, final T6 a6)
     {
       return newMessage(this, a1, a2, a3, a4, a5, a6);
     }
@@ -478,6 +494,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return true;
@@ -519,7 +536,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public Arg7(String rbBase, String key, ClassLoader classLoader)
+    public Arg7(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
     }
@@ -527,9 +545,9 @@
 
 
     /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
      *
      * @return LocalizableMessage object
      * @param a1
@@ -547,7 +565,8 @@
      * @param a7
      *          message argument
      */
-    public LocalizableMessage get(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7)
+    public LocalizableMessage get(final T1 a1, final T2 a2, final T3 a3,
+        final T4 a4, final T5 a5, final T6 a6, final T7 a7)
     {
       return newMessage(this, a1, a2, a3, a4, a5, a6, a7);
     }
@@ -557,6 +576,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return true;
@@ -586,8 +606,8 @@
    * @param <T8>
    *          The type of the eighth message argument.
    */
-  public static final class Arg8<T1, T2, T3, T4, T5, T6, T7, T8>
-      extends LocalizableMessageDescriptor
+  public static final class Arg8<T1, T2, T3, T4, T5, T6, T7, T8> extends
+      LocalizableMessageDescriptor
   {
 
     /**
@@ -600,7 +620,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public Arg8(String rbBase, String key, ClassLoader classLoader)
+    public Arg8(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
     }
@@ -608,9 +629,9 @@
 
 
     /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
      *
      * @return LocalizableMessage object
      * @param a1
@@ -630,8 +651,8 @@
      * @param a8
      *          message argument
      */
-    public LocalizableMessage get(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7,
-        T8 a8)
+    public LocalizableMessage get(final T1 a1, final T2 a2, final T3 a3,
+        final T4 a4, final T5 a5, final T6 a6, final T7 a7, final T8 a8)
     {
       return newMessage(this, a1, a2, a3, a4, a5, a6, a7, a8);
     }
@@ -641,6 +662,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return true;
@@ -672,8 +694,8 @@
    * @param <T9>
    *          The type of the ninth message argument.
    */
-  public static final class Arg9<T1, T2, T3, T4, T5, T6, T7, T8, T9>
-      extends LocalizableMessageDescriptor
+  public static final class Arg9<T1, T2, T3, T4, T5, T6, T7, T8, T9> extends
+      LocalizableMessageDescriptor
   {
 
     /**
@@ -686,7 +708,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public Arg9(String rbBase, String key, ClassLoader classLoader)
+    public Arg9(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
     }
@@ -694,9 +717,9 @@
 
 
     /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
      *
      * @return LocalizableMessage object
      * @param a1
@@ -718,8 +741,9 @@
      * @param a9
      *          message argument
      */
-    public LocalizableMessage get(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5, T6 a6, T7 a7,
-        T8 a8, T9 a9)
+    public LocalizableMessage get(final T1 a1, final T2 a2, final T3 a3,
+        final T4 a4, final T5 a5, final T6 a6, final T7 a7, final T8 a8,
+        final T9 a9)
     {
       return newMessage(this, a1, a2, a3, a4, a5, a6, a7, a8, a9);
     }
@@ -729,6 +753,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return true;
@@ -739,10 +764,9 @@
 
 
   /**
-   * Subclass for creating messages with an any number of arguments. In
-   * general this class should be used when a message needs to be
-   * defined with more arguments that can be handled with the current
-   * number of subclasses
+   * Subclass for creating messages with an any number of arguments. In general
+   * this class should be used when a message needs to be defined with more
+   * arguments that can be handled with the current number of subclasses
    */
   public static final class ArgN extends LocalizableMessageDescriptor
   {
@@ -757,7 +781,8 @@
      * @param classLoader
      *          the class loader to be used to get the ResourceBundle
      */
-    public ArgN(String rbBase, String key, ClassLoader classLoader)
+    public ArgN(final String rbBase, final String key,
+        final ClassLoader classLoader)
     {
       super(rbBase, key, classLoader);
     }
@@ -765,15 +790,15 @@
 
 
     /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
      *
      * @return LocalizableMessage object
      * @param args
      *          message arguments
      */
-    public LocalizableMessage get(Object... args)
+    public LocalizableMessage get(final Object... args)
     {
       return newMessage(this, args);
     }
@@ -783,6 +808,7 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     public boolean requiresFormatter()
     {
       return true;
@@ -793,98 +819,6 @@
 
 
   /**
-   * A descriptor for creating a raw message from a <code>String</code>.
-   * In general this descriptor should NOT be used internally. OpenDS
-   * plugins may want to use the mechanism to create messages without
-   * storing their strings in resource bundles.
-   */
-  public static final class Raw extends LocalizableMessageDescriptor
-  {
-
-    private final String formatString;
-
-    private final boolean requiresFormatter;
-
-
-
-    /**
-     * Creates a parameterized instance.
-     *
-     * @param formatString
-     *          for created messages
-     */
-    public Raw(CharSequence formatString)
-    {
-      super(null, null, null);
-      this.formatString = formatString != null ? formatString
-          .toString() : "";
-      this.requiresFormatter = this.formatString.matches(".*%.*");
-    }
-
-
-
-    /**
-     * Creates a message with arguments that will replace format
-     * specifiers in the assocated format string when the message is
-     * rendered to string representation.
-     *
-     * @return LocalizableMessage object
-     * @param args
-     *          message arguments
-     */
-    public LocalizableMessage get(Object... args)
-    {
-      return newMessage(this, args);
-    }
-
-
-
-    /**
-     * Overridden in order to bypass the resource bundle plumbing and
-     * return the format string directly.
-     *
-     * @param locale
-     *          ignored
-     * @return format string
-     */
-    public String getFormatString(Locale locale)
-    {
-      return this.formatString;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean requiresFormatter()
-    {
-      return this.requiresFormatter;
-    }
-
-  }
-
-
-
-  // Container for caching the last locale specific format string.
-  private static final class CachedFormatString
-  {
-    private final Locale locale;
-
-    private final String formatString;
-
-
-
-    private CachedFormatString(Locale locale, String formatString)
-    {
-      this.locale = locale;
-      this.formatString = formatString;
-    }
-  }
-
-
-
-  /**
    * Factory interface for creating messages. Only LocalizableMessage should
    * implement this.
    */
@@ -899,7 +833,101 @@
      *          The message parameters.
      * @return The new message.
      */
-    LocalizableMessage newMessage(LocalizableMessageDescriptor descriptor, Object... args);
+    LocalizableMessage newMessage(LocalizableMessageDescriptor descriptor,
+        Object... args);
+  }
+
+
+
+  /**
+   * A descriptor for creating a raw message from a <code>String</code>. In
+   * general this descriptor should NOT be used internally. OpenDS plugins may
+   * want to use the mechanism to create messages without storing their strings
+   * in resource bundles.
+   */
+  public static final class Raw extends LocalizableMessageDescriptor
+  {
+
+    private final String formatString;
+
+    private final boolean requiresFormatter;
+
+
+
+    /**
+     * Creates a parameterized instance.
+     *
+     * @param formatString
+     *          for created messages
+     */
+    public Raw(final CharSequence formatString)
+    {
+      super(null, null, null);
+      this.formatString = formatString != null ? formatString.toString() : "";
+      this.requiresFormatter = this.formatString.matches(".*%.*");
+    }
+
+
+
+    /**
+     * Creates a message with arguments that will replace format specifiers in
+     * the assocated format string when the message is rendered to string
+     * representation.
+     *
+     * @return LocalizableMessage object
+     * @param args
+     *          message arguments
+     */
+    public LocalizableMessage get(final Object... args)
+    {
+      return newMessage(this, args);
+    }
+
+
+
+    /**
+     * Overridden in order to bypass the resource bundle plumbing and return the
+     * format string directly.
+     *
+     * @param locale
+     *          ignored
+     * @return format string
+     */
+    @Override
+    public String getFormatString(final Locale locale)
+    {
+      return this.formatString;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean requiresFormatter()
+    {
+      return this.requiresFormatter;
+    }
+
+  }
+
+
+
+  // Container for caching the last locale specific format string.
+  private static final class CachedFormatString
+  {
+    private final Locale locale;
+
+    private final String formatString;
+
+
+
+    private CachedFormatString(final Locale locale, final String formatString)
+    {
+      this.locale = locale;
+      this.formatString = formatString;
+    }
   }
 
 
@@ -908,16 +936,16 @@
    * We use a factory for creating LocalizableMessage objects in order to avoid
    * exposing this class in the public API.
    */
-  public static MessageFactory MESSAGE_FACTORY;
+  public static MessageFactory messageFactory;
 
-  // Force MESSAGE_FACTORY to be set.
+  // Force messageFactory to be set.
   static
   {
     try
     {
       Class.forName("org.opends.sdk.LocalizableMessage");
     }
-    catch (ClassNotFoundException e)
+    catch (final ClassNotFoundException e)
     {
       throw new RuntimeException(e);
     }
@@ -926,27 +954,26 @@
 
 
   /**
-   * Indicates whether or not formatting should be applied to the given
-   * format string. Note that a format string might have literal
-   * specifiers (%% or %n for example) that require formatting but are
-   * not replaced by arguments.
+   * Indicates whether or not formatting should be applied to the given format
+   * string. Note that a format string might have literal specifiers (%% or %n
+   * for example) that require formatting but are not replaced by arguments.
    *
    * @param s
    *          candidate for formatting
-   * @return boolean where true indicates that the format string
-   *         requires formatting
+   * @return boolean where true indicates that the format string requires
+   *         formatting
    */
-  private static final boolean containsArgumentLiterals(String s)
+  private static final boolean containsArgumentLiterals(final String s)
   {
     return s.matches(".*%[n|%].*"); // match Formatter literals
   }
 
 
 
-  private static LocalizableMessage newMessage(LocalizableMessageDescriptor descriptor,
-      Object... args)
+  private static LocalizableMessage newMessage(
+      final LocalizableMessageDescriptor descriptor, final Object... args)
   {
-    return MESSAGE_FACTORY.newMessage(descriptor, args);
+    return messageFactory.newMessage(descriptor, args);
   }
 
 
@@ -958,8 +985,8 @@
   private final String key;
 
   /*
-   * The class loader to be used to retrieve the ResourceBundle. If null
-   * the default class loader will be used.
+   * The class loader to be used to retrieve the ResourceBundle. If null the
+   * default class loader will be used.
    */
   private final ClassLoader classLoader;
 
@@ -978,8 +1005,8 @@
    * @param classLoader
    *          the class loader to be used to get the ResourceBundle
    */
-  private LocalizableMessageDescriptor(String rbBase, String key,
-      ClassLoader classLoader)
+  private LocalizableMessageDescriptor(final String rbBase, final String key,
+      final ClassLoader classLoader)
   {
     this.rbBase = rbBase;
     this.key = key;
@@ -989,8 +1016,8 @@
 
 
   /**
-   * Returns the format string which should be used when creating the
-   * string representation of this message using the specified locale.
+   * Returns the format string which should be used when creating the string
+   * representation of this message using the specified locale.
    *
    * @param locale
    *          The locale.
@@ -998,7 +1025,7 @@
    * @throws NullPointerException
    *           If {@code locale} was {@code null}.
    */
-  public String getFormatString(Locale locale)
+  public String getFormatString(final Locale locale)
       throws NullPointerException
   {
     Validator.ensureNotNull(locale);
@@ -1022,16 +1049,29 @@
 
 
   /**
-   * Indicates whether or not this descriptor format string should be
-   * processed by {@code Formatter} during string rendering.
+   * Indicates whether or not this descriptor format string should be processed
+   * by {@code Formatter} during string rendering.
    *
-   * @return {@code true} if a {@code Formatter} should be used,
-   *         otherwise {@code false}.
+   * @return {@code true} if a {@code Formatter} should be used, otherwise
+   *         {@code false}.
    */
   public abstract boolean requiresFormatter();
 
 
 
+  /**
+   * Returns the format string which should be used when creating the string
+   * representation of this message using the default locale.
+   *
+   * @return The format string.
+   */
+  final String getFormatString()
+  {
+    return getFormatString(Locale.getDefault());
+  }
+
+
+
   private ResourceBundle getBundle(Locale locale)
   {
     if (locale == null)
@@ -1048,17 +1088,4 @@
     }
   }
 
-
-
-  /**
-   * Returns the format string which should be used when creating the
-   * string representation of this message using the default locale.
-   *
-   * @return The format string.
-   */
-  final String getFormatString()
-  {
-    return getFormatString(Locale.getDefault());
-  }
-
 }
diff --git a/sdk/src/com/sun/opends/sdk/util/Platform.java b/sdk/src/com/sun/opends/sdk/util/Platform.java
index 53bed41..5d57501 100644
--- a/sdk/src/com/sun/opends/sdk/util/Platform.java
+++ b/sdk/src/com/sun/opends/sdk/util/Platform.java
@@ -28,6 +28,7 @@
 package com.sun.opends.sdk.util;
 
 
+
 import static com.sun.opends.sdk.messages.Messages.*;
 
 import java.io.*;
@@ -41,611 +42,793 @@
 import org.opends.sdk.LocalizableMessage;
 
 
+
 /**
- * Provides a wrapper class that collects all of the JVM vendor
- * and JDK version specific code in a single place.
- *
+ * Provides a wrapper class that collects all of the JVM vendor and JDK version
+ * specific code in a single place.
  */
-public final class Platform {
+public final class Platform
+{
 
-   //Prefix that determines which security package to use.
-    private static String pkgPrefix;
+  /**
+   * Default platform class.
+   */
+  private static class DefaultPlatformIMPL extends PlatformIMPL
+  {
+    // normalize method.
+    private static final Method NORMALIZE;
+    // Normalized form method.
+    private static final Object FORM_NFKC;
 
-    //IBM security package doesn't appear to support PCKS10, this flags turns
-    //off support for that.
-    private static boolean certReqAllowed;
+    static
+    {
 
-    //The two security package prefixes (IBM and SUN).
-    private static final String IBM_SEC = "com.ibm.security";
-    private static final String SUN_SEC = "sun.security";
-
-    private static final PlatformIMPL IMPL;
-
-    static {
-     String vendor = System.getProperty("java.vendor");
-     String ver = System.getProperty("java.version");
-
-      if(vendor.startsWith("IBM"))
+      Method normalize = null;
+      Object formNFKC = null;
+      try
       {
-        pkgPrefix = IBM_SEC;
-        certReqAllowed = false;
-        if(ver.startsWith("1.5"))
+        final Class<?> normalizer = Class.forName("java.text.Normalizer");
+        final Class<?> normalizerForm = Class
+            .forName("java.text.Normalizer$Form");
+        normalize = normalizer.getMethod("normalize", CharSequence.class,
+            normalizerForm);
+        formNFKC = normalizerForm.getField("NFKD").get(null);
+      }
+      catch (final Exception ex)
+      {
+        // Do not use Normalizer. The values are already set to null.
+      }
+      NORMALIZE = normalize;
+      FORM_NFKC = formNFKC;
+    }
+
+
+
+    @Override
+    public void normalize(final StringBuilder buffer)
+    {
+      try
+      {
+        final String normal = (String) NORMALIZE
+            .invoke(null, buffer, FORM_NFKC);
+        buffer.replace(0, buffer.length(), normal);
+      }
+      catch (final Exception ex)
+      {
+        // Don't do anything. buffer should be used.
+      }
+    }
+  }
+
+
+
+  /**
+   * IBM JDK 5 platform class.
+   */
+  private static class IBM5PlatformIMPL extends PlatformIMPL
+  {
+
+    @Override
+    public void normalize(final StringBuilder buffer)
+    {
+      // No implementation.
+    }
+  }
+
+
+
+  /**
+   * Platform base class. Performs all of the certificate management functions.
+   */
+  private abstract static class PlatformIMPL
+  {
+
+    // Key size, key algorithm and signature algorithms used.
+    private static final int KEY_SIZE = 1024;
+    private static final String KEY_ALGORITHM = "rsa";
+    private static final String SIG_ALGORITHM = "SHA1WithRSA";
+
+    // Time values used in validity calculations.
+    private static final int SEC_IN_DAY = 24 * 60 * 60;
+    private static final int DEFAULT_VALIDITY = 90 * SEC_IN_DAY;
+
+    // These two are used to build certificate request files.
+    private static final String TMPFILE_PREFIX = "CertificateManager-";
+    private static final String TMPFILE_EXT = ".csr";
+
+    // Methods pulled from the classes.
+    private static final String ENCODE_SIGN_METHOD = "encodeAndSign";
+    private static final String GENERATE_METHOD = "generate";
+    private static final String GET_PRIVATE_KEY_METHOD = "getPrivateKey";
+    private static final String GET_SELFSIGNED_CERT_METHOD = "getSelfCertificate";
+    private static final String PRINT_METHOD = "print";
+
+    // Classes needed to manage certificates.
+    private static Class<?> certKeyGenClass, x500NameClass, x500SignerClass,
+        pkcs10Class;
+
+    // Constructors for each of the above classes.
+    private static Constructor<?> certKeyGenCons, x500NameCons, x500SignerCons,
+        pkcs10Cons;
+
+    static
+    {
+      final String x509pkg = pkgPrefix + ".x509";
+      final String pkcs10Pkg = pkgPrefix + ".pkcs";
+      final String certAndKeyGen = x509pkg + ".CertAndKeyGen";
+      final String x500Name = x509pkg + ".X500Name";
+      final String x500Signer = x509pkg + ".X500Signer";
+      try
+      {
+        certKeyGenClass = Class.forName(certAndKeyGen);
+        x500NameClass = Class.forName(x500Name);
+        x500SignerClass = Class.forName(x500Signer);
+        if (certReqAllowed)
         {
-          IMPL = new IBM5PlatformIMPL();
+          final String pkcs10 = pkcs10Pkg + ".PKCS10";
+          pkcs10Class = Class.forName(pkcs10);
+          pkcs10Cons = pkcs10Class.getConstructor(PublicKey.class);
+        }
+        certKeyGenCons = certKeyGenClass.getConstructor(String.class,
+            String.class);
+        x500NameCons = x500NameClass.getConstructor(String.class);
+        x500SignerCons = x500SignerClass.getConstructor(Signature.class,
+            x500NameClass);
+      }
+      catch (final ClassNotFoundException e)
+      {
+        final LocalizableMessage msg = ERR_CERTMGR_CLASS_NOT_FOUND.get(e
+            .getMessage());
+        throw new ExceptionInInitializerError(msg.toString());
+      }
+      catch (final SecurityException e)
+      {
+        final LocalizableMessage msg = ERR_CERTMGR_SECURITY.get(e.getMessage());
+        throw new ExceptionInInitializerError(msg.toString());
+      }
+      catch (final NoSuchMethodException e)
+      {
+        final LocalizableMessage msg = ERR_CERTMGR_NO_METHOD
+            .get(e.getMessage());
+        throw new ExceptionInInitializerError(msg.toString());
+      }
+    }
+
+
+
+    protected PlatformIMPL()
+    {
+    }
+
+
+
+    /**
+     * Add the certificate in the specified path to the specified keystore,
+     * creating the keystore using the specified type and path if it the
+     * keystore doesn't exist.
+     *
+     * @param ks
+     *          The keystore to add the certificate to, may be null if it
+     *          doesn't exist.
+     * @param ksType
+     *          The type to use if the keystore is created.
+     * @param ksPath
+     *          The path to the keystore if it is created.
+     * @param alias
+     *          The alias to store the certificate under.
+     * @param pwd
+     *          The password to use in saving the certificate.
+     * @param certPath
+     *          The path to the file containing the certificate.
+     * @throws KeyStoreException
+     *           If an error occurred adding the certificate to the keystore.
+     */
+    public final void addCertificate(KeyStore ks, final String ksType,
+        final String ksPath, final String alias, final char[] pwd,
+        final String certPath) throws KeyStoreException
+    {
+      try
+      {
+        final CertificateFactory cf = CertificateFactory.getInstance("X509");
+        final InputStream inStream = new FileInputStream(certPath);
+        if (ks == null)
+        {
+          ks = KeyStore.getInstance(ksType);
+          ks.load(null, pwd);
+        }
+        // Do not support certificate replies.
+        if (ks.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class))
+        {
+          final LocalizableMessage msg = ERR_CERTMGR_CERT_REPLIES_INVALID
+              .get(alias);
+          throw new KeyStoreException(msg.toString());
+        }
+        else if (!ks.containsAlias(alias)
+            || ks
+                .entryInstanceOf(alias, KeyStore.TrustedCertificateEntry.class))
+        {
+          trustedCert(alias, cf, ks, inStream);
         }
         else
         {
-          IMPL = new DefaultPlatformIMPL();
+          final LocalizableMessage msg = ERR_CERTMGR_ALIAS_INVALID.get(alias);
+          throw new KeyStoreException(msg.toString());
         }
+        final FileOutputStream fileOutStream = new FileOutputStream(ksPath);
+        ks.store(fileOutStream, pwd);
+        fileOutStream.close();
+        inStream.close();
+      }
+      catch (final Exception e)
+      {
+        final LocalizableMessage msg = ERR_CERTMGR_ADD_CERT.get(alias, e
+            .getMessage());
+        throw new KeyStoreException(msg.toString());
+      }
+    }
+
+
+
+    /**
+     * Delete the specified alias from the specified keystore.
+     *
+     * @param ks
+     *          The keystore to delete the alias from.
+     * @param ksPath
+     *          The path to the keystore.
+     * @param alias
+     *          The alias to use in the request generation.
+     * @param pwd
+     *          The keystore password to use.
+     * @throws KeyStoreException
+     *           If an error occurred deleting the alias.
+     */
+    public final void deleteAlias(final KeyStore ks, final String ksPath,
+        final String alias, final char[] pwd) throws KeyStoreException
+    {
+      try
+      {
+        if (ks == null)
+        {
+          final LocalizableMessage msg = ERR_CERTMGR_KEYSTORE_NONEXISTANT.get();
+          throw new KeyStoreException(msg.toString());
+        }
+        ks.deleteEntry(alias);
+        final FileOutputStream fs = new FileOutputStream(ksPath);
+        ks.store(fs, pwd);
+        fs.close();
+      }
+      catch (final Exception e)
+      {
+        final LocalizableMessage msg = ERR_CERTMGR_DELETE_ALIAS.get(alias, e
+            .getMessage());
+        throw new KeyStoreException(msg.toString());
+      }
+    }
+
+
+
+    /**
+     * Generate a certificate request. Note that this methods checks if the
+     * certificate request generation is allowed and throws an exception if it
+     * isn't supported. Some vendors JDKs aren't compatible with Sun's
+     * certificate request generation classes so they aren't supported.
+     *
+     * @param ks
+     *          The keystore to use in the request creation.
+     * @param ksType
+     *          The keystore type.
+     * @param ksPath
+     *          The path to the keystore.
+     * @param alias
+     *          The alias to use in the request generation.
+     * @param pwd
+     *          The keystore password to use.
+     * @param dn
+     *          A dn string to use as the certificate subject.
+     * @return A file object pointing at the created certificate request.
+     * @throws KeyStoreException
+     *           If the certificate request failed.
+     */
+    public final File generateCertificateRequest(final KeyStore ks,
+        final String ksType, final String ksPath, final String alias,
+        final char[] pwd, final String dn) throws KeyStoreException
+    {
+      if (!certReqAllowed)
+      {
+        final String vendor = System.getProperty("java.vendor");
+        final LocalizableMessage msg = ERR_CERTMGR_CERT_SIGN_REQ_NOT_SUPPORTED
+            .get(vendor);
+        throw new KeyStoreException(msg.toString());
+      }
+      final KeyStore keyStore = generateSelfSignedCertificate(ks, ksType,
+          ksPath, alias, pwd, dn, DEFAULT_VALIDITY);
+      File csrFile;
+      try
+      {
+        csrFile = File.createTempFile(TMPFILE_PREFIX, TMPFILE_EXT);
+        csrFile.deleteOnExit();
+        final PrintStream printStream = new PrintStream(new FileOutputStream(
+            csrFile.getAbsolutePath()));
+        if (keyStore == null)
+        {
+          final LocalizableMessage msg = ERR_CERTMGR_KEYSTORE_NONEXISTANT.get();
+          throw new KeyStoreException(msg.toString());
+        }
+        final PrivateKey privateKey = getPrivateKey(keyStore, alias, pwd);
+        if (privateKey == null)
+        {
+          final LocalizableMessage msg = ERR_CERTMGR_PRIVATE_KEY.get(alias);
+          throw new KeyStoreException(msg.toString());
+        }
+        final Certificate cert = keyStore.getCertificate(alias);
+        if (cert == null)
+        {
+          final LocalizableMessage msg = ERR_CERTMGR_ALIAS_NO_CERTIFICATE
+              .get(alias);
+          throw new KeyStoreException(msg.toString());
+        }
+        final Signature signature = Signature.getInstance(SIG_ALGORITHM);
+        signature.initSign(privateKey);
+        final Object request = pkcs10Cons.newInstance(cert.getPublicKey());
+        final Object subject = x500NameCons.newInstance(dn);
+        final Object signer = x500SignerCons.newInstance(signature, subject);
+        final Method encodeAndSign = pkcs10Class.getMethod(ENCODE_SIGN_METHOD,
+            x500SignerClass);
+        final Method print = pkcs10Class.getMethod(PRINT_METHOD,
+            PrintStream.class);
+        encodeAndSign.invoke(request, signer);
+        print.invoke(request, printStream);
+        printStream.close();
+      }
+      catch (final Exception e)
+      {
+        final LocalizableMessage msg = ERR_CERTMGR_CERT_REQUEST.get(alias, e
+            .getMessage());
+        throw new KeyStoreException(msg.toString());
+      }
+      return csrFile;
+    }
+
+
+
+    /**
+     * Generate a self-signed certificate using the specified alias, dn string
+     * and validity period. If the keystore does not exist, create it using the
+     * specified type and path.
+     *
+     * @param ks
+     *          The keystore to save the certificate in. May be null if it does
+     *          not exist.
+     * @param ksType
+     *          The keystore type to use if the keystore is created.
+     * @param ksPath
+     *          The path to the keystore if the keystore is created.
+     * @param alias
+     *          The alias to store the certificate under.
+     * @param pwd
+     *          The password to us in saving the certificate.
+     * @param dn
+     *          The dn string used as the certificate subject.
+     * @param validity
+     *          The validity of the certificate in days.
+     * @return The keystore that the self-signed certificate was stored in.
+     * @throws KeyStoreException
+     *           If the self-signed certificate cannot be generated.
+     */
+    public final KeyStore generateSelfSignedCertificate(KeyStore ks,
+        final String ksType, final String ksPath, final String alias,
+        final char[] pwd, final String dn, final int validity)
+        throws KeyStoreException
+    {
+      try
+      {
+        if (ks == null)
+        {
+          ks = KeyStore.getInstance(ksType);
+          ks.load(null, pwd);
+        }
+        else if (ks.containsAlias(alias))
+        {
+          final LocalizableMessage msg = ERR_CERTMGR_ALIAS_ALREADY_EXISTS
+              .get(alias);
+          throw new KeyStoreException(msg.toString());
+        }
+        final Object keypair = certKeyGenCons.newInstance(KEY_ALGORITHM,
+            SIG_ALGORITHM);
+        final Object subject = x500NameCons.newInstance(dn);
+        final Method certAndKeyGenGenerate = certKeyGenClass.getMethod(
+            GENERATE_METHOD, int.class);
+        certAndKeyGenGenerate.invoke(keypair, KEY_SIZE);
+        final Method certAndKeyGetPrivateKey = certKeyGenClass
+            .getMethod(GET_PRIVATE_KEY_METHOD);
+        final PrivateKey privatevKey = (PrivateKey) certAndKeyGetPrivateKey
+            .invoke(keypair);
+        final Certificate[] certificateChain = new Certificate[1];
+        final Method getSelfCertificate = certKeyGenClass.getMethod(
+            GET_SELFSIGNED_CERT_METHOD, x500NameClass, long.class);
+        final int days = validity * SEC_IN_DAY;
+        certificateChain[0] = (Certificate) getSelfCertificate.invoke(keypair,
+            subject, days);
+        ks.setKeyEntry(alias, privatevKey, pwd, certificateChain);
+        final FileOutputStream fileOutStream = new FileOutputStream(ksPath);
+        ks.store(fileOutStream, pwd);
+        fileOutStream.close();
+      }
+      catch (final Exception e)
+      {
+        final LocalizableMessage msg = ERR_CERTMGR_GEN_SELF_SIGNED_CERT.get(
+            alias, e.getMessage());
+        throw new KeyStoreException(msg.toString());
+      }
+      return ks;
+    }
+
+
+
+    /**
+     * Normalize the data in the specified buffer.
+     *
+     * @param buffer
+     *          The buffer to normalize.
+     */
+    public abstract void normalize(StringBuilder buffer);
+
+
+
+    /**
+     * Returns the private key associated with specified alias and keystore. The
+     * keystore was already checked for existance.
+     *
+     * @param ks
+     *          The keystore to get the private key from, it must exist.
+     * @param alias
+     *          The alias to get the private key of.
+     * @param pwd
+     *          The password used to get the key from the keystore.
+     * @return The private key of related to the alias.
+     * @throws KeyStoreException
+     *           If the alias is not in the keystore, the entry related to the
+     *           alias is not of
+     */
+    private PrivateKey getPrivateKey(final KeyStore ks, final String alias,
+        final char[] pwd) throws KeyStoreException
+    {
+      PrivateKey key = null;
+      try
+      {
+        if (!ks.containsAlias(alias))
+        {
+          final LocalizableMessage msg = ERR_CERTMGR_ALIAS_DOES_NOT_EXIST
+              .get(alias);
+          throw new KeyStoreException(msg.toString());
+        }
+        if (!ks.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class)
+            && !ks.entryInstanceOf(alias, KeyStore.SecretKeyEntry.class))
+        {
+          final LocalizableMessage msg = ERR_CERTMGR_ALIAS_INVALID_ENTRY_TYPE
+              .get(alias);
+          throw new KeyStoreException(msg.toString());
+        }
+        key = (PrivateKey) ks.getKey(alias, pwd);
+      }
+      catch (final Exception e)
+      {
+        final LocalizableMessage msg = ERR_CERTMGR_GET_KEY.get(alias, e
+            .getMessage());
+        throw new KeyStoreException(msg.toString());
+      }
+      return key;
+    }
+
+
+
+    /**
+     * Check that the issuer and subject DNs match.
+     *
+     * @param cert
+     *          The certificate to examine.
+     * @return {@code true} if the certificate is self-signed.
+     */
+    private boolean isSelfSigned(final X509Certificate cert)
+    {
+      return cert.getSubjectDN().equals(cert.getIssuerDN());
+    }
+
+
+
+    /**
+     * Generate a x509 certificate from the input stream. Verification is done
+     * only if it is self-signed.
+     *
+     * @param alias
+     *          The alias to save the certificate under.
+     * @param cf
+     *          The x509 certificate factory.
+     * @param ks
+     *          The keystore to add the certificate in.
+     * @param in
+     *          The input stream to read the certificate from.
+     * @throws KeyStoreException
+     *           If the alias exists already in the keystore, if the self-signed
+     *           certificate didn't verify, or the certificate could not be
+     *           stored.
+     */
+    private void trustedCert(final String alias, final CertificateFactory cf,
+        final KeyStore ks, final InputStream in) throws KeyStoreException
+    {
+      try
+      {
+        if (ks.containsAlias(alias) == true)
+        {
+          final LocalizableMessage msg = ERR_CERTMGR_ALIAS_ALREADY_EXISTS
+              .get(alias);
+          throw new KeyStoreException(msg.toString());
+        }
+        final X509Certificate cert = (X509Certificate) cf
+            .generateCertificate(in);
+        if (isSelfSigned(cert))
+        {
+          cert.verify(cert.getPublicKey());
+        }
+        ks.setCertificateEntry(alias, cert);
+      }
+      catch (final Exception e)
+      {
+        final LocalizableMessage msg = ERR_CERTMGR_TRUSTED_CERT.get(alias, e
+            .getMessage());
+        throw new KeyStoreException(msg.toString());
+      }
+    }
+  }
+
+
+
+  /**
+   * Sun 5 JDK platform class.
+   */
+  private static class Sun5PlatformIMPL extends PlatformIMPL
+  {
+    // normalize method.
+    private static final Method NORMALIZE;
+    // Normalized form method.
+    private static final Object FORM_NFKC;
+
+    static
+    {
+      Method normalize = null;
+      Object formNFKC = null;
+      try
+      {
+        final Class<?> normalizer = Class.forName("sun.text.Normalizer");
+        formNFKC = normalizer.getField("DECOMP_COMPAT").get(null);
+        final Class<?> normalizerForm = Class
+            .forName("sun.text.Normalizer$Mode");
+        normalize = normalizer.getMethod("normalize", String.class,
+            normalizerForm, Integer.TYPE);
+      }
+      catch (final Exception ex)
+      {
+        // Do not use Normalizer. The values are already set to null.
+      }
+      NORMALIZE = normalize;
+      FORM_NFKC = formNFKC;
+    }
+
+
+
+    @Override
+    public void normalize(final StringBuilder buffer)
+    {
+      try
+      {
+        final String normal = (String) NORMALIZE.invoke(null,
+            buffer.toString(), FORM_NFKC, 0);
+        buffer.replace(0, buffer.length(), normal);
+      }
+      catch (final Exception ex)
+      {
+        // Don't do anything. buffer should be used.
+      }
+    }
+  }
+
+
+
+  // Prefix that determines which security package to use.
+  private static String pkgPrefix;
+
+  // IBM security package doesn't appear to support PCKS10, this flags turns
+  // off support for that.
+  private static boolean certReqAllowed;
+
+  // The two security package prefixes (IBM and SUN).
+  private static final String IBM_SEC = "com.ibm.security";
+
+  private static final String SUN_SEC = "sun.security";
+
+  private static final PlatformIMPL IMPL;
+
+  static
+  {
+    final String vendor = System.getProperty("java.vendor");
+    final String ver = System.getProperty("java.version");
+
+    if (vendor.startsWith("IBM"))
+    {
+      pkgPrefix = IBM_SEC;
+      certReqAllowed = false;
+      if (ver.startsWith("1.5"))
+      {
+        IMPL = new IBM5PlatformIMPL();
       }
       else
       {
-        pkgPrefix = SUN_SEC;
-        certReqAllowed = true;
-        if(ver.startsWith("1.5"))
-        {
-         IMPL = new Sun5PlatformIMPL();
-        }
-        else
-        {
-          IMPL = new DefaultPlatformIMPL();
-        }
+        IMPL = new DefaultPlatformIMPL();
       }
     }
-
-   /**
-    * Platform base class. Performs all of the certificate management functions.
-    */
-    private abstract static class PlatformIMPL {
-
-        //Key size, key algorithm and signature algorithms used.
-        private static final  int KEY_SIZE = 1024;
-        private static final String KEY_ALGORITHM = "rsa";
-        private static final String SIG_ALGORITHM = "SHA1WithRSA";
-
-        //Time values used in validity calculations.
-        private static final int SEC_IN_DAY = 24 * 60 * 60;
-        private static final int DEFAULT_VALIDITY = 90 * SEC_IN_DAY;
-
-        //These two are used to build certificate request files.
-        private static final String TMPFILE_PREFIX = "CertificateManager-";
-        private static final String TMPFILE_EXT = ".csr";
-
-        //Methods pulled from the classes.
-        private static final String ENCODE_SIGN_METHOD = "encodeAndSign";
-        private static final String GENERATE_METHOD = "generate";
-        private static final String GET_PRIVATE_KEY_METHOD = "getPrivateKey";
-        private static final String GET_SELFSIGNED_CERT_METHOD =
-                                                          "getSelfCertificate";
-        private static final String PRINT_METHOD = "print";
-
-        //Classes needed to manage certificates.
-        private static Class<?> certKeyGenClass, X500NameClass,
-                                X500SignerClass, PKCS10Class;
-
-        //Constructors for each of the above classes.
-        private static Constructor<?> certKeyGenCons, X500NameCons,
-                                      X500SignerCons, pkcs10Cons;
-
-        static {
-          String x509pkg = pkgPrefix + ".x509";
-          String pkcs10Pkg = pkgPrefix + ".pkcs";
-          String certAndKeyGen=  x509pkg + ".CertAndKeyGen";
-          String X500Name =  x509pkg + ".X500Name";
-          String X500Signer = x509pkg + ".X500Signer";
-          try {
-            certKeyGenClass = Class.forName(certAndKeyGen);
-            X500NameClass = Class.forName(X500Name);
-            X500SignerClass = Class.forName(X500Signer);
-            if(certReqAllowed) {
-              String pkcs10 = pkcs10Pkg + ".PKCS10";
-              PKCS10Class = Class.forName(pkcs10);
-              pkcs10Cons = PKCS10Class.getConstructor(PublicKey.class);
-            }
-            certKeyGenCons =
-                    certKeyGenClass.getConstructor(String.class, String.class);
-            X500NameCons = X500NameClass.getConstructor(String.class);
-            X500SignerCons =
-                 X500SignerClass.getConstructor(Signature.class, X500NameClass);
-          } catch (ClassNotFoundException e) {
-            LocalizableMessage msg = ERR_CERTMGR_CLASS_NOT_FOUND.get(e.getMessage());
-            throw new ExceptionInInitializerError(msg.toString());
-          } catch (SecurityException e) {
-            LocalizableMessage msg = ERR_CERTMGR_SECURITY.get(e.getMessage());
-            throw new ExceptionInInitializerError(msg.toString());
-          } catch (NoSuchMethodException e) {
-            LocalizableMessage msg = ERR_CERTMGR_NO_METHOD.get(e.getMessage());
-            throw new ExceptionInInitializerError(msg.toString());
-          }
-        }
-
-        protected PlatformIMPL() {}
-
-        /**
-         * Generate a certificate request. Note that this methods checks if
-         * the certificate request generation is allowed and throws an
-         * exception if it isn't supported. Some vendors JDKs aren't compatible
-         * with Sun's certificate request generation classes so they aren't
-         * supported.
-         *
-         * @param ks The keystore to use in the request creation.
-         * @param ksType The keystore type.
-         * @param ksPath The path to the keystore.
-         * @param alias The alias to use in the request generation.
-         * @param pwd The keystore password to use.
-         * @param dn A dn string to use as the certificate subject.
-         *
-         * @return A file object pointing at the created certificate request.
-         * @throws KeyStoreException If the certificate request failed.
-         */
-        public final File
-        generateCertificateRequest(KeyStore ks, String ksType, String ksPath,
-            String alias, char[] pwd, String dn) throws KeyStoreException {
-          if(!certReqAllowed) {
-            String vendor = System.getProperty("java.vendor");
-            LocalizableMessage msg =
-              ERR_CERTMGR_CERT_SIGN_REQ_NOT_SUPPORTED.get(vendor);
-            throw new KeyStoreException(msg.toString());
-          }
-          KeyStore keyStore = generateSelfSignedCertificate(ks, ksType, ksPath,
-                                            alias, pwd, dn, DEFAULT_VALIDITY);
-          File csrFile;
-          try {
-            csrFile = File.createTempFile(TMPFILE_PREFIX, TMPFILE_EXT);
-            csrFile.deleteOnExit();
-            PrintStream printStream =
-              new PrintStream(new FileOutputStream(csrFile.getAbsolutePath()));
-            if(keyStore == null) {
-              LocalizableMessage msg = ERR_CERTMGR_KEYSTORE_NONEXISTANT.get();
-              throw new KeyStoreException(msg.toString());
-            }
-            PrivateKey privateKey = getPrivateKey(keyStore, alias, pwd);
-            if(privateKey == null) {
-              LocalizableMessage msg =  ERR_CERTMGR_PRIVATE_KEY.get(alias);
-              throw new KeyStoreException(msg.toString());
-            }
-            Certificate cert = keyStore.getCertificate(alias);
-            if(cert == null) {
-              LocalizableMessage msg = ERR_CERTMGR_ALIAS_NO_CERTIFICATE.get(alias);
-              throw new KeyStoreException(msg.toString());
-            }
-            Signature signature = Signature.getInstance(SIG_ALGORITHM);
-            signature.initSign(privateKey);
-            Object request = pkcs10Cons.newInstance(cert.getPublicKey());
-            Object subject = X500NameCons.newInstance(dn);
-            Object signer =
-              X500SignerCons.newInstance(signature, subject);
-            Method encodeAndSign =
-              PKCS10Class.getMethod(ENCODE_SIGN_METHOD, X500SignerClass);
-            Method print =
-              PKCS10Class.getMethod(PRINT_METHOD, PrintStream.class);
-            encodeAndSign.invoke(request, signer);
-            print.invoke(request, printStream);
-            printStream.close();
-          } catch (Exception e) {
-            LocalizableMessage msg = ERR_CERTMGR_CERT_REQUEST.get(alias,e.getMessage());
-            throw new KeyStoreException(msg.toString());
-          }
-          return csrFile;
-        }
-
-        /**
-         * Delete the specified alias from the specified keystore.
-         *
-         * @param ks The keystore to delete the alias from.
-         * @param ksPath The path to the keystore.
-         * @param alias The alias to use in the request generation.
-         * @param pwd The keystore password to use.
-         *
-         * @throws KeyStoreException If an error occurred deleting the alias.
-         */
-        public final void deleteAlias(KeyStore ks, String ksPath,
-            String alias, char[] pwd) throws KeyStoreException {
-              try {
-                  if(ks == null) {
-                      LocalizableMessage msg = ERR_CERTMGR_KEYSTORE_NONEXISTANT.get();
-                      throw new KeyStoreException(msg.toString());
-                  }
-                  ks.deleteEntry(alias);
-                  FileOutputStream fs = new FileOutputStream(ksPath);
-                  ks.store(fs, pwd);
-                  fs.close();
-              } catch (Exception e) {
-                  LocalizableMessage msg =
-                      ERR_CERTMGR_DELETE_ALIAS.get(alias,e.getMessage());
-                  throw new KeyStoreException(msg.toString());
-              }
-        }
-
-        /**
-         * Add the certificate in the specified path to the specified keystore,
-         * creating the keystore using the specified type and path if it the
-         * keystore doesn't exist.
-         *
-         * @param ks The keystore to add the certificate to, may be null if it
-         *           doesn't exist.
-         * @param ksType The type to use if the keystore is created.
-         * @param ksPath The path to the keystore if it is created.
-         * @param alias The alias to store the certificate under.
-         * @param pwd The password to use in saving the certificate.
-         * @param certPath The path to the file containing the certificate.
-         * @throws KeyStoreException If an error occurred adding the
-         *                           certificate to the keystore.
-         */
-        public final void addCertificate(KeyStore ks, String ksType,
-            String ksPath, String alias, char[] pwd, String certPath)
-        throws KeyStoreException {
-          try {
-            CertificateFactory cf = CertificateFactory.getInstance("X509");
-            InputStream inStream = new FileInputStream(certPath);
-            if(ks == null) {
-              ks = KeyStore.getInstance(ksType);
-              ks.load(null, pwd);
-            }
-            //Do not support certificate replies.
-            if (ks.entryInstanceOf(alias ,KeyStore.PrivateKeyEntry.class)) {
-              LocalizableMessage msg = ERR_CERTMGR_CERT_REPLIES_INVALID.get(alias);
-              throw new KeyStoreException(msg.toString());
-            } else if(!ks.containsAlias(alias) ||
-                ks.entryInstanceOf(alias,
-                    KeyStore.TrustedCertificateEntry.class))
-              trustedCert(alias, cf, ks, inStream);
-            else {
-              LocalizableMessage msg = ERR_CERTMGR_ALIAS_INVALID.get(alias);
-              throw new KeyStoreException(msg.toString());
-            }
-            FileOutputStream fileOutStream = new FileOutputStream(ksPath);
-            ks.store(fileOutStream, pwd);
-            fileOutStream.close();
-            inStream.close();
-          } catch (Exception e) {
-            LocalizableMessage msg =
-              ERR_CERTMGR_ADD_CERT.get(alias, e.getMessage());
-            throw new KeyStoreException(msg.toString());
-          }
-        }
-
-        /**
-         * Generate a self-signed certificate using the specified alias, dn
-         * string and validity period. If the keystore does not exist, create it
-         * using the specified type and path.
-         *
-         * @param ks The keystore to save the certificate in. May be null if it
-         *           does not exist.
-         * @param ksType The keystore type to use if the keystore is created.
-         * @param ksPath The path to the keystore if the keystore is created.
-         * @param alias The alias to store the certificate under.
-         * @param pwd The password to us in saving the certificate.
-         * @param dn The dn string used as the certificate subject.
-         * @param validity The validity of the certificate in days.
-         * @return The keystore that the self-signed certificate was stored in.
-         *
-         * @throws KeyStoreException If the self-signed certificate cannot be
-         *                           generated.
-         */
-        public final
-        KeyStore generateSelfSignedCertificate(KeyStore ks, String ksType,
-            String ksPath, String alias, char[] pwd, String dn, int validity)
-        throws KeyStoreException {
-          try {
-            if(ks == null) {
-              ks = KeyStore.getInstance(ksType);
-              ks.load(null, pwd);
-            } else if(ks.containsAlias(alias)) {
-              LocalizableMessage msg = ERR_CERTMGR_ALIAS_ALREADY_EXISTS.get(alias);
-              throw new KeyStoreException(msg.toString());
-            }
-            Object keypair =
-              certKeyGenCons.newInstance(KEY_ALGORITHM, SIG_ALGORITHM);
-            Object subject = X500NameCons.newInstance(dn);
-            Method certAndKeyGenGenerate =
-              certKeyGenClass.getMethod(GENERATE_METHOD, int.class);
-            certAndKeyGenGenerate.invoke(keypair, KEY_SIZE);
-            Method certAndKeyGetPrivateKey =
-              certKeyGenClass.getMethod(GET_PRIVATE_KEY_METHOD);
-            PrivateKey privatevKey =
-              (PrivateKey) certAndKeyGetPrivateKey.invoke(keypair);
-            Certificate[] certificateChain = new Certificate[1];
-            Method getSelfCertificate =
-              certKeyGenClass.getMethod(GET_SELFSIGNED_CERT_METHOD,
-                                        X500NameClass,long.class);
-            int days = validity * SEC_IN_DAY;
-            certificateChain[0] =
-              (Certificate) getSelfCertificate.invoke(keypair, subject, days);
-            ks.setKeyEntry(alias, privatevKey, pwd, certificateChain);
-            FileOutputStream fileOutStream = new FileOutputStream(ksPath);
-            ks.store(fileOutStream, pwd);
-            fileOutStream.close();
-          } catch (Exception e) {
-            LocalizableMessage msg =
-                   ERR_CERTMGR_GEN_SELF_SIGNED_CERT.get(alias, e.getMessage());
-            throw new KeyStoreException(msg.toString());
-          }
-          return ks;
-        }
-
-        /**
-         * Generate a x509 certificate from the input stream. Verification is
-         * done only if it is self-signed.
-         *
-         * @param alias The alias to save the certificate under.
-         * @param cf The x509 certificate factory.
-         * @param ks The keystore to add the certificate in.
-         * @param in The input stream to read the certificate from.
-         * @throws KeyStoreException If the alias exists already in the
-         *         keystore, if the self-signed certificate didn't verify, or
-         *         the certificate could not be stored.
-         */
-        private void trustedCert(String alias, CertificateFactory cf,
-             KeyStore ks, InputStream in) throws KeyStoreException {
-          try {
-            if (ks.containsAlias(alias) == true) {
-              LocalizableMessage msg = ERR_CERTMGR_ALIAS_ALREADY_EXISTS.get(alias);
-              throw new KeyStoreException(msg.toString());
-            }
-            X509Certificate cert = (X509Certificate) cf.generateCertificate(in);
-            if (isSelfSigned(cert))
-              cert.verify(cert.getPublicKey());
-            ks.setCertificateEntry(alias, cert);
-          } catch (Exception e) {
-            LocalizableMessage msg =
-              ERR_CERTMGR_TRUSTED_CERT.get(alias,e.getMessage());
-            throw new KeyStoreException(msg.toString());
-          }
-        }
-
-        /**
-         * Check that the issuer and subject DNs match.
-         *
-         * @param cert The certificate to examine.
-         * @return {@code true} if the certificate is self-signed.
-         */
-        private boolean isSelfSigned(X509Certificate cert) {
-          return cert.getSubjectDN().equals(cert.getIssuerDN());
-        }
-
-        /**
-         * Returns the private key associated with specified alias and keystore.
-         * The keystore was already checked for existance.
-         *
-         * @param ks The keystore to get the private key from, it must exist.
-         * @param alias The alias to get the private key of.
-         * @param pwd The password used to get the key from the keystore.
-         * @return The private key of related to the alias.
-         *
-         * @throws KeyStoreException If the alias is not in the keystore, the
-         *    entry related to the alias is not of
-         */
-        private PrivateKey getPrivateKey(KeyStore ks, String alias, char[] pwd)
-        throws KeyStoreException  {
-            PrivateKey key = null;
-            try {
-                if(!ks.containsAlias(alias)) {
-                    LocalizableMessage msg = ERR_CERTMGR_ALIAS_DOES_NOT_EXIST.get(alias);
-                    throw new KeyStoreException(msg.toString());
-                }
-                if(!ks.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class) &&
-                  !ks.entryInstanceOf(alias, KeyStore.SecretKeyEntry.class)) {
-                    LocalizableMessage msg =
-                                ERR_CERTMGR_ALIAS_INVALID_ENTRY_TYPE.get(alias);
-                    throw new KeyStoreException(msg.toString());
-                }
-                key = (PrivateKey)ks.getKey(alias, pwd);
-            } catch (Exception  e) {
-                LocalizableMessage msg =
-                    ERR_CERTMGR_GET_KEY.get(alias,e.getMessage());
-                throw new KeyStoreException(msg.toString());
-            }
-            return key;
-        }
-
-        /**
-         * Normalize the data in the specified buffer.
-         *
-         * @param buffer The buffer to normalize.
-         */
-         public abstract void normalize(StringBuilder buffer);
-    }
-
-    //Prevent instantiation.
-    private Platform() {}
-
-    /**
-     * Add the certificate in the specified path to the provided keystore;
-     * creating the keystore with the provided type and path if it doesn't
-     * exist.
-     *
-     * @param ks The keystore to add the certificate to, may be null if it
-     *           doesn't exist.
-     * @param ksType The type to use if the keystore is created.
-     * @param ksPath The path to the keystore if it is created.
-     * @param alias The alias to store the certificate under.
-     * @param pwd The password to use in saving the certificate.
-     * @param certPath The path to the file containing the certificate.
-     *
-     * @throws KeyStoreException If an error occurred adding the
-     *                           certificate to the keystore.
-     */
-    public static void addCertificate(KeyStore ks, String ksType, String ksPath,
-        String alias, char[] pwd, String certPath) throws KeyStoreException {
-        IMPL.addCertificate(ks,ksType, ksPath, alias, pwd, certPath);
-    }
-
-
-    /**
-     * Delete the specified alias from the provided keystore.
-     *
-     * @param ks The keystore to delete the alias from.
-     * @param ksPath The path to the keystore.
-     * @param alias The alias to use in the request generation.
-     * @param pwd The keystore password to use.
-     *
-     * @throws KeyStoreException If an error occurred deleting the alias.
-     */
-    public static void deleteAlias(KeyStore ks, String ksPath, String alias,
-        char[] pwd) throws KeyStoreException {
-        IMPL.deleteAlias(ks, ksPath, alias, pwd);
-    }
-
-
-    /**
-     * Generate a certificate request using the specified parameters.
-     *
-     * @param ks The keystore to use in the request creation.
-     * @param ksType The keystore type.
-     * @param ksPath The path to the keystore.
-     * @param alias The alias to use in the request generation.
-     * @param pwd The keystore password to use.
-     * @param dn A dn string to use as the certificate subject.
-     * @return A file object pointing at the created certificate request.
-     *
-     * @throws KeyStoreException If the certificate request failed.
-     */
-    public static File generateCertificateRequest(KeyStore ks, String ksType,
-        String ksPath, String alias, char[] pwd, String dn)
-    throws KeyStoreException {
-        return IMPL.generateCertificateRequest(ks, ksType, ksPath, alias,
-                                               pwd, dn);
-    }
-
-
-    /**
-     * Generate a self-signed certificate using the specified alias, dn
-     * string and validity period. If the keystore does not exist, it will be
-     * created using the specified keystore type and path.
-     *
-     * @param ks The keystore to save the certificate in. May be null if it
-     *           does not exist.
-     * @param ksType The keystore type to use if the keystore is created.
-     * @param ksPath The path to the keystore if the keystore is created.
-     * @param alias The alias to store the certificate under.
-     * @param pwd The password to us in saving the certificate.
-     * @param dn The dn string used as the certificate subject.
-     * @param validity The validity of the certificate in days.
-     *
-     * @throws KeyStoreException If the self-signed certificate cannot be
-     *                           generated.
-     */
-    public static void generateSelfSignedCertificate(KeyStore ks, String ksType,
-        String ksPath, String alias, char[] pwd, String dn, int validity)
-    throws KeyStoreException {
-        IMPL.generateSelfSignedCertificate(ks, ksType, ksPath, alias, pwd, dn,
-                                      validity);
-    }
-
-
-
-    /**
-     * Sun 5 JDK platform class.
-     */
-    private static class Sun5PlatformIMPL extends PlatformIMPL {
-       //normalize method.
-      private static final Method NORMALIZE;
-      //Normalized form method.
-      private static final Object FORM_NFKC;
-
-      static {
-        Method normalize = null;
-        Object formNFKC = null;
-        try {
-          Class<?> normalizer = Class.forName("sun.text.Normalizer");
-          formNFKC = normalizer.getField("DECOMP_COMPAT").get(null);
-          Class<?> normalizerForm = Class.forName("sun.text.Normalizer$Mode");
-          normalize = normalizer.getMethod("normalize", String.class,
-                 normalizerForm, Integer.TYPE);
-        }
-        catch (Exception ex) {
-        // Do not use Normalizer. The values are already set to null.
-        }
-      NORMALIZE = normalize;
-      FORM_NFKC = formNFKC;
-     }
-
-
-      @Override
-      public void normalize(StringBuilder buffer) {
-        try {
-          String normal =
-               (String) NORMALIZE.invoke(null, buffer.toString(), FORM_NFKC,0);
-          buffer.replace(0,buffer.length(),normal);
-        }
-        catch(Exception ex) {
-          //Don't do anything. buffer should be used.
-        }
+    else
+    {
+      pkgPrefix = SUN_SEC;
+      certReqAllowed = true;
+      if (ver.startsWith("1.5"))
+      {
+        IMPL = new Sun5PlatformIMPL();
       }
-   }
-
-    /**
-     * Default platform class.
-     */
-     private static class DefaultPlatformIMPL extends PlatformIMPL {
-       //normalize method.
-      private static final Method NORMALIZE;
-      //Normalized form method.
-      private static final Object FORM_NFKC;
-
-      static {
-
-        Method normalize = null;
-        Object formNFKC = null;
-        try {
-          Class<?> normalizer = Class.forName("java.text.Normalizer");
-          Class<?> normalizerForm = Class.forName("java.text.Normalizer$Form");
-          normalize = normalizer.getMethod("normalize", CharSequence.class,
-                normalizerForm);
-          formNFKC = normalizerForm.getField("NFKD").get(null);
-        }
-        catch (Exception ex) {
-        // Do not use Normalizer. The values are already set to null.
-        }
-        NORMALIZE = normalize;
-        FORM_NFKC = formNFKC;
-     }
-
-
-      @Override
-      public void normalize(StringBuilder buffer) {
-        try {
-          String normal = (String) NORMALIZE.invoke(null, buffer, FORM_NFKC);
-          buffer.replace(0,buffer.length(),normal);
-        }
-        catch(Exception ex) {
-          //Don't do anything. buffer should be used.
-        }
+      else
+      {
+        IMPL = new DefaultPlatformIMPL();
       }
-   }
-
-   /**
-    * IBM JDK 5 platform class.
-    */
-   private static class IBM5PlatformIMPL extends PlatformIMPL {
-
-    @Override
-    public void normalize(StringBuilder buffer) {
-      //No implementation.
     }
-   }
+  }
 
-   /**
-    * Normalize the specified buffer.
-    *
-    * @param buffer The buffer to normalize.
-    */
-   public static void normalize(StringBuilder buffer) {
-     IMPL.normalize(buffer);
-   }
 
-   /**
-    * Test if a platform java vendor property starts with the specified
-    * vendor string.
-    *
-    * @param vendor The vendor to check for.
-    * @return {@code true} if the java vendor starts with the specified vendor
-    *         string.
-    */
-   public static boolean isVendor(String vendor) {
-     String javaVendor = System.getProperty("java.vendor");
-     return javaVendor.startsWith(vendor);
-   }
+
+  /**
+   * Add the certificate in the specified path to the provided keystore;
+   * creating the keystore with the provided type and path if it doesn't exist.
+   *
+   * @param ks
+   *          The keystore to add the certificate to, may be null if it doesn't
+   *          exist.
+   * @param ksType
+   *          The type to use if the keystore is created.
+   * @param ksPath
+   *          The path to the keystore if it is created.
+   * @param alias
+   *          The alias to store the certificate under.
+   * @param pwd
+   *          The password to use in saving the certificate.
+   * @param certPath
+   *          The path to the file containing the certificate.
+   * @throws KeyStoreException
+   *           If an error occurred adding the certificate to the keystore.
+   */
+  public static void addCertificate(final KeyStore ks, final String ksType,
+      final String ksPath, final String alias, final char[] pwd,
+      final String certPath) throws KeyStoreException
+  {
+    IMPL.addCertificate(ks, ksType, ksPath, alias, pwd, certPath);
+  }
+
+
+
+  /**
+   * Delete the specified alias from the provided keystore.
+   *
+   * @param ks
+   *          The keystore to delete the alias from.
+   * @param ksPath
+   *          The path to the keystore.
+   * @param alias
+   *          The alias to use in the request generation.
+   * @param pwd
+   *          The keystore password to use.
+   * @throws KeyStoreException
+   *           If an error occurred deleting the alias.
+   */
+  public static void deleteAlias(final KeyStore ks, final String ksPath,
+      final String alias, final char[] pwd) throws KeyStoreException
+  {
+    IMPL.deleteAlias(ks, ksPath, alias, pwd);
+  }
+
+
+
+  /**
+   * Generate a certificate request using the specified parameters.
+   *
+   * @param ks
+   *          The keystore to use in the request creation.
+   * @param ksType
+   *          The keystore type.
+   * @param ksPath
+   *          The path to the keystore.
+   * @param alias
+   *          The alias to use in the request generation.
+   * @param pwd
+   *          The keystore password to use.
+   * @param dn
+   *          A dn string to use as the certificate subject.
+   * @return A file object pointing at the created certificate request.
+   * @throws KeyStoreException
+   *           If the certificate request failed.
+   */
+  public static File generateCertificateRequest(final KeyStore ks,
+      final String ksType, final String ksPath, final String alias,
+      final char[] pwd, final String dn) throws KeyStoreException
+  {
+    return IMPL.generateCertificateRequest(ks, ksType, ksPath, alias, pwd, dn);
+  }
+
+
+
+  /**
+   * Generate a self-signed certificate using the specified alias, dn string and
+   * validity period. If the keystore does not exist, it will be created using
+   * the specified keystore type and path.
+   *
+   * @param ks
+   *          The keystore to save the certificate in. May be null if it does
+   *          not exist.
+   * @param ksType
+   *          The keystore type to use if the keystore is created.
+   * @param ksPath
+   *          The path to the keystore if the keystore is created.
+   * @param alias
+   *          The alias to store the certificate under.
+   * @param pwd
+   *          The password to us in saving the certificate.
+   * @param dn
+   *          The dn string used as the certificate subject.
+   * @param validity
+   *          The validity of the certificate in days.
+   * @throws KeyStoreException
+   *           If the self-signed certificate cannot be generated.
+   */
+  public static void generateSelfSignedCertificate(final KeyStore ks,
+      final String ksType, final String ksPath, final String alias,
+      final char[] pwd, final String dn, final int validity)
+      throws KeyStoreException
+  {
+    IMPL.generateSelfSignedCertificate(ks, ksType, ksPath, alias, pwd, dn,
+        validity);
+  }
+
+
+
+  /**
+   * Test if a platform java vendor property starts with the specified vendor
+   * string.
+   *
+   * @param vendor
+   *          The vendor to check for.
+   * @return {@code true} if the java vendor starts with the specified vendor
+   *         string.
+   */
+  public static boolean isVendor(final String vendor)
+  {
+    final String javaVendor = System.getProperty("java.vendor");
+    return javaVendor.startsWith(vendor);
+  }
+
+
+
+  /**
+   * Normalize the specified buffer.
+   *
+   * @param buffer
+   *          The buffer to normalize.
+   */
+  public static void normalize(final StringBuilder buffer)
+  {
+    IMPL.normalize(buffer);
+  }
+
+
+
+  // Prevent instantiation.
+  private Platform()
+  {
+  }
 }
-
diff --git a/sdk/src/com/sun/opends/sdk/util/Predicate.java b/sdk/src/com/sun/opends/sdk/util/Predicate.java
index d2eb188..34253e0 100644
--- a/sdk/src/com/sun/opends/sdk/util/Predicate.java
+++ b/sdk/src/com/sun/opends/sdk/util/Predicate.java
@@ -30,28 +30,28 @@
 
 
 /**
- * Predicates transform input values of type {@code M} to a boolean
- * output value and are typically used for performing filtering.
+ * Predicates transform input values of type {@code M} to a boolean output value
+ * and are typically used for performing filtering.
  *
  * @param <M>
  *          The type of input values matched by this predicate.
  * @param <P>
- *          The type of the additional parameter to this predicate's
- *          {@code matches} method. Use {@link java.lang.Void} for
- *          predicates that do not need an additional parameter.
+ *          The type of the additional parameter to this predicate's {@code
+ *          matches} method. Use {@link java.lang.Void} for predicates that do
+ *          not need an additional parameter.
  */
 public interface Predicate<M, P>
 {
   /**
-   * Indicates whether or not this predicate matches the provided input
-   * value of type {@code M}.
+   * Indicates whether or not this predicate matches the provided input value of
+   * type {@code M}.
    *
    * @param value
    *          The input value for which to make the determination.
    * @param p
    *          A predicate specified parameter.
-   * @return {@code true} if this predicate matches {@code value},
-   *         otherwise {@code false}.
+   * @return {@code true} if this predicate matches {@code value}, otherwise
+   *         {@code false}.
    */
   boolean matches(M value, P p);
 }
diff --git a/sdk/src/com/sun/opends/sdk/util/RecursiveFutureResult.java b/sdk/src/com/sun/opends/sdk/util/RecursiveFutureResult.java
index 1d96342..e719784 100644
--- a/sdk/src/com/sun/opends/sdk/util/RecursiveFutureResult.java
+++ b/sdk/src/com/sun/opends/sdk/util/RecursiveFutureResult.java
@@ -40,23 +40,23 @@
 
 
 /**
- * An implementation of the {@code FutureResult} interface which can be
- * used to combine a sequence of two asynchronous operations into a
- * single future result. Implementations should override the methods
- * {@link #chainResult} and {@link #chainErrorResult} in order to define
- * the second asynchronous operation.
+ * An implementation of the {@code FutureResult} interface which can be used to
+ * combine a sequence of two asynchronous operations into a single future
+ * result. Implementations should override the methods {@link #chainResult} and
+ * {@link #chainErrorResult} in order to define the second asynchronous
+ * operation.
  *
  * @param <M>
  *          The type of the inner result.
  * @param <N>
  *          The type of the outer result.
  */
-public abstract class RecursiveFutureResult<M, N> implements
-    FutureResult<N>, ResultHandler<M>
+public abstract class RecursiveFutureResult<M, N> implements FutureResult<N>,
+    ResultHandler<M>
 {
   private final class FutureResultImpl extends AbstractFutureResult<N>
   {
-    private FutureResultImpl(ResultHandler<? super N> handler)
+    private FutureResultImpl(final ResultHandler<? super N> handler)
     {
       super(handler);
     }
@@ -67,7 +67,7 @@
     {
       if (innerFuture instanceof FutureResult<?>)
       {
-        FutureResult<?> tmp = (FutureResult<?>) innerFuture;
+        final FutureResult<?> tmp = (FutureResult<?>) innerFuture;
         return tmp.getRequestID();
       }
       else
@@ -81,8 +81,9 @@
     /**
      * {@inheritDoc}
      */
+    @Override
     protected ErrorResultException handleCancelRequest(
-        boolean mayInterruptIfRunning)
+        final boolean mayInterruptIfRunning)
     {
       innerFuture.cancel(mayInterruptIfRunning);
       if (outerFuture != null)
@@ -113,7 +114,7 @@
    * @param handler
    *          The outer result handler.
    */
-  protected RecursiveFutureResult(ResultHandler<? super N> handler)
+  protected RecursiveFutureResult(final ResultHandler<? super N> handler)
   {
     this.impl = new FutureResultImpl(handler);
   }
@@ -123,7 +124,7 @@
   /**
    * {@inheritDoc}
    */
-  public final boolean cancel(boolean mayInterruptIfRunning)
+  public final boolean cancel(final boolean mayInterruptIfRunning)
   {
     return impl.cancel(mayInterruptIfRunning);
   }
@@ -133,8 +134,7 @@
   /**
    * {@inheritDoc}
    */
-  public final N get() throws ErrorResultException,
-      InterruptedException
+  public final N get() throws ErrorResultException, InterruptedException
   {
     return impl.get();
   }
@@ -144,9 +144,8 @@
   /**
    * {@inheritDoc}
    */
-  public final N get(long timeout, TimeUnit unit)
-      throws ErrorResultException, TimeoutException,
-      InterruptedException
+  public final N get(final long timeout, final TimeUnit unit)
+      throws ErrorResultException, TimeoutException, InterruptedException
   {
     return impl.get(timeout, unit);
   }
@@ -166,7 +165,7 @@
   /**
    * {@inheritDoc}
    */
-  public final void handleErrorResult(ErrorResultException error)
+  public final void handleErrorResult(final ErrorResultException error)
   {
     try
     {
@@ -183,7 +182,7 @@
   /**
    * {@inheritDoc}
    */
-  public final void handleResult(M result)
+  public final void handleResult(final M result)
   {
     try
     {
@@ -218,13 +217,13 @@
 
 
   /**
-   * Sets the inner future for this result chain. This must be done
-   * before this future is published.
+   * Sets the inner future for this result chain. This must be done before this
+   * future is published.
    *
    * @param future
    *          The inner future.
    */
-  public final void setFutureResult(Future<?> future)
+  public final void setFutureResult(final Future<?> future)
   {
     this.innerFuture = future;
   }
@@ -232,9 +231,8 @@
 
 
   /**
-   * Invokes the outer request based on the error result of the inner
-   * request and returns a future representing the result of the outer
-   * request.
+   * Invokes the outer request based on the error result of the inner request
+   * and returns a future representing the result of the outer request.
    * <p>
    * The default implementation is to terminate further processing by
    * re-throwing the inner error result.
@@ -245,12 +243,12 @@
    *          The result handler to be used for the outer request.
    * @return A future representing the result of the outer request.
    * @throws ErrorResultException
-   *           If the outer request could not be invoked and processing
-   *           should terminate.
+   *           If the outer request could not be invoked and processing should
+   *           terminate.
    */
   protected FutureResult<? extends N> chainErrorResult(
-      ErrorResultException innerError, ResultHandler<? super N> handler)
-      throws ErrorResultException
+      final ErrorResultException innerError,
+      final ResultHandler<? super N> handler) throws ErrorResultException
   {
     throw innerError;
   }
@@ -258,8 +256,8 @@
 
 
   /**
-   * Invokes the outer request based on the result of the inner request
-   * and returns a future representing the result of the outer request.
+   * Invokes the outer request based on the result of the inner request and
+   * returns a future representing the result of the outer request.
    *
    * @param innerResult
    *          The result of the inner request.
@@ -267,11 +265,10 @@
    *          The result handler to be used for the outer request.
    * @return A future representing the result of the outer request.
    * @throws ErrorResultException
-   *           If the outer request could not be invoked and processing
-   *           should terminate.
+   *           If the outer request could not be invoked and processing should
+   *           terminate.
    */
-  protected abstract FutureResult<? extends N> chainResult(
-      M innerResult, ResultHandler<? super N> handler)
-      throws ErrorResultException;
+  protected abstract FutureResult<? extends N> chainResult(M innerResult,
+      ResultHandler<? super N> handler) throws ErrorResultException;
 
 }
diff --git a/sdk/src/com/sun/opends/sdk/util/SSLUtils.java b/sdk/src/com/sun/opends/sdk/util/SSLUtils.java
deleted file mode 100644
index 1a1ba2f..0000000
--- a/sdk/src/com/sun/opends/sdk/util/SSLUtils.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.sun.opends.sdk.util;
-
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.TrustManager;
-
-/**
- * Created by IntelliJ IDEA.
- * User: boli
- * Date: Oct 22, 2009
- * Time: 3:10:13 PM
- * To change this template use File | Settings | File Templates.
- */
-public class SSLUtils
-{
-  public static SSLContext getSSLContext(TrustManager trustManager,
-                                         KeyManager keyManager)
-      throws KeyManagementException, NoSuchAlgorithmException {
-    TrustManager[] tm = null;
-    if (trustManager != null)
-    {
-      tm = new TrustManager[] {trustManager};
-    }
-
-    KeyManager[] km = null;
-    if (keyManager != null)
-    {
-      km = new KeyManager[] {keyManager};
-    }
-
-    SSLContext sslContext = SSLContext.getInstance("TLSv1");
-    sslContext.init(km, tm, null);
-
-    return sslContext;
-  }
-}
diff --git a/sdk/src/com/sun/opends/sdk/util/SizeLimitInputStream.java b/sdk/src/com/sun/opends/sdk/util/SizeLimitInputStream.java
index 5a02dad..9bdf0ed 100644
--- a/sdk/src/com/sun/opends/sdk/util/SizeLimitInputStream.java
+++ b/sdk/src/com/sun/opends/sdk/util/SizeLimitInputStream.java
@@ -26,9 +26,13 @@
  */
 package com.sun.opends.sdk.util;
 
+
+
 import java.io.IOException;
 import java.io.InputStream;
 
+
+
 /**
  * An implementation of input stream that enforces an read size limit.
  */
@@ -36,8 +40,10 @@
 {
   private int bytesRead;
   private int markBytesRead;
-  private int readLimit;
-  private InputStream parentStream;
+  private final int readLimit;
+  private final InputStream parentStream;
+
+
 
   /**
    * Creates a new a new size limit input stream.
@@ -47,119 +53,39 @@
    * @param readLimit
    *          The size limit.
    */
-  public SizeLimitInputStream(InputStream parentStream, int readLimit)
+  public SizeLimitInputStream(final InputStream parentStream,
+      final int readLimit)
   {
     this.parentStream = parentStream;
     this.readLimit = readLimit;
   }
 
+
+
   /**
    * {@inheritDoc}
    */
+  @Override
   public int available() throws IOException
   {
-    int streamAvail = parentStream.available();
-    int limitedAvail = readLimit - bytesRead;
+    final int streamAvail = parentStream.available();
+    final int limitedAvail = readLimit - bytesRead;
     return limitedAvail < streamAvail ? limitedAvail : streamAvail;
   }
 
+
+
   /**
    * {@inheritDoc}
    */
-  public synchronized void mark(int readlimit)
+  @Override
+  public void close() throws IOException
   {
-    parentStream.mark(readlimit);
-    markBytesRead = bytesRead;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public int read() throws IOException
-  {
-    if(bytesRead >= readLimit)
-    {
-      return -1;
-    }
-
-    int b = parentStream.read();
-    if (b != -1)
-    {
-      ++bytesRead;
-    }
-    return b;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public int read(byte b[], int off, int len) throws IOException
-  {
-    if(off < 0 || len < 0 || off+len > b.length)
-    {
-      throw new IndexOutOfBoundsException();
-    }
-
-    if(len == 0)
-    {
-      return 0;
-    }
-
-    if(bytesRead >= readLimit)
-    {
-      return -1;
-    }
-
-    if(bytesRead + len > readLimit)
-    {
-      len = readLimit - bytesRead;
-    }
-
-    int readLen = parentStream.read(b, off, len);
-    if(readLen > 0)
-    {
-      bytesRead += readLen;
-    }
-    return readLen;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public synchronized void reset() throws IOException
-  {
-    parentStream.reset();
-    bytesRead = markBytesRead;
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public long skip(long n) throws IOException
-  {
-    if(bytesRead + n > readLimit)
-    {
-      n = readLimit - bytesRead;
-    }
-
-    bytesRead += n;
-    return parentStream.skip(n);
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean markSupported() {
-    return parentStream.markSupported();
-  }
-
-  /**
-   * {@inheritDoc}
-   */
-  public void close() throws IOException {
     parentStream.close();
   }
 
+
+
   /**
    * Retrieves the number of bytes read from this stream.
    *
@@ -170,6 +96,8 @@
     return bytesRead;
   }
 
+
+
   /**
    * Retrieves the size limit of this stream.
    *
@@ -179,4 +107,113 @@
   {
     return readLimit;
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public synchronized void mark(final int readlimit)
+  {
+    parentStream.mark(readlimit);
+    markBytesRead = bytesRead;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean markSupported()
+  {
+    return parentStream.markSupported();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int read() throws IOException
+  {
+    if (bytesRead >= readLimit)
+    {
+      return -1;
+    }
+
+    final int b = parentStream.read();
+    if (b != -1)
+    {
+      ++bytesRead;
+    }
+    return b;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int read(final byte b[], final int off, int len) throws IOException
+  {
+    if (off < 0 || len < 0 || off + len > b.length)
+    {
+      throw new IndexOutOfBoundsException();
+    }
+
+    if (len == 0)
+    {
+      return 0;
+    }
+
+    if (bytesRead >= readLimit)
+    {
+      return -1;
+    }
+
+    if (bytesRead + len > readLimit)
+    {
+      len = readLimit - bytesRead;
+    }
+
+    final int readLen = parentStream.read(b, off, len);
+    if (readLen > 0)
+    {
+      bytesRead += readLen;
+    }
+    return readLen;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public synchronized void reset() throws IOException
+  {
+    parentStream.reset();
+    bytesRead = markBytesRead;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public long skip(long n) throws IOException
+  {
+    if (bytesRead + n > readLimit)
+    {
+      n = readLimit - bytesRead;
+    }
+
+    bytesRead += n;
+    return parentStream.skip(n);
+  }
 }
diff --git a/sdk/src/com/sun/opends/sdk/util/StaticUtils.java b/sdk/src/com/sun/opends/sdk/util/StaticUtils.java
index ccd41b9..e40902c 100644
--- a/sdk/src/com/sun/opends/sdk/util/StaticUtils.java
+++ b/sdk/src/com/sun/opends/sdk/util/StaticUtils.java
@@ -29,7 +29,8 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_HEX_DECODE_INVALID_CHARACTER;
+import static com.sun.opends.sdk.messages.Messages.ERR_HEX_DECODE_INVALID_LENGTH;
 
 import java.lang.reflect.InvocationTargetException;
 import java.text.ParseException;
@@ -49,8 +50,10 @@
  */
 public final class StaticUtils
 {
-  public static final Logger DEBUG_LOG = Logger
-      .getLogger("org.opends.sdk");
+  /**
+   * The debug logger which should be used by the SDK.
+   */
+  public static final Logger DEBUG_LOG = Logger.getLogger("org.opends.sdk");
 
   /**
    * The end-of-line character for this platform.
@@ -67,16 +70,14 @@
 
 
   /**
-   * Retrieves a string representation of the provided byte in
-   * hexadecimal.
+   * Retrieves a string representation of the provided byte in hexadecimal.
    *
    * @param b
    *          The byte for which to retrieve the hexadecimal string
    *          representation.
-   * @return The string representation of the provided byte in
-   *         hexadecimal.
+   * @return The string representation of the provided byte in hexadecimal.
    */
-  public static String byteToHex(byte b)
+  public static String byteToHex(final byte b)
   {
     switch (b & 0xFF)
     {
@@ -600,13 +601,544 @@
 
 
   /**
-   * Attempts to compress the data in the provided source array into the
-   * given destination array. If the compressed data will fit into the
-   * destination array, then this method will return the number of bytes
-   * of compressed data in the array. Otherwise, it will return -1 to
-   * indicate that the compression was not successful. Note that if -1
-   * is returned, then the data in the destination array should be
-   * considered invalid.
+   * Retrieves a string representation of the provided byte in hexadecimal.
+   *
+   * @param b
+   *          The byte for which to retrieve the hexadecimal string
+   *          representation.
+   * @return The string representation of the provided byte in hexadecimal using
+   *         lowercase characters.
+   */
+  public static String byteToLowerHex(final byte b)
+  {
+    switch (b & 0xFF)
+    {
+    case 0x00:
+      return "00";
+    case 0x01:
+      return "01";
+    case 0x02:
+      return "02";
+    case 0x03:
+      return "03";
+    case 0x04:
+      return "04";
+    case 0x05:
+      return "05";
+    case 0x06:
+      return "06";
+    case 0x07:
+      return "07";
+    case 0x08:
+      return "08";
+    case 0x09:
+      return "09";
+    case 0x0A:
+      return "0a";
+    case 0x0B:
+      return "0b";
+    case 0x0C:
+      return "0c";
+    case 0x0D:
+      return "0d";
+    case 0x0E:
+      return "0e";
+    case 0x0F:
+      return "0f";
+    case 0x10:
+      return "10";
+    case 0x11:
+      return "11";
+    case 0x12:
+      return "12";
+    case 0x13:
+      return "13";
+    case 0x14:
+      return "14";
+    case 0x15:
+      return "15";
+    case 0x16:
+      return "16";
+    case 0x17:
+      return "17";
+    case 0x18:
+      return "18";
+    case 0x19:
+      return "19";
+    case 0x1A:
+      return "1a";
+    case 0x1B:
+      return "1b";
+    case 0x1C:
+      return "1c";
+    case 0x1D:
+      return "1d";
+    case 0x1E:
+      return "1e";
+    case 0x1F:
+      return "1f";
+    case 0x20:
+      return "20";
+    case 0x21:
+      return "21";
+    case 0x22:
+      return "22";
+    case 0x23:
+      return "23";
+    case 0x24:
+      return "24";
+    case 0x25:
+      return "25";
+    case 0x26:
+      return "26";
+    case 0x27:
+      return "27";
+    case 0x28:
+      return "28";
+    case 0x29:
+      return "29";
+    case 0x2A:
+      return "2a";
+    case 0x2B:
+      return "2b";
+    case 0x2C:
+      return "2c";
+    case 0x2D:
+      return "2d";
+    case 0x2E:
+      return "2e";
+    case 0x2F:
+      return "2f";
+    case 0x30:
+      return "30";
+    case 0x31:
+      return "31";
+    case 0x32:
+      return "32";
+    case 0x33:
+      return "33";
+    case 0x34:
+      return "34";
+    case 0x35:
+      return "35";
+    case 0x36:
+      return "36";
+    case 0x37:
+      return "37";
+    case 0x38:
+      return "38";
+    case 0x39:
+      return "39";
+    case 0x3A:
+      return "3a";
+    case 0x3B:
+      return "3b";
+    case 0x3C:
+      return "3c";
+    case 0x3D:
+      return "3d";
+    case 0x3E:
+      return "3e";
+    case 0x3F:
+      return "3f";
+    case 0x40:
+      return "40";
+    case 0x41:
+      return "41";
+    case 0x42:
+      return "42";
+    case 0x43:
+      return "43";
+    case 0x44:
+      return "44";
+    case 0x45:
+      return "45";
+    case 0x46:
+      return "46";
+    case 0x47:
+      return "47";
+    case 0x48:
+      return "48";
+    case 0x49:
+      return "49";
+    case 0x4A:
+      return "4a";
+    case 0x4B:
+      return "4b";
+    case 0x4C:
+      return "4c";
+    case 0x4D:
+      return "4d";
+    case 0x4E:
+      return "4e";
+    case 0x4F:
+      return "4f";
+    case 0x50:
+      return "50";
+    case 0x51:
+      return "51";
+    case 0x52:
+      return "52";
+    case 0x53:
+      return "53";
+    case 0x54:
+      return "54";
+    case 0x55:
+      return "55";
+    case 0x56:
+      return "56";
+    case 0x57:
+      return "57";
+    case 0x58:
+      return "58";
+    case 0x59:
+      return "59";
+    case 0x5A:
+      return "5a";
+    case 0x5B:
+      return "5b";
+    case 0x5C:
+      return "5c";
+    case 0x5D:
+      return "5d";
+    case 0x5E:
+      return "5e";
+    case 0x5F:
+      return "5f";
+    case 0x60:
+      return "60";
+    case 0x61:
+      return "61";
+    case 0x62:
+      return "62";
+    case 0x63:
+      return "63";
+    case 0x64:
+      return "64";
+    case 0x65:
+      return "65";
+    case 0x66:
+      return "66";
+    case 0x67:
+      return "67";
+    case 0x68:
+      return "68";
+    case 0x69:
+      return "69";
+    case 0x6A:
+      return "6a";
+    case 0x6B:
+      return "6b";
+    case 0x6C:
+      return "6c";
+    case 0x6D:
+      return "6d";
+    case 0x6E:
+      return "6e";
+    case 0x6F:
+      return "6f";
+    case 0x70:
+      return "70";
+    case 0x71:
+      return "71";
+    case 0x72:
+      return "72";
+    case 0x73:
+      return "73";
+    case 0x74:
+      return "74";
+    case 0x75:
+      return "75";
+    case 0x76:
+      return "76";
+    case 0x77:
+      return "77";
+    case 0x78:
+      return "78";
+    case 0x79:
+      return "79";
+    case 0x7A:
+      return "7a";
+    case 0x7B:
+      return "7b";
+    case 0x7C:
+      return "7c";
+    case 0x7D:
+      return "7d";
+    case 0x7E:
+      return "7e";
+    case 0x7F:
+      return "7f";
+    case 0x80:
+      return "80";
+    case 0x81:
+      return "81";
+    case 0x82:
+      return "82";
+    case 0x83:
+      return "83";
+    case 0x84:
+      return "84";
+    case 0x85:
+      return "85";
+    case 0x86:
+      return "86";
+    case 0x87:
+      return "87";
+    case 0x88:
+      return "88";
+    case 0x89:
+      return "89";
+    case 0x8A:
+      return "8a";
+    case 0x8B:
+      return "8b";
+    case 0x8C:
+      return "8c";
+    case 0x8D:
+      return "8d";
+    case 0x8E:
+      return "8e";
+    case 0x8F:
+      return "8f";
+    case 0x90:
+      return "90";
+    case 0x91:
+      return "91";
+    case 0x92:
+      return "92";
+    case 0x93:
+      return "93";
+    case 0x94:
+      return "94";
+    case 0x95:
+      return "95";
+    case 0x96:
+      return "96";
+    case 0x97:
+      return "97";
+    case 0x98:
+      return "98";
+    case 0x99:
+      return "99";
+    case 0x9A:
+      return "9a";
+    case 0x9B:
+      return "9b";
+    case 0x9C:
+      return "9c";
+    case 0x9D:
+      return "9d";
+    case 0x9E:
+      return "9e";
+    case 0x9F:
+      return "9f";
+    case 0xA0:
+      return "a0";
+    case 0xA1:
+      return "a1";
+    case 0xA2:
+      return "a2";
+    case 0xA3:
+      return "a3";
+    case 0xA4:
+      return "a4";
+    case 0xA5:
+      return "a5";
+    case 0xA6:
+      return "a6";
+    case 0xA7:
+      return "a7";
+    case 0xA8:
+      return "a8";
+    case 0xA9:
+      return "a9";
+    case 0xAA:
+      return "aa";
+    case 0xAB:
+      return "ab";
+    case 0xAC:
+      return "ac";
+    case 0xAD:
+      return "ad";
+    case 0xAE:
+      return "ae";
+    case 0xAF:
+      return "af";
+    case 0xB0:
+      return "b0";
+    case 0xB1:
+      return "b1";
+    case 0xB2:
+      return "b2";
+    case 0xB3:
+      return "b3";
+    case 0xB4:
+      return "b4";
+    case 0xB5:
+      return "b5";
+    case 0xB6:
+      return "b6";
+    case 0xB7:
+      return "b7";
+    case 0xB8:
+      return "b8";
+    case 0xB9:
+      return "b9";
+    case 0xBA:
+      return "ba";
+    case 0xBB:
+      return "bb";
+    case 0xBC:
+      return "bc";
+    case 0xBD:
+      return "bd";
+    case 0xBE:
+      return "be";
+    case 0xBF:
+      return "bf";
+    case 0xC0:
+      return "c0";
+    case 0xC1:
+      return "c1";
+    case 0xC2:
+      return "c2";
+    case 0xC3:
+      return "c3";
+    case 0xC4:
+      return "c4";
+    case 0xC5:
+      return "c5";
+    case 0xC6:
+      return "c6";
+    case 0xC7:
+      return "c7";
+    case 0xC8:
+      return "c8";
+    case 0xC9:
+      return "c9";
+    case 0xCA:
+      return "ca";
+    case 0xCB:
+      return "cb";
+    case 0xCC:
+      return "cc";
+    case 0xCD:
+      return "cd";
+    case 0xCE:
+      return "ce";
+    case 0xCF:
+      return "cf";
+    case 0xD0:
+      return "d0";
+    case 0xD1:
+      return "d1";
+    case 0xD2:
+      return "d2";
+    case 0xD3:
+      return "d3";
+    case 0xD4:
+      return "d4";
+    case 0xD5:
+      return "d5";
+    case 0xD6:
+      return "d6";
+    case 0xD7:
+      return "d7";
+    case 0xD8:
+      return "d8";
+    case 0xD9:
+      return "d9";
+    case 0xDA:
+      return "da";
+    case 0xDB:
+      return "db";
+    case 0xDC:
+      return "dc";
+    case 0xDD:
+      return "dd";
+    case 0xDE:
+      return "de";
+    case 0xDF:
+      return "df";
+    case 0xE0:
+      return "e0";
+    case 0xE1:
+      return "e1";
+    case 0xE2:
+      return "e2";
+    case 0xE3:
+      return "e3";
+    case 0xE4:
+      return "e4";
+    case 0xE5:
+      return "e5";
+    case 0xE6:
+      return "e6";
+    case 0xE7:
+      return "e7";
+    case 0xE8:
+      return "e8";
+    case 0xE9:
+      return "e9";
+    case 0xEA:
+      return "ea";
+    case 0xEB:
+      return "eb";
+    case 0xEC:
+      return "ec";
+    case 0xED:
+      return "ed";
+    case 0xEE:
+      return "ee";
+    case 0xEF:
+      return "ef";
+    case 0xF0:
+      return "f0";
+    case 0xF1:
+      return "f1";
+    case 0xF2:
+      return "f2";
+    case 0xF3:
+      return "f3";
+    case 0xF4:
+      return "f4";
+    case 0xF5:
+      return "f5";
+    case 0xF6:
+      return "f6";
+    case 0xF7:
+      return "f7";
+    case 0xF8:
+      return "f8";
+    case 0xF9:
+      return "f9";
+    case 0xFA:
+      return "fa";
+    case 0xFB:
+      return "fb";
+    case 0xFC:
+      return "fc";
+    case 0xFD:
+      return "fd";
+    case 0xFE:
+      return "fe";
+    case 0xFF:
+      return "ff";
+    default:
+      return "??";
+    }
+  }
+
+
+
+  /**
+   * Attempts to compress the data in the provided source array into the given
+   * destination array. If the compressed data will fit into the destination
+   * array, then this method will return the number of bytes of compressed data
+   * in the array. Otherwise, it will return -1 to indicate that the compression
+   * was not successful. Note that if -1 is returned, then the data in the
+   * destination array should be considered invalid.
    *
    * @param src
    *          The array containing the raw data to compress.
@@ -615,8 +1147,7 @@
    * @param srcLen
    *          The maximum number of source data bytes to compress.
    * @param dst
-   *          The array into which the compressed data should be
-   *          written.
+   *          The array into which the compressed data should be written.
    * @param dstOff
    *          The start offset of the compressed data.
    * @param dstLen
@@ -624,8 +1155,8 @@
    * @return The number of bytes of compressed data, or -1 if it was not
    *         possible to actually compress the data.
    */
-  public static int compress(byte[] src, int srcOff, int srcLen,
-      byte[] dst, int dstOff, int dstLen)
+  public static int compress(final byte[] src, final int srcOff,
+      final int srcLen, final byte[] dst, final int dstOff, final int dstLen)
   {
     final Deflater deflater = new Deflater();
     try
@@ -633,8 +1164,7 @@
       deflater.setInput(src, srcOff, srcLen);
       deflater.finish();
 
-      final int compressedLength = deflater
-          .deflate(dst, dstOff, dstLen);
+      final int compressedLength = deflater.deflate(dst, dstOff, dstLen);
       if (deflater.finished())
       {
         return compressedLength;
@@ -653,26 +1183,26 @@
 
 
   /**
-   * Attempts to compress the data in the provided byte sequence into
-   * the provided byte string builder. Note that if compression was not
-   * successful, then the byte string builder will be left unchanged.
+   * Attempts to compress the data in the provided byte sequence into the
+   * provided byte string builder. Note that if compression was not successful,
+   * then the byte string builder will be left unchanged.
    *
    * @param input
    *          The source data to be compressed.
    * @param output
-   *          The destination buffer to which the compressed data will
-   *          be appended.
+   *          The destination buffer to which the compressed data will be
+   *          appended.
    * @return <code>true</code> if compression was successful or
    *         <code>false</code> otherwise.
    */
-  public static boolean compress(ByteSequence input,
-      ByteStringBuilder output)
+  public static boolean compress(final ByteSequence input,
+      final ByteStringBuilder output)
   {
-    byte[] inputBytes = input.toByteArray();
-    byte[] outputBytes = new byte[inputBytes.length];
+    final byte[] inputBytes = input.toByteArray();
+    final byte[] outputBytes = new byte[inputBytes.length];
 
-    final int compressedSize = compress(inputBytes, 0,
-        inputBytes.length, outputBytes, 0, outputBytes.length);
+    final int compressedSize = compress(inputBytes, 0, inputBytes.length,
+        outputBytes, 0, outputBytes.length);
 
     if (compressedSize != -1)
     {
@@ -691,138 +1221,19 @@
 
 
 
-  public static ByteString evaluateEscapes(SubstringReader reader,
-      char[] escapeChars, boolean trim) throws DecodeException
-  {
-    return evaluateEscapes(reader, escapeChars, escapeChars, trim);
-  }
-
-
-
-  public static ByteString evaluateEscapes(SubstringReader reader,
-      char[] escapeChars, char[] delimiterChars, boolean trim)
-      throws DecodeException
-  {
-    int length = 0;
-    int lengthWithoutSpace = 0;
-    char c;
-    ByteStringBuilder valueBuffer = null;
-
-    if (trim)
-    {
-      reader.skipWhitespaces();
-    }
-
-    reader.mark();
-    while (reader.remaining() > 0)
-    {
-      c = reader.read();
-      if (c == 0x5C) // The backslash character
-      {
-        if (valueBuffer == null)
-        {
-          valueBuffer = new ByteStringBuilder();
-        }
-        valueBuffer.append(reader.read(length));
-        valueBuffer.append(evaluateEscapedChar(reader, escapeChars));
-        reader.mark();
-        length = lengthWithoutSpace = 0;
-      }
-      if (delimiterChars != null)
-      {
-        for (final char delimiterChar : delimiterChars)
-        {
-          if (c == delimiterChar)
-          {
-            reader.reset();
-            if (valueBuffer != null)
-            {
-              if (trim)
-              {
-                valueBuffer.append(reader.read(lengthWithoutSpace));
-              }
-              else
-              {
-                valueBuffer.append(reader.read(length));
-              }
-              return valueBuffer.toByteString();
-            }
-            else
-            {
-              if (trim)
-              {
-                if (lengthWithoutSpace > 0)
-                {
-                  return ByteString.valueOf(reader
-                      .read(lengthWithoutSpace));
-                }
-                return ByteString.empty();
-              }
-              if (length > 0)
-              {
-                return ByteString.valueOf(reader.read(length));
-              }
-              return ByteString.empty();
-            }
-          }
-        }
-      }
-      length++;
-      if (c != ' ')
-      {
-        lengthWithoutSpace = length;
-      }
-      else
-      {
-        lengthWithoutSpace++;
-      }
-    }
-
-    reader.reset();
-    if (valueBuffer != null)
-    {
-      if (trim)
-      {
-        valueBuffer.append(reader.read(lengthWithoutSpace));
-      }
-      else
-      {
-        valueBuffer.append(reader.read(length));
-      }
-      return valueBuffer.toByteString();
-    }
-    else
-    {
-      if (trim)
-      {
-        if (lengthWithoutSpace > 0)
-        {
-          return ByteString.valueOf(reader.read(lengthWithoutSpace));
-        }
-        return ByteString.empty();
-      }
-      if (length > 0)
-      {
-        return ByteString.valueOf(reader.read(length));
-      }
-      return ByteString.empty();
-    }
-  }
-
-
-
   /**
-   * Returns a string containing provided date formatted using the
-   * generalized time syntax.
+   * Returns a string containing provided date formatted using the generalized
+   * time syntax.
    *
    * @param date
    *          The date to be formated.
-   * @return The string containing provided date formatted using the
-   *         generalized time syntax.
+   * @return The string containing provided date formatted using the generalized
+   *         time syntax.
    * @throws NullPointerException
    *           If {@code date} was {@code null}.
    */
-  public static String formatAsGeneralizedTime(Date date)
+  public static String formatAsGeneralizedTime(final Date date)
+      throws NullPointerException
   {
     return formatAsGeneralizedTime(date.getTime());
   }
@@ -830,17 +1241,18 @@
 
 
   /**
-   * Returns a string containing provided date formatted using the
-   * generalized time syntax.
+   * Returns a string containing provided date formatted using the generalized
+   * time syntax.
    *
    * @param date
    *          The date to be formated.
-   * @return The string containing provided date formatted using the
-   *         generalized time syntax.
+   * @return The string containing provided date formatted using the generalized
+   *         time syntax.
    * @throws IllegalArgumentException
    *           If {@code date} was invalid.
    */
-  public static String formatAsGeneralizedTime(long date)
+  public static String formatAsGeneralizedTime(final long date)
+      throws IllegalArgumentException
   {
     // Generalized time has the format yyyyMMddHHmmss.SSS'Z'
 
@@ -849,8 +1261,7 @@
 
     final StringBuilder sb = new StringBuilder(19);
 
-    final GregorianCalendar calendar = new GregorianCalendar(
-        TIME_ZONE_UTC_OBJ);
+    final GregorianCalendar calendar = new GregorianCalendar(TIME_ZONE_UTC_OBJ);
     calendar.setLenient(false);
     calendar.setTimeInMillis(date);
 
@@ -860,8 +1271,7 @@
     {
       final IllegalArgumentException e = new IllegalArgumentException(
           "Year cannot be < 0:" + n);
-      StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax", "format",
-          e);
+      StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax", "format", e);
       throw e;
     }
     else if (n < 10)
@@ -940,16 +1350,16 @@
 
 
   /**
-   * Construct a byte array containing the UTF-8 encoding of the
-   * provided string. This is significantly faster than calling
+   * Construct a byte array containing the UTF-8 encoding of the provided
+   * string. This is significantly faster than calling
    * {@link String#getBytes(String)} for ASCII strings.
    *
    * @param s
    *          The string to convert to a UTF-8 byte array.
-   * @return Returns a byte array containing the UTF-8 encoding of the
-   *         provided string.
+   * @return Returns a byte array containing the UTF-8 encoding of the provided
+   *         string.
    */
-  public static byte[] getBytes(String s)
+  public static byte[] getBytes(final String s)
   {
     if (s == null)
     {
@@ -984,20 +1394,17 @@
 
 
   /**
-   * Retrieves the best human-readable message for the provided
-   * exception. For exceptions defined in the OpenDS project, it will
-   * attempt to use the message (combining it with the message ID if
-   * available). For some exceptions that use encapsulation (e.g.,
-   * InvocationTargetException), it will be unwrapped and the cause will
-   * be treated. For all others, the
+   * Retrieves the best human-readable message for the provided exception. For
+   * exceptions defined in the OpenDS project, it will attempt to use the
+   * message (combining it with the message ID if available). For some
+   * exceptions that use encapsulation (e.g., InvocationTargetException), it
+   * will be unwrapped and the cause will be treated. For all others, the
    *
    * @param t
-   *          The {@code Throwable} object for which to retrieve the
-   *          message.
-   * @return The human-readable message generated for the provided
-   *         exception.
+   *          The {@code Throwable} object for which to retrieve the message.
+   * @return The human-readable message generated for the provided exception.
    */
-  public static LocalizableMessage getExceptionMessage(Throwable t)
+  public static LocalizableMessage getExceptionMessage(final Throwable t)
   {
     if (t instanceof LocalizableException)
     {
@@ -1016,8 +1423,7 @@
       message.append(")");
       return message.toMessage();
     }
-    else if (t instanceof InvocationTargetException
-        && t.getCause() != null)
+    else if (t instanceof InvocationTargetException && t.getCause() != null)
     {
       return getExceptionMessage(t.getCause());
     }
@@ -1074,13 +1480,13 @@
    *
    * @param hexString
    *          The hexadecimal string to convert to a byte array.
-   * @return The byte array containing the binary representation of the
-   *         provided hex string.
+   * @return The byte array containing the binary representation of the provided
+   *         hex string.
    * @throws java.text.ParseException
-   *           If the provided string contains invalid hexadecimal
-   *           digits or does not contain an even number of digits.
+   *           If the provided string contains invalid hexadecimal digits or
+   *           does not contain an even number of digits.
    */
-  public static byte[] hexStringToByteArray(String hexString)
+  public static byte[] hexStringToByteArray(final String hexString)
       throws ParseException
   {
     int length;
@@ -1089,7 +1495,7 @@
       return new byte[0];
     }
 
-    if (length % 2 == 1)
+    if (length % 2 != 0)
     {
       final LocalizableMessage message = ERR_HEX_DECODE_INVALID_LENGTH
           .get(hexString);
@@ -1116,13 +1522,14 @@
    *          The first hexadecimal character.
    * @param c2
    *          The second hexadecimal character.
-   * @return The byte containing the binary representation of the
-   *         provided hex characters.
+   * @return The byte containing the binary representation of the provided hex
+   *         characters.
    * @throws ParseException
-   *           If the provided string contains invalid hexadecimal
-   *           digits or does not contain an even number of digits.
+   *           If the provided string contains invalid hexadecimal digits or
+   *           does not contain an even number of digits.
    */
-  public static byte hexToByte(char c1, char c2) throws ParseException
+  public static byte hexToByte(final char c1, final char c2)
+      throws ParseException
   {
     byte b;
     switch (c1)
@@ -1182,8 +1589,8 @@
       b = (byte) 0xF0;
       break;
     default:
-      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER
-          .get(new String(new char[] { c1, c2 }), c1);
+      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER.get(
+          new String(new char[] { c1, c2 }), c1);
       throw new ParseException(message.toString(), 0);
     }
 
@@ -1244,8 +1651,8 @@
       b |= 0x0F;
       break;
     default:
-      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER
-          .get(new String(new char[] { c1, c2 }), c1);
+      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER.get(
+          new String(new char[] { c1, c2 }), c1);
       throw new ParseException(message.toString(), 0);
     }
 
@@ -1255,16 +1662,15 @@
 
 
   /**
-   * Indicates whether the provided character is an ASCII alphabetic
-   * character.
+   * Indicates whether the provided character is an ASCII alphabetic character.
    *
    * @param c
    *          The character for which to make the determination.
    * @return <CODE>true</CODE> if the provided value is an uppercase or
-   *         lowercase ASCII alphabetic character, or <CODE>false</CODE>
-   *         if it is not.
+   *         lowercase ASCII alphabetic character, or <CODE>false</CODE> if it
+   *         is not.
    */
-  public static boolean isAlpha(char c)
+  public static boolean isAlpha(final char c)
   {
     final ASCIICharProp cp = ASCIICharProp.valueOf(c);
     return cp != null ? cp.isLetter() : false;
@@ -1277,10 +1683,10 @@
    *
    * @param c
    *          The character for which to make the determination.
-   * @return <CODE>true</CODE> if the provided character represents a
-   *         numeric digit, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided character represents a numeric
+   *         digit, or <CODE>false</CODE> if not.
    */
-  public static boolean isDigit(char c)
+  public static boolean isDigit(final char c)
   {
     final ASCIICharProp cp = ASCIICharProp.valueOf(c);
     return cp != null ? cp.isDigit() : false;
@@ -1296,7 +1702,7 @@
    * @return <CODE>true</CODE> if the provided character represents a
    *         hexadecimal digit, or <CODE>false</CODE> if not.
    */
-  public static boolean isHexDigit(char c)
+  public static boolean isHexDigit(final char c)
   {
     final ASCIICharProp cp = ASCIICharProp.valueOf(c);
     return cp != null ? cp.isHexDigit() : false;
@@ -1305,16 +1711,15 @@
 
 
   /**
-   * Returns a string representation of the contents of the provided
-   * byte sequence using hexadecimal characters and a space between each
-   * byte.
+   * Returns a string representation of the contents of the provided byte
+   * sequence using hexadecimal characters and a space between each byte.
    *
    * @param bytes
    *          The byte sequence.
-   * @return A string representation of the contents of the provided
-   *         byte sequence using hexadecimal characters.
+   * @return A string representation of the contents of the provided byte
+   *         sequence using hexadecimal characters.
    */
-  public static String toHex(ByteSequence bytes)
+  public static String toHex(final ByteSequence bytes)
   {
     return toHex(bytes, new StringBuilder((bytes.length() - 1) * 3 + 2))
         .toString();
@@ -1323,19 +1728,19 @@
 
 
   /**
-   * Appends the string representation of the contents of the provided
-   * byte sequence to a string builder using hexadecimal characters and
-   * a space between each byte.
+   * Appends the string representation of the contents of the provided byte
+   * sequence to a string builder using hexadecimal characters and a space
+   * between each byte.
    *
    * @param bytes
    *          The byte sequence.
    * @param builder
-   *          The string builder to which the hexadecimal representation
-   *          of {@code bytes} should be appended.
+   *          The string builder to which the hexadecimal representation of
+   *          {@code bytes} should be appended.
    * @return The string builder.
    */
-  public static StringBuilder toHex(ByteSequence bytes,
-      StringBuilder builder)
+  public static StringBuilder toHex(final ByteSequence bytes,
+      final StringBuilder builder)
   {
     final int length = bytes.length();
     builder.ensureCapacity(builder.length() + (length - 1) * 3 + 2);
@@ -1351,24 +1756,23 @@
 
 
   /**
-   * Appends a string representation of the data in the provided byte
-   * sequence to the given string builder using the specified indent.
+   * Appends a string representation of the data in the provided byte sequence
+   * to the given string builder using the specified indent.
    * <p>
-   * The data will be formatted with sixteen hex bytes in a row followed
-   * by the ASCII representation, then wrapping to a new line as
-   * necessary. The state of the byte buffer is not changed.
+   * The data will be formatted with sixteen hex bytes in a row followed by the
+   * ASCII representation, then wrapping to a new line as necessary. The state
+   * of the byte buffer is not changed.
    *
    * @param bytes
    *          The byte sequence.
    * @param builder
-   *          The string builder to which the information is to be
-   *          appended.
+   *          The string builder to which the information is to be appended.
    * @param indent
    *          The number of spaces to indent the output.
    * @return The string builder.
    */
-  public static StringBuilder toHexPlusAscii(ByteSequence bytes,
-      StringBuilder builder, int indent)
+  public static StringBuilder toHexPlusAscii(final ByteSequence bytes,
+      final StringBuilder builder, final int indent)
   {
     final StringBuilder indentBuf = new StringBuilder(indent);
     for (int i = 0; i < indent; i++)
@@ -1455,23 +1859,23 @@
 
 
   /**
-   * Appends a lowercase string representation of the contents of the
-   * given byte array to the provided buffer. This implementation
-   * presumes that the provided string will contain only ASCII
-   * characters and is optimized for that case. However, if a non-ASCII
-   * character is encountered it will fall back on a more expensive
-   * algorithm that will work properly for non-ASCII characters.
+   * Appends a lowercase string representation of the contents of the given byte
+   * array to the provided buffer. This implementation presumes that the
+   * provided string will contain only ASCII characters and is optimized for
+   * that case. However, if a non-ASCII character is encountered it will fall
+   * back on a more expensive algorithm that will work properly for non-ASCII
+   * characters.
    *
    * @param b
    *          The byte array for which to obtain the lowercase string
    *          representation.
    * @param builder
-   *          The buffer to which the lowercase form of the string
-   *          should be appended.
+   *          The buffer to which the lowercase form of the string should be
+   *          appended.
    * @return The updated {@code StringBuilder}.
    */
-  public static StringBuilder toLowerCase(ByteSequence b,
-      StringBuilder builder)
+  public static StringBuilder toLowerCase(final ByteSequence b,
+      final StringBuilder builder)
   {
     Validator.ensureNotNull(b, builder);
 
@@ -1504,18 +1908,16 @@
 
   /**
    * Retrieves a lower-case representation of the given string. This
-   * implementation presumes that the provided string will contain only
-   * ASCII characters and is optimized for that case. However, if a
-   * non-ASCII character is encountered it will fall back on a more
-   * expensive algorithm that will work properly for non-ASCII
-   * characters.
+   * implementation presumes that the provided string will contain only ASCII
+   * characters and is optimized for that case. However, if a non-ASCII
+   * character is encountered it will fall back on a more expensive algorithm
+   * that will work properly for non-ASCII characters.
    *
    * @param s
-   *          The string for which to obtain the lower-case
-   *          representation.
+   *          The string for which to obtain the lower-case representation.
    * @return The lower-case representation of the given string.
    */
-  public static String toLowerCase(String s)
+  public static String toLowerCase(final String s)
   {
     Validator.ensureNotNull(s);
 
@@ -1532,7 +1934,10 @@
     while (i < length)
     {
       cp = ASCIICharProp.valueOf(s.charAt(i));
-      if (cp == null || cp.isUpperCase()) break;
+      if (cp == null || cp.isUpperCase())
+      {
+        break;
+      }
       i++;
     }
 
@@ -1554,7 +1959,10 @@
       while (i < length)
       {
         cp = ASCIICharProp.valueOf(s.charAt(i));
-        if (cp == null) break;
+        if (cp == null)
+        {
+          break;
+        }
         builder.append(cp.toLowerCase());
         i++;
       }
@@ -1571,23 +1979,21 @@
 
 
   /**
-   * Appends a lower-case representation of the given string to the
-   * provided buffer. This implementation presumes that the provided
-   * string will contain only ASCII characters and is optimized for that
-   * case. However, if a non-ASCII character is encountered it will fall
-   * back on a more expensive algorithm that will work properly for
-   * non-ASCII characters.
+   * Appends a lower-case representation of the given string to the provided
+   * buffer. This implementation presumes that the provided string will contain
+   * only ASCII characters and is optimized for that case. However, if a
+   * non-ASCII character is encountered it will fall back on a more expensive
+   * algorithm that will work properly for non-ASCII characters.
    *
    * @param s
-   *          The string for which to obtain the lower-case
-   *          representation.
+   *          The string for which to obtain the lower-case representation.
    * @param builder
-   *          The {@code StringBuilder} to which the lower-case form of
-   *          the string should be appended.
+   *          The {@code StringBuilder} to which the lower-case form of the
+   *          string should be appended.
    * @return The updated {@code StringBuilder}.
    */
-  public static StringBuilder toLowerCase(String s,
-      StringBuilder builder)
+  public static StringBuilder toLowerCase(final String s,
+      final StringBuilder builder)
   {
     Validator.ensureNotNull(s, builder);
 
@@ -1618,16 +2024,15 @@
 
 
   /**
-   * Attempts to uncompress the data in the provided source array into
-   * the given destination array. If the uncompressed data will fit into
-   * the given destination array, then this method will return the
-   * number of bytes of uncompressed data written into the destination
-   * buffer. Otherwise, it will return a negative value to indicate that
-   * the destination buffer was not large enough. The absolute value of
-   * that negative return value will indicate the buffer size required
-   * to fully decompress the data. Note that if a negative value is
-   * returned, then the data in the destination array should be
-   * considered invalid.
+   * Attempts to uncompress the data in the provided source array into the given
+   * destination array. If the uncompressed data will fit into the given
+   * destination array, then this method will return the number of bytes of
+   * uncompressed data written into the destination buffer. Otherwise, it will
+   * return a negative value to indicate that the destination buffer was not
+   * large enough. The absolute value of that negative return value will
+   * indicate the buffer size required to fully decompress the data. Note that
+   * if a negative value is returned, then the data in the destination array
+   * should be considered invalid.
    *
    * @param src
    *          The array containing the raw data to compress.
@@ -1636,31 +2041,28 @@
    * @param srcLen
    *          The maximum number of source data bytes to compress.
    * @param dst
-   *          The array into which the compressed data should be
-   *          written.
+   *          The array into which the compressed data should be written.
    * @param dstOff
    *          The start offset of the compressed data.
    * @param dstLen
    *          The maximum number of bytes of compressed data.
-   * @return A positive value containing the number of bytes of
-   *         uncompressed data written into the destination buffer, or a
-   *         negative value whose absolute value is the size of the
-   *         destination buffer required to fully decompress the
-   *         provided data.
+   * @return A positive value containing the number of bytes of uncompressed
+   *         data written into the destination buffer, or a negative value whose
+   *         absolute value is the size of the destination buffer required to
+   *         fully decompress the provided data.
    * @throws java.util.zip.DataFormatException
-   *           If a problem occurs while attempting to uncompress the
-   *           data.
+   *           If a problem occurs while attempting to uncompress the data.
    */
-  public static int uncompress(byte[] src, int srcOff, int srcLen,
-      byte[] dst, int dstOff, int dstLen) throws DataFormatException
+  public static int uncompress(final byte[] src, final int srcOff,
+      final int srcLen, final byte[] dst, final int dstOff, final int dstLen)
+      throws DataFormatException
   {
     final Inflater inflater = new Inflater();
     try
     {
       inflater.setInput(src, srcOff, srcLen);
 
-      final int decompressedLength = inflater.inflate(dst, dstOff,
-          dstLen);
+      final int decompressedLength = inflater.inflate(dst, dstOff, dstLen);
       if (inflater.finished())
       {
         return decompressedLength;
@@ -1686,31 +2088,29 @@
 
 
   /**
-   * Attempts to uncompress the data in the provided byte sequence into
-   * the provided byte string builder. Note that if uncompression was
-   * not successful, then the data in the destination buffer should be
-   * considered invalid.
+   * Attempts to uncompress the data in the provided byte sequence into the
+   * provided byte string builder. Note that if uncompression was not
+   * successful, then the data in the destination buffer should be considered
+   * invalid.
    *
    * @param input
    *          The source data to be uncompressed.
    * @param output
-   *          The destination buffer to which the uncompressed data will
-   *          be appended.
+   *          The destination buffer to which the uncompressed data will be
+   *          appended.
    * @param uncompressedSize
    *          The uncompressed size of the data if known or 0 otherwise.
    * @return <code>true</code> if decompression was successful or
    *         <code>false</code> otherwise.
    * @throws java.util.zip.DataFormatException
-   *           If a problem occurs while attempting to uncompress the
-   *           data.
+   *           If a problem occurs while attempting to uncompress the data.
    */
-  public static boolean uncompress(ByteSequence input,
-      ByteStringBuilder output, int uncompressedSize)
+  public static boolean uncompress(final ByteSequence input,
+      final ByteStringBuilder output, final int uncompressedSize)
       throws DataFormatException
   {
-    byte[] inputBytes = input.toByteArray();
-    byte[] outputBytes = new byte[uncompressedSize > 0 ? uncompressedSize
-        : 0];
+    final byte[] inputBytes = input.toByteArray();
+    byte[] outputBytes = new byte[uncompressedSize > 0 ? uncompressedSize : 0];
 
     int decompressResult = uncompress(inputBytes, 0, inputBytes.length,
         outputBytes, 0, outputBytes.length);
@@ -1740,13 +2140,11 @@
    * Retrieves the printable ASCII representation of the provided byte.
    *
    * @param b
-   *          The byte for which to retrieve the printable ASCII
-   *          representation.
-   * @return The printable ASCII representation of the provided byte, or
-   *         a space if the provided byte does not have printable ASCII
-   *         representation.
+   *          The byte for which to retrieve the printable ASCII representation.
+   * @return The printable ASCII representation of the provided byte, or a space
+   *         if the provided byte does not have printable ASCII representation.
    */
-  private static char byteToASCII(byte b)
+  private static char byteToASCII(final byte b)
   {
     if (b >= 32 && b <= 126)
     {
@@ -1758,164 +2156,6 @@
 
 
 
-  private static char evaluateEscapedChar(SubstringReader reader,
-      char[] escapeChars) throws DecodeException
-  {
-    final char c1 = reader.read();
-    byte b;
-    switch (c1)
-    {
-    case '0':
-      b = 0x00;
-      break;
-    case '1':
-      b = 0x10;
-      break;
-    case '2':
-      b = 0x20;
-      break;
-    case '3':
-      b = 0x30;
-      break;
-    case '4':
-      b = 0x40;
-      break;
-    case '5':
-      b = 0x50;
-      break;
-    case '6':
-      b = 0x60;
-      break;
-    case '7':
-      b = 0x70;
-      break;
-    case '8':
-      b = (byte) 0x80;
-      break;
-    case '9':
-      b = (byte) 0x90;
-      break;
-    case 'A':
-    case 'a':
-      b = (byte) 0xA0;
-      break;
-    case 'B':
-    case 'b':
-      b = (byte) 0xB0;
-      break;
-    case 'C':
-    case 'c':
-      b = (byte) 0xC0;
-      break;
-    case 'D':
-    case 'd':
-      b = (byte) 0xD0;
-      break;
-    case 'E':
-    case 'e':
-      b = (byte) 0xE0;
-      break;
-    case 'F':
-    case 'f':
-      b = (byte) 0xF0;
-      break;
-    default:
-      if (c1 == 0x5C)
-      {
-        return c1;
-      }
-      if (escapeChars != null)
-      {
-        for (final char escapeChar : escapeChars)
-        {
-          if (c1 == escapeChar)
-          {
-            return c1;
-          }
-        }
-      }
-      final LocalizableMessage message = ERR_INVALID_ESCAPE_CHAR.get(
-          reader.getString(), c1);
-      throw DecodeException.error(message);
-    }
-
-    // The two positions must be the hex characters that
-    // comprise the escaped value.
-    if (reader.remaining() == 0)
-    {
-      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_LENGTH
-          .get(reader.getString());
-
-      throw DecodeException.error(message);
-    }
-
-    final char c2 = reader.read();
-    switch (c2)
-    {
-    case '0':
-      // No action required.
-      break;
-    case '1':
-      b |= 0x01;
-      break;
-    case '2':
-      b |= 0x02;
-      break;
-    case '3':
-      b |= 0x03;
-      break;
-    case '4':
-      b |= 0x04;
-      break;
-    case '5':
-      b |= 0x05;
-      break;
-    case '6':
-      b |= 0x06;
-      break;
-    case '7':
-      b |= 0x07;
-      break;
-    case '8':
-      b |= 0x08;
-      break;
-    case '9':
-      b |= 0x09;
-      break;
-    case 'A':
-    case 'a':
-      b |= 0x0A;
-      break;
-    case 'B':
-    case 'b':
-      b |= 0x0B;
-      break;
-    case 'C':
-    case 'c':
-      b |= 0x0C;
-      break;
-    case 'D':
-    case 'd':
-      b |= 0x0D;
-      break;
-    case 'E':
-    case 'e':
-      b |= 0x0E;
-      break;
-    case 'F':
-    case 'f':
-      b |= 0x0F;
-      break;
-    default:
-      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER
-          .get(new String(new char[] { c1, c2 }), c1);
-      throw DecodeException.error(message);
-    }
-    return (char) b;
-  }
-
-
-
   // Prevent instantiation.
   private StaticUtils()
   {
diff --git a/sdk/src/com/sun/opends/sdk/util/StringPrepProfile.java b/sdk/src/com/sun/opends/sdk/util/StringPrepProfile.java
index f3dc098..c7fa64e 100644
--- a/sdk/src/com/sun/opends/sdk/util/StringPrepProfile.java
+++ b/sdk/src/com/sun/opends/sdk/util/StringPrepProfile.java
@@ -28,7 +28,7 @@
 
 
 
-import static com.sun.opends.sdk.util.Validator.*;
+import static com.sun.opends.sdk.util.Validator.ensureNotNull;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -38,487 +38,374 @@
 
 
 /**
- * This class defines the "stringprep" profile as defined in RFC 4518.
- * It must be used by all the matching rules that support unicode
- * characters. For a complete list of such rules, refer to Section 4.2,
- * RFC 4517.
+ * This class defines the "stringprep" profile as defined in RFC 4518. It must
+ * be used by all the matching rules that support unicode characters. For a
+ * complete list of such rules, refer to Section 4.2, RFC 4517.
  */
 public final class StringPrepProfile
 {
   /**
    * A Table defining the mapped code-points as per RFC 3454.
    */
-  private static class MappingTable
+  private static final class MappingTable
   {
     // Set of chars which are deleted from the incoming value.
-    private final static HashSet<Character> map2null =
-        new HashSet<Character>();
+    private final static HashSet<Character> MAP_2_NULL = new HashSet<Character>();
+
     // Set of chars which are replaced by a SPACE when found.
-    private final static HashSet<Character> map2space =
-        new HashSet<Character>();
+    private final static HashSet<Character> MAP_2_SPACE = new HashSet<Character>();
+
     // Table for case-folding. Map of Character and String containing
-    // uppercase
-    // and lowercase value as the key-value pair.
-    private final static HashMap<Character, String> caseMappingTable =
-        new HashMap<Character, String>();
+    // uppercase and lowercase value as the key-value pair.
+    private final static HashMap<Character, String> CASE_MAP_TABLE =
+      new HashMap<Character, String>();
 
     static
     {
       // Appendix B.1 RFC 3454.
-      final char[][] mapped2null =
-          new char[][] { { '\u0000', '\u0008' },
-              { '\u000E', '\u001F' }, { '\u007F', '\u0084' },
-              { '\u0086', '\u009F' }, { '\u00AD' }, { '\u034F' },
-              { '\u06DD' }, { '\u070F' }, { '\u1806' },
-              { '\u180B', '\u180E' }, { '\u200C', '\u200F' },
-              { '\u202A', '\u202E' }, { '\u2060', '\u2063' },
-              { '\u206A', '\u206F' }, { '\uFE00', '\uFE0F' },
-              { '\uFEFF' }, { '\uFFF9', '\uFFFC' } };
+      final char[][] mapped2null = new char[][] { { '\u0000', '\u0008' },
+          { '\u000E', '\u001F' }, { '\u007F', '\u0084' },
+          { '\u0086', '\u009F' }, { '\u00AD' }, { '\u034F' }, { '\u06DD' },
+          { '\u070F' }, { '\u1806' }, { '\u180B', '\u180E' },
+          { '\u200C', '\u200F' }, { '\u202A', '\u202E' },
+          { '\u2060', '\u2063' }, { '\u206A', '\u206F' },
+          { '\uFE00', '\uFE0F' }, { '\uFEFF' }, { '\uFFF9', '\uFFFC' } };
 
       for (final char[] element : mapped2null)
       {
         if (element.length == 1)
         {
-          map2null.add(element[0]);
+          MAP_2_NULL.add(element[0]);
         }
         else
         {
           // Contains a range of values.
           for (char c = element[0]; c <= element[1]; c++)
           {
-            map2null.add(c);
+            MAP_2_NULL.add(c);
           }
         }
       }
 
-      final char[] mapped2Space =
-          new char[] { '\u0009', 0xA, '\u000B', '\u000C', 0xD,
-              '\u0085', '\u00A0', '\u1680', '\u2000', '\u2001',
-              '\u2002', '\u2003', '\u2004', '\u2005', '\u2006',
-              '\u2007', '\u2008', '\u2009', '\u200A', '\u2028',
-              '\u2029', '\u202F', '\u205F', '\u3000' };
+      final char[] mapped2Space = new char[] { '\u0009', 0xA, '\u000B',
+          '\u000C', 0xD, '\u0085', '\u00A0', '\u1680', '\u2000', '\u2001',
+          '\u2002', '\u2003', '\u2004', '\u2005', '\u2006', '\u2007', '\u2008',
+          '\u2009', '\u200A', '\u2028', '\u2029', '\u202F', '\u205F', '\u3000' };
 
       for (final char c : mapped2Space)
       {
-        map2space.add(c);
+        MAP_2_SPACE.add(c);
       }
 
       // Appendix B.2 RFC 3454.
       // Build an uppercase array and a lowercase array and create a map
       // of both
       // values.
-      final char[] upperCaseArr =
-          new char[] { '\u0041', '\u0042', '\u0043', '\u0044',
-              '\u0045', '\u0046', '\u0047', '\u0048', '\u0049',
-              '\u004A', '\u004B', '\u004C', '\u004D', '\u004E',
-              '\u004F', '\u0050', '\u0051', '\u0052', '\u0053',
-              '\u0054', '\u0055', '\u0056', '\u0057', '\u0058',
-              '\u0059', '\u005A', '\u00B5', '\u00C0', '\u00C1',
-              '\u00C2', '\u00C3', '\u00C4', '\u00C5', '\u00C6',
-              '\u00C7', '\u00C8', '\u00C9', '\u00CA', '\u00CB',
-              '\u00CC', '\u00CD', '\u00CE', '\u00CF', '\u00D0',
-              '\u00D1', '\u00D2', '\u00D3', '\u00D4', '\u00D5',
-              '\u00D6', '\u00D8', '\u00D9', '\u00DA', '\u00DB',
-              '\u00DC', '\u00DD', '\u00DE', '\u00DF', '\u0100',
-              '\u0102', '\u0104', '\u0106', '\u0108', '\u010A',
-              '\u010C', '\u010E', '\u0110', '\u0112', '\u0114',
-              '\u0116', '\u0118', '\u011A', '\u011C', '\u011E',
-              '\u0120', '\u0122', '\u0124', '\u0126', '\u0128',
-              '\u012A', '\u012C', '\u012E', '\u0130', '\u0132',
-              '\u0134', '\u0136', '\u0139', '\u013B', '\u013D',
-              '\u013F', '\u0141', '\u0143', '\u0145', '\u0147',
-              '\u0149', '\u014A', '\u014C', '\u014E', '\u0150',
-              '\u0152', '\u0154', '\u0156', '\u0158', '\u015A',
-              '\u015C', '\u015E', '\u0160', '\u0162', '\u0164',
-              '\u0166', '\u0168', '\u016A', '\u016C', '\u016E',
-              '\u0170', '\u0172', '\u0174', '\u0176', '\u0178',
-              '\u0179', '\u017B', '\u017D', '\u017F', '\u0181',
-              '\u0182', '\u0184', '\u0186', '\u0187', '\u0189',
-              '\u018A', '\u018B', '\u018E', '\u018F', '\u0190',
-              '\u0191', '\u0193', '\u0194', '\u0196', '\u0197',
-              '\u0198', '\u019C', '\u019D', '\u019F', '\u01A0',
-              '\u01A2', '\u01A4', '\u01A6', '\u01A7', '\u01A9',
-              '\u01AC', '\u01AE', '\u01AF', '\u01B1', '\u01B2',
-              '\u01B3', '\u01B5', '\u01B7', '\u01B8', '\u01BC',
-              '\u01C4', '\u01C5', '\u01C7', '\u01C8', '\u01CA',
-              '\u01CB', '\u01CD', '\u01CF', '\u01D1', '\u01D3',
-              '\u01D5', '\u01D7', '\u01D9', '\u01DB', '\u01DE',
-              '\u01E0', '\u01E2', '\u01E4', '\u01E6', '\u01E8',
-              '\u01EA', '\u01EC', '\u01EE', '\u01F0', '\u01F1',
-              '\u01F2', '\u01F4', '\u01F6', '\u01F7', '\u01F8',
-              '\u01FA', '\u01FC', '\u01FE', '\u0200', '\u0202',
-              '\u0204', '\u0206', '\u0208', '\u020A', '\u020C',
-              '\u020E', '\u0210', '\u0212', '\u0214', '\u0216',
-              '\u0218', '\u021A', '\u021C', '\u021E', '\u0220',
-              '\u0222', '\u0224', '\u0226', '\u0228', '\u022A',
-              '\u022C', '\u022E', '\u0230', '\u0232', '\u0345',
-              '\u037A', '\u0386', '\u0388', '\u0389', '\u038A',
-              '\u038C', '\u038E', '\u038F', '\u0390', '\u0391',
-              '\u0392', '\u0393', '\u0394', '\u0395', '\u0396',
-              '\u0397', '\u0398', '\u0399', '\u039A', '\u039B',
-              '\u039C', '\u039D', '\u039E', '\u039F', '\u03A0',
-              '\u03A1', '\u03A3', '\u03A4', '\u03A5', '\u03A6',
-              '\u03A7', '\u03A8', '\u03A9', '\u03AA', '\u03AB',
-              '\u03B0', '\u03C2', '\u03D0', '\u03D1', '\u03D2',
-              '\u03D3', '\u03D4', '\u03D5', '\u03D6', '\u03D8',
-              '\u03DA', '\u03DC', '\u03DE', '\u03E0', '\u03E2',
-              '\u03E4', '\u03E6', '\u03E8', '\u03EA', '\u03EC',
-              '\u03EE', '\u03F0', '\u03F1', '\u03F2', '\u03F4',
-              '\u03F5', '\u0400', '\u0401', '\u0402', '\u0403',
-              '\u0404', '\u0405', '\u0406', '\u0407', '\u0408',
-              '\u0409', '\u040A', '\u040B', '\u040C', '\u040D',
-              '\u040E', '\u040F', '\u0410', '\u0411', '\u0412',
-              '\u0413', '\u0414', '\u0415', '\u0416', '\u0417',
-              '\u0418', '\u0419', '\u041A', '\u041B', '\u041C',
-              '\u041D', '\u041E', '\u041F', '\u0420', '\u0421',
-              '\u0422', '\u0423', '\u0424', '\u0425', '\u0426',
-              '\u0427', '\u0428', '\u0429', '\u042A', '\u042B',
-              '\u042C', '\u042D', '\u042E', '\u042F', '\u0460',
-              '\u0462', '\u0464', '\u0466', '\u0468', '\u046A',
-              '\u046C', '\u046E', '\u0470', '\u0472', '\u0474',
-              '\u0476', '\u0478', '\u047A', '\u047C', '\u047E',
-              '\u0480', '\u048A', '\u048C', '\u048E', '\u0490',
-              '\u0492', '\u0494', '\u0496', '\u0498', '\u049A',
-              '\u049C', '\u049E', '\u04A0', '\u04A2', '\u04A4',
-              '\u04A6', '\u04A8', '\u04AA', '\u04AC', '\u04AE',
-              '\u04B0', '\u04B2', '\u04B4', '\u04B6', '\u04B8',
-              '\u04BA', '\u04BC', '\u04BE', '\u04C1', '\u04C3',
-              '\u04C5', '\u04C7', '\u04C9', '\u04CB', '\u04CD',
-              '\u04D0', '\u04D2', '\u04D4', '\u04D6', '\u04D8',
-              '\u04DA', '\u04DC', '\u04DE', '\u04E0', '\u04E2',
-              '\u04E4', '\u04E6', '\u04E8', '\u04EA', '\u04EC',
-              '\u04EE', '\u04F0', '\u04F2', '\u04F4', '\u04F8',
-              '\u0500', '\u0502', '\u0504', '\u0506', '\u0508',
-              '\u050A', '\u050C', '\u050E', '\u0531', '\u0532',
-              '\u0533', '\u0534', '\u0535', '\u0536', '\u0537',
-              '\u0538', '\u0539', '\u053A', '\u053B', '\u053C',
-              '\u053D', '\u053E', '\u053F', '\u0540', '\u0541',
-              '\u0542', '\u0543', '\u0544', '\u0545', '\u0546',
-              '\u0547', '\u0548', '\u0549', '\u054A', '\u054B',
-              '\u054C', '\u054D', '\u054E', '\u054F', '\u0550',
-              '\u0551', '\u0552', '\u0553', '\u0554', '\u0555',
-              '\u0556', '\u0587', '\u1E00', '\u1E02', '\u1E04',
-              '\u1E06', '\u1E08', '\u1E0A', '\u1E0C', '\u1E0E',
-              '\u1E10', '\u1E12', '\u1E14', '\u1E16', '\u1E18',
-              '\u1E1A', '\u1E1C', '\u1E1E', '\u1E20', '\u1E22',
-              '\u1E24', '\u1E26', '\u1E28', '\u1E2A', '\u1E2C',
-              '\u1E2E', '\u1E30', '\u1E32', '\u1E34', '\u1E36',
-              '\u1E38', '\u1E3A', '\u1E3C', '\u1E3E', '\u1E40',
-              '\u1E42', '\u1E44', '\u1E46', '\u1E48', '\u1E4A',
-              '\u1E4C', '\u1E4E', '\u1E50', '\u1E52', '\u1E54',
-              '\u1E56', '\u1E58', '\u1E5A', '\u1E5C', '\u1E5E',
-              '\u1E60', '\u1E62', '\u1E64', '\u1E66', '\u1E68',
-              '\u1E6A', '\u1E6C', '\u1E6E', '\u1E70', '\u1E72',
-              '\u1E74', '\u1E76', '\u1E78', '\u1E7A', '\u1E7C',
-              '\u1E7E', '\u1E80', '\u1E82', '\u1E84', '\u1E86',
-              '\u1E88', '\u1E8A', '\u1E8C', '\u1E8E', '\u1E90',
-              '\u1E92', '\u1E94', '\u1E96', '\u1E97', '\u1E98',
-              '\u1E99', '\u1E9A', '\u1E9B', '\u1EA0', '\u1EA2',
-              '\u1EA4', '\u1EA6', '\u1EA8', '\u1EAA', '\u1EAC',
-              '\u1EAE', '\u1EB0', '\u1EB2', '\u1EB4', '\u1EB6',
-              '\u1EB8', '\u1EBA', '\u1EBC', '\u1EBE', '\u1EC0',
-              '\u1EC2', '\u1EC4', '\u1EC6', '\u1EC8', '\u1ECA',
-              '\u1ECC', '\u1ECE', '\u1ED0', '\u1ED2', '\u1ED4',
-              '\u1ED6', '\u1ED8', '\u1EDA', '\u1EDC', '\u1EDE',
-              '\u1EE0', '\u1EE2', '\u1EE4', '\u1EE6', '\u1EE8',
-              '\u1EEA', '\u1EEC', '\u1EEE', '\u1EF0', '\u1EF2',
-              '\u1EF4', '\u1EF6', '\u1EF8', '\u1F08', '\u1F09',
-              '\u1F0A', '\u1F0B', '\u1F0C', '\u1F0D', '\u1F0E',
-              '\u1F0F', '\u1F18', '\u1F19', '\u1F1A', '\u1F1B',
-              '\u1F1C', '\u1F1D', '\u1F28', '\u1F29', '\u1F2A',
-              '\u1F2B', '\u1F2C', '\u1F2D', '\u1F2E', '\u1F2F',
-              '\u1F38', '\u1F39', '\u1F3A', '\u1F3B', '\u1F3C',
-              '\u1F3D', '\u1F3E', '\u1F3F', '\u1F48', '\u1F49',
-              '\u1F4A', '\u1F4B', '\u1F4C', '\u1F4D', '\u1F50',
-              '\u1F52', '\u1F54', '\u1F56', '\u1F59', '\u1F5B',
-              '\u1F5D', '\u1F5F', '\u1F68', '\u1F69', '\u1F6A',
-              '\u1F6B', '\u1F6C', '\u1F6D', '\u1F6E', '\u1F6F',
-              '\u1F80', '\u1F81', '\u1F82', '\u1F83', '\u1F84',
-              '\u1F85', '\u1F86', '\u1F87', '\u1F88', '\u1F89',
-              '\u1F8A', '\u1F8B', '\u1F8C', '\u1F8D', '\u1F8E',
-              '\u1F8F', '\u1F90', '\u1F91', '\u1F92', '\u1F93',
-              '\u1F94', '\u1F95', '\u1F96', '\u1F97', '\u1F98',
-              '\u1F99', '\u1F9A', '\u1F9B', '\u1F9C', '\u1F9D',
-              '\u1F9E', '\u1F9F', '\u1FA0', '\u1FA1', '\u1FA2',
-              '\u1FA3', '\u1FA4', '\u1FA5', '\u1FA6', '\u1FA7',
-              '\u1FA8', '\u1FA9', '\u1FAA', '\u1FAB', '\u1FAC',
-              '\u1FAD', '\u1FAE', '\u1FAF', '\u1FB2', '\u1FB3',
-              '\u1FB4', '\u1FB6', '\u1FB7', '\u1FB8', '\u1FB9',
-              '\u1FBA', '\u1FBB', '\u1FBC', '\u1FBE', '\u1FC2',
-              '\u1FC3', '\u1FC4', '\u1FC6', '\u1FC7', '\u1FC8',
-              '\u1FC9', '\u1FCA', '\u1FCB', '\u1FCC', '\u1FD2',
-              '\u1FD3', '\u1FD6', '\u1FD7', '\u1FD8', '\u1FD9',
-              '\u1FDA', '\u1FDB', '\u1FE2', '\u1FE3', '\u1FE4',
-              '\u1FE6', '\u1FE7', '\u1FE8', '\u1FE9', '\u1FEA',
-              '\u1FEB', '\u1FEC', '\u1FF2', '\u1FF3', '\u1FF4',
-              '\u1FF6', '\u1FF7', '\u1FF8', '\u1FF9', '\u1FFA',
-              '\u1FFB', '\u1FFC', '\u20A8', '\u2102', '\u2103',
-              '\u2107', '\u2109', '\u210B', '\u210C', '\u210D',
-              '\u2110', '\u2111', '\u2112', '\u2115', '\u2116',
-              '\u2119', '\u211A', '\u211B', '\u211C', '\u211D',
-              '\u2120', '\u2121', '\u2122', '\u2124', '\u2126',
-              '\u2128', '\u212A', '\u212B', '\u212C', '\u212D',
-              '\u2130', '\u2131', '\u2133', '\u213E', '\u213F',
-              '\u2145', '\u2160', '\u2161', '\u2162', '\u2163',
-              '\u2164', '\u2165', '\u2166', '\u2167', '\u2168',
-              '\u2169', '\u216A', '\u216B', '\u216C', '\u216D',
-              '\u216E', '\u216F', '\u24B6', '\u24B7', '\u24B8',
-              '\u24B9', '\u24BA', '\u24BB', '\u24BC', '\u24BD',
-              '\u24BE', '\u24BF', '\u24C0', '\u24C1', '\u24C2',
-              '\u24C3', '\u24C4', '\u24C5', '\u24C6', '\u24C7',
-              '\u24C8', '\u24C9', '\u24CA', '\u24CB', '\u24CC',
-              '\u24CD', '\u24CE', '\u24CF', '\u3371', '\u3373',
-              '\u3375', '\u3380', '\u3381', '\u3382', '\u3383',
-              '\u3384', '\u3385', '\u3386', '\u3387', '\u338A',
-              '\u338B', '\u338C', '\u3390', '\u3391', '\u3392',
-              '\u3393', '\u3394', '\u33A9', '\u33AA', '\u33AB',
-              '\u33AC', '\u33B4', '\u33B5', '\u33B6', '\u33B7',
-              '\u33B8', '\u33B9', '\u33BA', '\u33BB', '\u33BC',
-              '\u33BD', '\u33BE', '\u33BF', '\u33C0', '\u33C1',
-              '\u33C3', '\u33C6', '\u33C7', '\u33C8', '\u33C9',
-              '\u33CB', '\u33CD', '\u33CE', '\u33D7', '\u33D9',
-              '\u33DA', '\u33DC', '\u33DD', '\uFB00', '\uFB01',
-              '\uFB02', '\uFB03', '\uFB04', '\uFB05', '\uFB06',
-              '\uFB13', '\uFB14', '\uFB15', '\uFB16', '\uFB17',
-              '\uFF21', '\uFF22', '\uFF23', '\uFF24', '\uFF25',
-              '\uFF26', '\uFF27', '\uFF28', '\uFF29', '\uFF2A',
-              '\uFF2B', '\uFF2C', '\uFF2D', '\uFF2E', '\uFF2F',
-              '\uFF30', '\uFF31', '\uFF32', '\uFF33', '\uFF34',
-              '\uFF35', '\uFF36', '\uFF37', '\uFF38', '\uFF39',
-              '\uFF3A' };
-      final String[] lowerCaseFoldedArr =
-          new String[] { "\u0061", "\u0062", "\u0063", "\u0064",
-              "\u0065", "\u0066", "\u0067", "\u0068", "\u0069",
-              "\u006A", "\u006B", "\u006C", "\u006D", "\u006E",
-              "\u006F", "\u0070", "\u0071", "\u0072", "\u0073",
-              "\u0074", "\u0075", "\u0076", "\u0077", "\u0078",
-              "\u0079", "\u007A", "\u03BC", "\u00E0", "\u00E1",
-              "\u00E2", "\u00E3", "\u00E4", "\u00E5", "\u00E6",
-              "\u00E7", "\u00E8", "\u00E9", "\u00EA", "\u00EB",
-              "\u00EC", "\u00ED", "\u00EE", "\u00EF", "\u00F0",
-              "\u00F1", "\u00F2", "\u00F3", "\u00F4", "\u00F5",
-              "\u00F6", "\u00F8", "\u00F9", "\u00FA", "\u00FB",
-              "\u00FC", "\u00FD", "\u00FE", "\u0073\u0073", "\u0101",
-              "\u0103", "\u0105", "\u0107", "\u0109", "\u010B",
-              "\u010D", "\u010F", "\u0111", "\u0113", "\u0115",
-              "\u0117", "\u0119", "\u011B", "\u011D", "\u011F",
-              "\u0121", "\u0123", "\u0125", "\u0127", "\u0129",
-              "\u012B", "\u012D", "\u012F", "\u0069\u0307", "\u0133",
-              "\u0135", "\u0137", "\u013A", "\u013C", "\u013E",
-              "\u0140", "\u0142", "\u0144", "\u0146", "\u0148",
-              "\u02BC\u006E", "\u014B", "\u014D", "\u014F", "\u0151",
-              "\u0153", "\u0155", "\u0157", "\u0159", "\u015B",
-              "\u015D", "\u015F", "\u0161", "\u0163", "\u0165",
-              "\u0167", "\u0169", "\u016B", "\u016D", "\u016F",
-              "\u0171", "\u0173", "\u0175", "\u0177", "\u00FF",
-              "\u017A", "\u017C", "\u017E", "\u0073", "\u0253",
-              "\u0183", "\u0185", "\u0254", "\u0188", "\u0256",
-              "\u0257", "\u018C", "\u01DD", "\u0259", "\u025B",
-              "\u0192", "\u0260", "\u0263", "\u0269", "\u0268",
-              "\u0199", "\u026F", "\u0272", "\u0275", "\u01A1",
-              "\u01A3", "\u01A5", "\u0280", "\u01A8", "\u0283",
-              "\u01AD", "\u0288", "\u01B0", "\u028A", "\u028B",
-              "\u01B4", "\u01B6", "\u0292", "\u01B9", "\u01BD",
-              "\u01C6", "\u01C6", "\u01C9", "\u01C9", "\u01CC",
-              "\u01CC", "\u01CE", "\u01D0", "\u01D2", "\u01D4",
-              "\u01D6", "\u01D8", "\u01DA", "\u01DC", "\u01DF",
-              "\u01E1", "\u01E3", "\u01E5", "\u01E7", "\u01E9",
-              "\u01EB", "\u01ED", "\u01EF", "\u006A\u030C", "\u01F3",
-              "\u01F3", "\u01F5", "\u0195", "\u01BF", "\u01F9",
-              "\u01FB", "\u01FD", "\u01FF", "\u0201", "\u0203",
-              "\u0205", "\u0207", "\u0209", "\u020B", "\u020D",
-              "\u020F", "\u0211", "\u0213", "\u0215", "\u0217",
-              "\u0219", "\u021B", "\u021D", "\u021F", "\u019E",
-              "\u0223", "\u0225", "\u0227", "\u0229", "\u022B",
-              "\u022D", "\u022F", "\u0231", "\u0233", "\u03B9",
-              "\u0020\u03B9", "\u03AC", "\u03AD", "\u03AE", "\u03AF",
-              "\u03CC", "\u03CD", "\u03CE", "\u03B9\u0308\u0301",
-              "\u03B1", "\u03B2", "\u03B3", "\u03B4", "\u03B5",
-              "\u03B6", "\u03B7", "\u03B8", "\u03B9", "\u03BA",
-              "\u03BB", "\u03BC", "\u03BD", "\u03BE", "\u03BF",
-              "\u03C0", "\u03C1", "\u03C3", "\u03C4", "\u03C5",
-              "\u03C6", "\u03C7", "\u03C8", "\u03C9", "\u03CA",
-              "\u03CB", "\u03C5\u0308\u0301", "\u03C3", "\u03B2",
-              "\u03B8", "\u03C5", "\u03CD", "\u03CB", "\u03C6",
-              "\u03C0", "\u03D9", "\u03DB", "\u03DD", "\u03DF",
-              "\u03E1", "\u03E3", "\u03E5", "\u03E7", "\u03E9",
-              "\u03EB", "\u03ED", "\u03EF", "\u03BA", "\u03C1",
-              "\u03C3", "\u03B8", "\u03B5", "\u0450", "\u0451",
-              "\u0452", "\u0453", "\u0454", "\u0455", "\u0456",
-              "\u0457", "\u0458", "\u0459", "\u045A", "\u045B",
-              "\u045C", "\u045D", "\u045E", "\u045F", "\u0430",
-              "\u0431", "\u0432", "\u0433", "\u0434", "\u0435",
-              "\u0436", "\u0437", "\u0438", "\u0439", "\u043A",
-              "\u043B", "\u043C", "\u043D", "\u043E", "\u043F",
-              "\u0440", "\u0441", "\u0442", "\u0443", "\u0444",
-              "\u0445", "\u0446", "\u0447", "\u0448", "\u0449",
-              "\u044A", "\u044B", "\u044C", "\u044D", "\u044E",
-              "\u044F", "\u0461", "\u0463", "\u0465", "\u0467",
-              "\u0469", "\u046B", "\u046D", "\u046F", "\u0471",
-              "\u0473", "\u0475", "\u0477", "\u0479", "\u047B",
-              "\u047D", "\u047F", "\u0481", "\u048B", "\u048D",
-              "\u048F", "\u0491", "\u0493", "\u0495", "\u0497",
-              "\u0499", "\u049B", "\u049D", "\u049F", "\u04A1",
-              "\u04A3", "\u04A5", "\u04A7", "\u04A9", "\u04AB",
-              "\u04AD", "\u04AF", "\u04B1", "\u04B3", "\u04B5",
-              "\u04B7", "\u04B9", "\u04BB", "\u04BD", "\u04BF",
-              "\u04C2", "\u04C4", "\u04C6", "\u04C8", "\u04CA",
-              "\u04CC", "\u04CE", "\u04D1", "\u04D3", "\u04D5",
-              "\u04D7", "\u04D9", "\u04DB", "\u04DD", "\u04DF",
-              "\u04E1", "\u04E3", "\u04E5", "\u04E7", "\u04E9",
-              "\u04EB", "\u04ED", "\u04EF", "\u04F1", "\u04F3",
-              "\u04F5", "\u04F9", "\u0501", "\u0503", "\u0505",
-              "\u0507", "\u0509", "\u050B", "\u050D", "\u050F",
-              "\u0561", "\u0562", "\u0563", "\u0564", "\u0565",
-              "\u0566", "\u0567", "\u0568", "\u0569", "\u056A",
-              "\u056B", "\u056C", "\u056D", "\u056E", "\u056F",
-              "\u0570", "\u0571", "\u0572", "\u0573", "\u0574",
-              "\u0575", "\u0576", "\u0577", "\u0578", "\u0579",
-              "\u057A", "\u057B", "\u057C", "\u057D", "\u057E",
-              "\u057F", "\u0580", "\u0581", "\u0582", "\u0583",
-              "\u0584", "\u0585", "\u0586", "\u0565\u0582", "\u1E01",
-              "\u1E03", "\u1E05", "\u1E07", "\u1E09", "\u1E0B",
-              "\u1E0D", "\u1E0F", "\u1E11", "\u1E13", "\u1E15",
-              "\u1E17", "\u1E19", "\u1E1B", "\u1E1D", "\u1E1F",
-              "\u1E21", "\u1E23", "\u1E25", "\u1E27", "\u1E29",
-              "\u1E2B", "\u1E2D", "\u1E2F", "\u1E31", "\u1E33",
-              "\u1E35", "\u1E37", "\u1E39", "\u1E3B", "\u1E3D",
-              "\u1E3F", "\u1E41", "\u1E43", "\u1E45", "\u1E47",
-              "\u1E49", "\u1E4B", "\u1E4D", "\u1E4F", "\u1E51",
-              "\u1E53", "\u1E55", "\u1E57", "\u1E59", "\u1E5B",
-              "\u1E5D", "\u1E5F", "\u1E61", "\u1E63", "\u1E65",
-              "\u1E67", "\u1E69", "\u1E6B", "\u1E6D", "\u1E6F",
-              "\u1E71", "\u1E73", "\u1E75", "\u1E77", "\u1E79",
-              "\u1E7B", "\u1E7D", "\u1E7F", "\u1E81", "\u1E83",
-              "\u1E85", "\u1E87", "\u1E89", "\u1E8B", "\u1E8D",
-              "\u1E8F", "\u1E91", "\u1E93", "\u1E95", "\u0068\u0331",
-              "\u0074\u0308", "\u0077\u030A", "\u0079\u030A",
-              "\u0061\u02BE", "\u1E61", "\u1EA1", "\u1EA3", "\u1EA5",
-              "\u1EA7", "\u1EA9", "\u1EAB", "\u1EAD", "\u1EAF",
-              "\u1EB1", "\u1EB3", "\u1EB5", "\u1EB7", "\u1EB9",
-              "\u1EBB", "\u1EBD", "\u1EBF", "\u1EC1", "\u1EC3",
-              "\u1EC5", "\u1EC7", "\u1EC9", "\u1ECB", "\u1ECD",
-              "\u1ECF", "\u1ED1", "\u1ED3", "\u1ED5", "\u1ED7",
-              "\u1ED9", "\u1EDB", "\u1EDD", "\u1EDF", "\u1EE1",
-              "\u1EE3", "\u1EE5", "\u1EE7", "\u1EE9", "\u1EEB",
-              "\u1EED", "\u1EEF", "\u1EF1", "\u1EF3", "\u1EF5",
-              "\u1EF7", "\u1EF9", "\u1F00", "\u1F01", "\u1F02",
-              "\u1F03", "\u1F04", "\u1F05", "\u1F06", "\u1F07",
-              "\u1F10", "\u1F11", "\u1F12", "\u1F13", "\u1F14",
-              "\u1F15", "\u1F20", "\u1F21", "\u1F22", "\u1F23",
-              "\u1F24", "\u1F25", "\u1F26", "\u1F27", "\u1F30",
-              "\u1F31", "\u1F32", "\u1F33", "\u1F34", "\u1F35",
-              "\u1F36", "\u1F37", "\u1F40", "\u1F41", "\u1F42",
-              "\u1F43", "\u1F44", "\u1F45", "\u03C5\u0313",
-              "\u03C5\u0313\u0300", "\u03C5\u0313\u0301",
-              "\u03C5\u0313\u0342", "\u1F51", "\u1F53", "\u1F55",
-              "\u1F57", "\u1F60", "\u1F61", "\u1F62", "\u1F63",
-              "\u1F64", "\u1F65", "\u1F66", "\u1F67", "\u1F00\u03B9",
-              "\u1F01\u03B9", "\u1F02\u03B9", "\u1F03\u03B9",
-              "\u1F04\u03B9", "\u1F05\u03B9", "\u1F06\u03B9",
-              "\u1F07\u03B9", "\u1F00\u03B9", "\u1F01\u03B9",
-              "\u1F02\u03B9", "\u1F03\u03B9", "\u1F04\u03B9",
-              "\u1F05\u03B9", "\u1F06\u03B9", "\u1F07\u03B9",
-              "\u1F20\u03B9", "\u1F21\u03B9", "\u1F22\u03B9",
-              "\u1F23\u03B9", "\u1F24\u03B9", "\u1F25\u03B9",
-              "\u1F26\u03B9", "\u1F27\u03B9", "\u1F20\u03B9",
-              "\u1F21\u03B9", "\u1F22\u03B9", "\u1F23\u03B9",
-              "\u1F24\u03B9", "\u1F25\u03B9", "\u1F26\u03B9",
-              "\u1F27\u03B9", "\u1F60\u03B9", "\u1F61\u03B9",
-              "\u1F62\u03B9", "\u1F63\u03B9", "\u1F64\u03B9",
-              "\u1F65\u03B9", "\u1F66\u03B9", "\u1F67\u03B9",
-              "\u1F60\u03B9", "\u1F61\u03B9", "\u1F62\u03B9",
-              "\u1F63\u03B9", "\u1F64\u03B9", "\u1F65\u03B9",
-              "\u1F66\u03B9", "\u1F67\u03B9", "\u1F70\u03B9",
-              "\u03B1\u03B9", "\u03AC\u03B9", "\u03B1\u0342",
-              "\u03B1\u0342\u03B9", "\u1FB0", "\u1FB1", "\u1F70",
-              "\u1F71", "\u03B1\u03B9", "\u03B9", "\u1F74\u03B9",
-              "\u03B7\u03B9", "\u03AE\u03B9", "\u03B7\u0342",
-              "\u03B7\u0342\u03B9", "\u1F72", "\u1F73", "\u1F74",
-              "\u1F75", "\u03B7\u03B9", "\u03B9\u0308\u0300",
-              "\u03B9\u0308\u0301", "\u03B9\u0342",
-              "\u03B9\u0308\u0342", "\u1FD0", "\u1FD1", "\u1F76",
-              "\u1F77", "\u03C5\u0308\u0300", "\u03C5\u0308\u0301",
-              "\u03C1\u0313", "\u03C5\u0342", "\u03C5\u0308\u0342",
-              "\u1FE0", "\u1FE1", "\u1F7A", "\u1F7B", "\u1FE5",
-              "\u1F7C\u03B9", "\u03C9\u03B9", "\u03CE\u03B9",
-              "\u03C9\u0342", "\u03C9\u0342\u03B9", "\u1F78", "\u1F79",
-              "\u1F7C", "\u1F7D", "\u03C9\u03B9", "\u0072\u0073",
-              "\u0063", "\u00B0\u0063", "\u025B", "\u00B0\u0066",
-              "\u0068", "\u0068", "\u0068", "\u0069", "\u0069",
-              "\u006C", "\u006E", "\u006E\u006F", "\u0070", "\u0071",
-              "\u0072", "\u0072", "\u0072", "\u0073\u006D",
-              "\u0074\u0065\u006C", "\u0074\u006D", "\u007A", "\u03C9",
-              "\u007A", "\u006B", "\u00E5", "\u0062", "\u0063",
-              "\u0065", "\u0066", "\u006D", "\u03B3", "\u03C0",
-              "\u0064", "\u2170", "\u2171", "\u2172", "\u2173",
-              "\u2174", "\u2175", "\u2176", "\u2177", "\u2178",
-              "\u2179", "\u217A", "\u217B", "\u217C", "\u217D",
-              "\u217E", "\u217F", "\u24D0", "\u24D1", "\u24D2",
-              "\u24D3", "\u24D4", "\u24D5", "\u24D6", "\u24D7",
-              "\u24D8", "\u24D9", "\u24DA", "\u24DB", "\u24DC",
-              "\u24DD", "\u24DE", "\u24DF", "\u24E0", "\u24E1",
-              "\u24E2", "\u24E3", "\u24E4", "\u24E5", "\u24E6",
-              "\u24E7", "\u24E8", "\u24E9", "\u0068\u0070\u0061",
-              "\u0061\u0075", "\u006F\u0076", "\u0070\u0061",
-              "\u006E\u0061", "\u03BC\u0061", "\u006D\u0061",
-              "\u006B\u0061", "\u006B\u0062", "\u006D\u0062",
-              "\u0067\u0062", "\u0070\u0066", "\u006E\u0066",
-              "\u03BC\u0066", "\u0068\u007A", "\u006B\u0068\u007A",
-              "\u006D\u0068\u007A", "\u0067\u0068\u007A",
-              "\u0074\u0068\u007A", "\u0070\u0061",
-              "\u006B\u0070\u0061", "\u006D\u0070\u0061",
-              "\u0067\u0070\u0061", "\u0070\u0076", "\u006E\u0076",
-              "\u03BC\u0076", "\u006D\u0076", "\u006B\u0076",
-              "\u006D\u0076", "\u0070\u0077", "\u006E\u0077",
-              "\u03BC\u0077", "\u006D\u0077", "\u006B\u0077",
-              "\u006D\u0077", "\u006B\u03C9", "\u006D\u03C9",
-              "\u0062\u0071", "\u0063\u2215\u006B\u0067",
-              "\u0063\u006F\u002E", "\u0064\u0062", "\u0067\u0079",
-              "\u0068\u0070", "\u006B\u006B", "\u006B\u006D",
-              "\u0070\u0068", "\u0070\u0070\u006D", "\u0070\u0072",
-              "\u0073\u0076", "\u0077\u0062", "\u0066\u0066",
-              "\u0066\u0069", "\u0066\u006C", "\u0066\u0066\u0069",
-              "\u0066\u0066\u006C", "\u0073\u0074", "\u0073\u0074",
-              "\u0574\u0576", "\u0574\u0565", "\u0574\u056B",
-              "\u057E\u0576", "\u0574\u056D", "\uFF41", "\uFF42",
-              "\uFF43", "\uFF44", "\uFF45", "\uFF46", "\uFF47",
-              "\uFF48", "\uFF49", "\uFF4A", "\uFF4B", "\uFF4C",
-              "\uFF4D", "\uFF4E", "\uFF4F", "\uFF50", "\uFF51",
-              "\uFF52", "\uFF53", "\uFF54", "\uFF55", "\uFF56",
-              "\uFF57", "\uFF58", "\uFF59", "\uFF5A" };
+      final char[] upperCaseArr = new char[] { '\u0041', '\u0042', '\u0043',
+          '\u0044', '\u0045', '\u0046', '\u0047', '\u0048', '\u0049', '\u004A',
+          '\u004B', '\u004C', '\u004D', '\u004E', '\u004F', '\u0050', '\u0051',
+          '\u0052', '\u0053', '\u0054', '\u0055', '\u0056', '\u0057', '\u0058',
+          '\u0059', '\u005A', '\u00B5', '\u00C0', '\u00C1', '\u00C2', '\u00C3',
+          '\u00C4', '\u00C5', '\u00C6', '\u00C7', '\u00C8', '\u00C9', '\u00CA',
+          '\u00CB', '\u00CC', '\u00CD', '\u00CE', '\u00CF', '\u00D0', '\u00D1',
+          '\u00D2', '\u00D3', '\u00D4', '\u00D5', '\u00D6', '\u00D8', '\u00D9',
+          '\u00DA', '\u00DB', '\u00DC', '\u00DD', '\u00DE', '\u00DF', '\u0100',
+          '\u0102', '\u0104', '\u0106', '\u0108', '\u010A', '\u010C', '\u010E',
+          '\u0110', '\u0112', '\u0114', '\u0116', '\u0118', '\u011A', '\u011C',
+          '\u011E', '\u0120', '\u0122', '\u0124', '\u0126', '\u0128', '\u012A',
+          '\u012C', '\u012E', '\u0130', '\u0132', '\u0134', '\u0136', '\u0139',
+          '\u013B', '\u013D', '\u013F', '\u0141', '\u0143', '\u0145', '\u0147',
+          '\u0149', '\u014A', '\u014C', '\u014E', '\u0150', '\u0152', '\u0154',
+          '\u0156', '\u0158', '\u015A', '\u015C', '\u015E', '\u0160', '\u0162',
+          '\u0164', '\u0166', '\u0168', '\u016A', '\u016C', '\u016E', '\u0170',
+          '\u0172', '\u0174', '\u0176', '\u0178', '\u0179', '\u017B', '\u017D',
+          '\u017F', '\u0181', '\u0182', '\u0184', '\u0186', '\u0187', '\u0189',
+          '\u018A', '\u018B', '\u018E', '\u018F', '\u0190', '\u0191', '\u0193',
+          '\u0194', '\u0196', '\u0197', '\u0198', '\u019C', '\u019D', '\u019F',
+          '\u01A0', '\u01A2', '\u01A4', '\u01A6', '\u01A7', '\u01A9', '\u01AC',
+          '\u01AE', '\u01AF', '\u01B1', '\u01B2', '\u01B3', '\u01B5', '\u01B7',
+          '\u01B8', '\u01BC', '\u01C4', '\u01C5', '\u01C7', '\u01C8', '\u01CA',
+          '\u01CB', '\u01CD', '\u01CF', '\u01D1', '\u01D3', '\u01D5', '\u01D7',
+          '\u01D9', '\u01DB', '\u01DE', '\u01E0', '\u01E2', '\u01E4', '\u01E6',
+          '\u01E8', '\u01EA', '\u01EC', '\u01EE', '\u01F0', '\u01F1', '\u01F2',
+          '\u01F4', '\u01F6', '\u01F7', '\u01F8', '\u01FA', '\u01FC', '\u01FE',
+          '\u0200', '\u0202', '\u0204', '\u0206', '\u0208', '\u020A', '\u020C',
+          '\u020E', '\u0210', '\u0212', '\u0214', '\u0216', '\u0218', '\u021A',
+          '\u021C', '\u021E', '\u0220', '\u0222', '\u0224', '\u0226', '\u0228',
+          '\u022A', '\u022C', '\u022E', '\u0230', '\u0232', '\u0345', '\u037A',
+          '\u0386', '\u0388', '\u0389', '\u038A', '\u038C', '\u038E', '\u038F',
+          '\u0390', '\u0391', '\u0392', '\u0393', '\u0394', '\u0395', '\u0396',
+          '\u0397', '\u0398', '\u0399', '\u039A', '\u039B', '\u039C', '\u039D',
+          '\u039E', '\u039F', '\u03A0', '\u03A1', '\u03A3', '\u03A4', '\u03A5',
+          '\u03A6', '\u03A7', '\u03A8', '\u03A9', '\u03AA', '\u03AB', '\u03B0',
+          '\u03C2', '\u03D0', '\u03D1', '\u03D2', '\u03D3', '\u03D4', '\u03D5',
+          '\u03D6', '\u03D8', '\u03DA', '\u03DC', '\u03DE', '\u03E0', '\u03E2',
+          '\u03E4', '\u03E6', '\u03E8', '\u03EA', '\u03EC', '\u03EE', '\u03F0',
+          '\u03F1', '\u03F2', '\u03F4', '\u03F5', '\u0400', '\u0401', '\u0402',
+          '\u0403', '\u0404', '\u0405', '\u0406', '\u0407', '\u0408', '\u0409',
+          '\u040A', '\u040B', '\u040C', '\u040D', '\u040E', '\u040F', '\u0410',
+          '\u0411', '\u0412', '\u0413', '\u0414', '\u0415', '\u0416', '\u0417',
+          '\u0418', '\u0419', '\u041A', '\u041B', '\u041C', '\u041D', '\u041E',
+          '\u041F', '\u0420', '\u0421', '\u0422', '\u0423', '\u0424', '\u0425',
+          '\u0426', '\u0427', '\u0428', '\u0429', '\u042A', '\u042B', '\u042C',
+          '\u042D', '\u042E', '\u042F', '\u0460', '\u0462', '\u0464', '\u0466',
+          '\u0468', '\u046A', '\u046C', '\u046E', '\u0470', '\u0472', '\u0474',
+          '\u0476', '\u0478', '\u047A', '\u047C', '\u047E', '\u0480', '\u048A',
+          '\u048C', '\u048E', '\u0490', '\u0492', '\u0494', '\u0496', '\u0498',
+          '\u049A', '\u049C', '\u049E', '\u04A0', '\u04A2', '\u04A4', '\u04A6',
+          '\u04A8', '\u04AA', '\u04AC', '\u04AE', '\u04B0', '\u04B2', '\u04B4',
+          '\u04B6', '\u04B8', '\u04BA', '\u04BC', '\u04BE', '\u04C1', '\u04C3',
+          '\u04C5', '\u04C7', '\u04C9', '\u04CB', '\u04CD', '\u04D0', '\u04D2',
+          '\u04D4', '\u04D6', '\u04D8', '\u04DA', '\u04DC', '\u04DE', '\u04E0',
+          '\u04E2', '\u04E4', '\u04E6', '\u04E8', '\u04EA', '\u04EC', '\u04EE',
+          '\u04F0', '\u04F2', '\u04F4', '\u04F8', '\u0500', '\u0502', '\u0504',
+          '\u0506', '\u0508', '\u050A', '\u050C', '\u050E', '\u0531', '\u0532',
+          '\u0533', '\u0534', '\u0535', '\u0536', '\u0537', '\u0538', '\u0539',
+          '\u053A', '\u053B', '\u053C', '\u053D', '\u053E', '\u053F', '\u0540',
+          '\u0541', '\u0542', '\u0543', '\u0544', '\u0545', '\u0546', '\u0547',
+          '\u0548', '\u0549', '\u054A', '\u054B', '\u054C', '\u054D', '\u054E',
+          '\u054F', '\u0550', '\u0551', '\u0552', '\u0553', '\u0554', '\u0555',
+          '\u0556', '\u0587', '\u1E00', '\u1E02', '\u1E04', '\u1E06', '\u1E08',
+          '\u1E0A', '\u1E0C', '\u1E0E', '\u1E10', '\u1E12', '\u1E14', '\u1E16',
+          '\u1E18', '\u1E1A', '\u1E1C', '\u1E1E', '\u1E20', '\u1E22', '\u1E24',
+          '\u1E26', '\u1E28', '\u1E2A', '\u1E2C', '\u1E2E', '\u1E30', '\u1E32',
+          '\u1E34', '\u1E36', '\u1E38', '\u1E3A', '\u1E3C', '\u1E3E', '\u1E40',
+          '\u1E42', '\u1E44', '\u1E46', '\u1E48', '\u1E4A', '\u1E4C', '\u1E4E',
+          '\u1E50', '\u1E52', '\u1E54', '\u1E56', '\u1E58', '\u1E5A', '\u1E5C',
+          '\u1E5E', '\u1E60', '\u1E62', '\u1E64', '\u1E66', '\u1E68', '\u1E6A',
+          '\u1E6C', '\u1E6E', '\u1E70', '\u1E72', '\u1E74', '\u1E76', '\u1E78',
+          '\u1E7A', '\u1E7C', '\u1E7E', '\u1E80', '\u1E82', '\u1E84', '\u1E86',
+          '\u1E88', '\u1E8A', '\u1E8C', '\u1E8E', '\u1E90', '\u1E92', '\u1E94',
+          '\u1E96', '\u1E97', '\u1E98', '\u1E99', '\u1E9A', '\u1E9B', '\u1EA0',
+          '\u1EA2', '\u1EA4', '\u1EA6', '\u1EA8', '\u1EAA', '\u1EAC', '\u1EAE',
+          '\u1EB0', '\u1EB2', '\u1EB4', '\u1EB6', '\u1EB8', '\u1EBA', '\u1EBC',
+          '\u1EBE', '\u1EC0', '\u1EC2', '\u1EC4', '\u1EC6', '\u1EC8', '\u1ECA',
+          '\u1ECC', '\u1ECE', '\u1ED0', '\u1ED2', '\u1ED4', '\u1ED6', '\u1ED8',
+          '\u1EDA', '\u1EDC', '\u1EDE', '\u1EE0', '\u1EE2', '\u1EE4', '\u1EE6',
+          '\u1EE8', '\u1EEA', '\u1EEC', '\u1EEE', '\u1EF0', '\u1EF2', '\u1EF4',
+          '\u1EF6', '\u1EF8', '\u1F08', '\u1F09', '\u1F0A', '\u1F0B', '\u1F0C',
+          '\u1F0D', '\u1F0E', '\u1F0F', '\u1F18', '\u1F19', '\u1F1A', '\u1F1B',
+          '\u1F1C', '\u1F1D', '\u1F28', '\u1F29', '\u1F2A', '\u1F2B', '\u1F2C',
+          '\u1F2D', '\u1F2E', '\u1F2F', '\u1F38', '\u1F39', '\u1F3A', '\u1F3B',
+          '\u1F3C', '\u1F3D', '\u1F3E', '\u1F3F', '\u1F48', '\u1F49', '\u1F4A',
+          '\u1F4B', '\u1F4C', '\u1F4D', '\u1F50', '\u1F52', '\u1F54', '\u1F56',
+          '\u1F59', '\u1F5B', '\u1F5D', '\u1F5F', '\u1F68', '\u1F69', '\u1F6A',
+          '\u1F6B', '\u1F6C', '\u1F6D', '\u1F6E', '\u1F6F', '\u1F80', '\u1F81',
+          '\u1F82', '\u1F83', '\u1F84', '\u1F85', '\u1F86', '\u1F87', '\u1F88',
+          '\u1F89', '\u1F8A', '\u1F8B', '\u1F8C', '\u1F8D', '\u1F8E', '\u1F8F',
+          '\u1F90', '\u1F91', '\u1F92', '\u1F93', '\u1F94', '\u1F95', '\u1F96',
+          '\u1F97', '\u1F98', '\u1F99', '\u1F9A', '\u1F9B', '\u1F9C', '\u1F9D',
+          '\u1F9E', '\u1F9F', '\u1FA0', '\u1FA1', '\u1FA2', '\u1FA3', '\u1FA4',
+          '\u1FA5', '\u1FA6', '\u1FA7', '\u1FA8', '\u1FA9', '\u1FAA', '\u1FAB',
+          '\u1FAC', '\u1FAD', '\u1FAE', '\u1FAF', '\u1FB2', '\u1FB3', '\u1FB4',
+          '\u1FB6', '\u1FB7', '\u1FB8', '\u1FB9', '\u1FBA', '\u1FBB', '\u1FBC',
+          '\u1FBE', '\u1FC2', '\u1FC3', '\u1FC4', '\u1FC6', '\u1FC7', '\u1FC8',
+          '\u1FC9', '\u1FCA', '\u1FCB', '\u1FCC', '\u1FD2', '\u1FD3', '\u1FD6',
+          '\u1FD7', '\u1FD8', '\u1FD9', '\u1FDA', '\u1FDB', '\u1FE2', '\u1FE3',
+          '\u1FE4', '\u1FE6', '\u1FE7', '\u1FE8', '\u1FE9', '\u1FEA', '\u1FEB',
+          '\u1FEC', '\u1FF2', '\u1FF3', '\u1FF4', '\u1FF6', '\u1FF7', '\u1FF8',
+          '\u1FF9', '\u1FFA', '\u1FFB', '\u1FFC', '\u20A8', '\u2102', '\u2103',
+          '\u2107', '\u2109', '\u210B', '\u210C', '\u210D', '\u2110', '\u2111',
+          '\u2112', '\u2115', '\u2116', '\u2119', '\u211A', '\u211B', '\u211C',
+          '\u211D', '\u2120', '\u2121', '\u2122', '\u2124', '\u2126', '\u2128',
+          '\u212A', '\u212B', '\u212C', '\u212D', '\u2130', '\u2131', '\u2133',
+          '\u213E', '\u213F', '\u2145', '\u2160', '\u2161', '\u2162', '\u2163',
+          '\u2164', '\u2165', '\u2166', '\u2167', '\u2168', '\u2169', '\u216A',
+          '\u216B', '\u216C', '\u216D', '\u216E', '\u216F', '\u24B6', '\u24B7',
+          '\u24B8', '\u24B9', '\u24BA', '\u24BB', '\u24BC', '\u24BD', '\u24BE',
+          '\u24BF', '\u24C0', '\u24C1', '\u24C2', '\u24C3', '\u24C4', '\u24C5',
+          '\u24C6', '\u24C7', '\u24C8', '\u24C9', '\u24CA', '\u24CB', '\u24CC',
+          '\u24CD', '\u24CE', '\u24CF', '\u3371', '\u3373', '\u3375', '\u3380',
+          '\u3381', '\u3382', '\u3383', '\u3384', '\u3385', '\u3386', '\u3387',
+          '\u338A', '\u338B', '\u338C', '\u3390', '\u3391', '\u3392', '\u3393',
+          '\u3394', '\u33A9', '\u33AA', '\u33AB', '\u33AC', '\u33B4', '\u33B5',
+          '\u33B6', '\u33B7', '\u33B8', '\u33B9', '\u33BA', '\u33BB', '\u33BC',
+          '\u33BD', '\u33BE', '\u33BF', '\u33C0', '\u33C1', '\u33C3', '\u33C6',
+          '\u33C7', '\u33C8', '\u33C9', '\u33CB', '\u33CD', '\u33CE', '\u33D7',
+          '\u33D9', '\u33DA', '\u33DC', '\u33DD', '\uFB00', '\uFB01', '\uFB02',
+          '\uFB03', '\uFB04', '\uFB05', '\uFB06', '\uFB13', '\uFB14', '\uFB15',
+          '\uFB16', '\uFB17', '\uFF21', '\uFF22', '\uFF23', '\uFF24', '\uFF25',
+          '\uFF26', '\uFF27', '\uFF28', '\uFF29', '\uFF2A', '\uFF2B', '\uFF2C',
+          '\uFF2D', '\uFF2E', '\uFF2F', '\uFF30', '\uFF31', '\uFF32', '\uFF33',
+          '\uFF34', '\uFF35', '\uFF36', '\uFF37', '\uFF38', '\uFF39', '\uFF3A' };
+      final String[] lowerCaseFoldedArr = new String[] { "\u0061", "\u0062",
+          "\u0063", "\u0064", "\u0065", "\u0066", "\u0067", "\u0068", "\u0069",
+          "\u006A", "\u006B", "\u006C", "\u006D", "\u006E", "\u006F", "\u0070",
+          "\u0071", "\u0072", "\u0073", "\u0074", "\u0075", "\u0076", "\u0077",
+          "\u0078", "\u0079", "\u007A", "\u03BC", "\u00E0", "\u00E1", "\u00E2",
+          "\u00E3", "\u00E4", "\u00E5", "\u00E6", "\u00E7", "\u00E8", "\u00E9",
+          "\u00EA", "\u00EB", "\u00EC", "\u00ED", "\u00EE", "\u00EF", "\u00F0",
+          "\u00F1", "\u00F2", "\u00F3", "\u00F4", "\u00F5", "\u00F6", "\u00F8",
+          "\u00F9", "\u00FA", "\u00FB", "\u00FC", "\u00FD", "\u00FE",
+          "\u0073\u0073", "\u0101", "\u0103", "\u0105", "\u0107", "\u0109",
+          "\u010B", "\u010D", "\u010F", "\u0111", "\u0113", "\u0115", "\u0117",
+          "\u0119", "\u011B", "\u011D", "\u011F", "\u0121", "\u0123", "\u0125",
+          "\u0127", "\u0129", "\u012B", "\u012D", "\u012F", "\u0069\u0307",
+          "\u0133", "\u0135", "\u0137", "\u013A", "\u013C", "\u013E", "\u0140",
+          "\u0142", "\u0144", "\u0146", "\u0148", "\u02BC\u006E", "\u014B",
+          "\u014D", "\u014F", "\u0151", "\u0153", "\u0155", "\u0157", "\u0159",
+          "\u015B", "\u015D", "\u015F", "\u0161", "\u0163", "\u0165", "\u0167",
+          "\u0169", "\u016B", "\u016D", "\u016F", "\u0171", "\u0173", "\u0175",
+          "\u0177", "\u00FF", "\u017A", "\u017C", "\u017E", "\u0073", "\u0253",
+          "\u0183", "\u0185", "\u0254", "\u0188", "\u0256", "\u0257", "\u018C",
+          "\u01DD", "\u0259", "\u025B", "\u0192", "\u0260", "\u0263", "\u0269",
+          "\u0268", "\u0199", "\u026F", "\u0272", "\u0275", "\u01A1", "\u01A3",
+          "\u01A5", "\u0280", "\u01A8", "\u0283", "\u01AD", "\u0288", "\u01B0",
+          "\u028A", "\u028B", "\u01B4", "\u01B6", "\u0292", "\u01B9", "\u01BD",
+          "\u01C6", "\u01C6", "\u01C9", "\u01C9", "\u01CC", "\u01CC", "\u01CE",
+          "\u01D0", "\u01D2", "\u01D4", "\u01D6", "\u01D8", "\u01DA", "\u01DC",
+          "\u01DF", "\u01E1", "\u01E3", "\u01E5", "\u01E7", "\u01E9", "\u01EB",
+          "\u01ED", "\u01EF", "\u006A\u030C", "\u01F3", "\u01F3", "\u01F5",
+          "\u0195", "\u01BF", "\u01F9", "\u01FB", "\u01FD", "\u01FF", "\u0201",
+          "\u0203", "\u0205", "\u0207", "\u0209", "\u020B", "\u020D", "\u020F",
+          "\u0211", "\u0213", "\u0215", "\u0217", "\u0219", "\u021B", "\u021D",
+          "\u021F", "\u019E", "\u0223", "\u0225", "\u0227", "\u0229", "\u022B",
+          "\u022D", "\u022F", "\u0231", "\u0233", "\u03B9", "\u0020\u03B9",
+          "\u03AC", "\u03AD", "\u03AE", "\u03AF", "\u03CC", "\u03CD", "\u03CE",
+          "\u03B9\u0308\u0301", "\u03B1", "\u03B2", "\u03B3", "\u03B4",
+          "\u03B5", "\u03B6", "\u03B7", "\u03B8", "\u03B9", "\u03BA", "\u03BB",
+          "\u03BC", "\u03BD", "\u03BE", "\u03BF", "\u03C0", "\u03C1", "\u03C3",
+          "\u03C4", "\u03C5", "\u03C6", "\u03C7", "\u03C8", "\u03C9", "\u03CA",
+          "\u03CB", "\u03C5\u0308\u0301", "\u03C3", "\u03B2", "\u03B8",
+          "\u03C5", "\u03CD", "\u03CB", "\u03C6", "\u03C0", "\u03D9", "\u03DB",
+          "\u03DD", "\u03DF", "\u03E1", "\u03E3", "\u03E5", "\u03E7", "\u03E9",
+          "\u03EB", "\u03ED", "\u03EF", "\u03BA", "\u03C1", "\u03C3", "\u03B8",
+          "\u03B5", "\u0450", "\u0451", "\u0452", "\u0453", "\u0454", "\u0455",
+          "\u0456", "\u0457", "\u0458", "\u0459", "\u045A", "\u045B", "\u045C",
+          "\u045D", "\u045E", "\u045F", "\u0430", "\u0431", "\u0432", "\u0433",
+          "\u0434", "\u0435", "\u0436", "\u0437", "\u0438", "\u0439", "\u043A",
+          "\u043B", "\u043C", "\u043D", "\u043E", "\u043F", "\u0440", "\u0441",
+          "\u0442", "\u0443", "\u0444", "\u0445", "\u0446", "\u0447", "\u0448",
+          "\u0449", "\u044A", "\u044B", "\u044C", "\u044D", "\u044E", "\u044F",
+          "\u0461", "\u0463", "\u0465", "\u0467", "\u0469", "\u046B", "\u046D",
+          "\u046F", "\u0471", "\u0473", "\u0475", "\u0477", "\u0479", "\u047B",
+          "\u047D", "\u047F", "\u0481", "\u048B", "\u048D", "\u048F", "\u0491",
+          "\u0493", "\u0495", "\u0497", "\u0499", "\u049B", "\u049D", "\u049F",
+          "\u04A1", "\u04A3", "\u04A5", "\u04A7", "\u04A9", "\u04AB", "\u04AD",
+          "\u04AF", "\u04B1", "\u04B3", "\u04B5", "\u04B7", "\u04B9", "\u04BB",
+          "\u04BD", "\u04BF", "\u04C2", "\u04C4", "\u04C6", "\u04C8", "\u04CA",
+          "\u04CC", "\u04CE", "\u04D1", "\u04D3", "\u04D5", "\u04D7", "\u04D9",
+          "\u04DB", "\u04DD", "\u04DF", "\u04E1", "\u04E3", "\u04E5", "\u04E7",
+          "\u04E9", "\u04EB", "\u04ED", "\u04EF", "\u04F1", "\u04F3", "\u04F5",
+          "\u04F9", "\u0501", "\u0503", "\u0505", "\u0507", "\u0509", "\u050B",
+          "\u050D", "\u050F", "\u0561", "\u0562", "\u0563", "\u0564", "\u0565",
+          "\u0566", "\u0567", "\u0568", "\u0569", "\u056A", "\u056B", "\u056C",
+          "\u056D", "\u056E", "\u056F", "\u0570", "\u0571", "\u0572", "\u0573",
+          "\u0574", "\u0575", "\u0576", "\u0577", "\u0578", "\u0579", "\u057A",
+          "\u057B", "\u057C", "\u057D", "\u057E", "\u057F", "\u0580", "\u0581",
+          "\u0582", "\u0583", "\u0584", "\u0585", "\u0586", "\u0565\u0582",
+          "\u1E01", "\u1E03", "\u1E05", "\u1E07", "\u1E09", "\u1E0B", "\u1E0D",
+          "\u1E0F", "\u1E11", "\u1E13", "\u1E15", "\u1E17", "\u1E19", "\u1E1B",
+          "\u1E1D", "\u1E1F", "\u1E21", "\u1E23", "\u1E25", "\u1E27", "\u1E29",
+          "\u1E2B", "\u1E2D", "\u1E2F", "\u1E31", "\u1E33", "\u1E35", "\u1E37",
+          "\u1E39", "\u1E3B", "\u1E3D", "\u1E3F", "\u1E41", "\u1E43", "\u1E45",
+          "\u1E47", "\u1E49", "\u1E4B", "\u1E4D", "\u1E4F", "\u1E51", "\u1E53",
+          "\u1E55", "\u1E57", "\u1E59", "\u1E5B", "\u1E5D", "\u1E5F", "\u1E61",
+          "\u1E63", "\u1E65", "\u1E67", "\u1E69", "\u1E6B", "\u1E6D", "\u1E6F",
+          "\u1E71", "\u1E73", "\u1E75", "\u1E77", "\u1E79", "\u1E7B", "\u1E7D",
+          "\u1E7F", "\u1E81", "\u1E83", "\u1E85", "\u1E87", "\u1E89", "\u1E8B",
+          "\u1E8D", "\u1E8F", "\u1E91", "\u1E93", "\u1E95", "\u0068\u0331",
+          "\u0074\u0308", "\u0077\u030A", "\u0079\u030A", "\u0061\u02BE",
+          "\u1E61", "\u1EA1", "\u1EA3", "\u1EA5", "\u1EA7", "\u1EA9", "\u1EAB",
+          "\u1EAD", "\u1EAF", "\u1EB1", "\u1EB3", "\u1EB5", "\u1EB7", "\u1EB9",
+          "\u1EBB", "\u1EBD", "\u1EBF", "\u1EC1", "\u1EC3", "\u1EC5", "\u1EC7",
+          "\u1EC9", "\u1ECB", "\u1ECD", "\u1ECF", "\u1ED1", "\u1ED3", "\u1ED5",
+          "\u1ED7", "\u1ED9", "\u1EDB", "\u1EDD", "\u1EDF", "\u1EE1", "\u1EE3",
+          "\u1EE5", "\u1EE7", "\u1EE9", "\u1EEB", "\u1EED", "\u1EEF", "\u1EF1",
+          "\u1EF3", "\u1EF5", "\u1EF7", "\u1EF9", "\u1F00", "\u1F01", "\u1F02",
+          "\u1F03", "\u1F04", "\u1F05", "\u1F06", "\u1F07", "\u1F10", "\u1F11",
+          "\u1F12", "\u1F13", "\u1F14", "\u1F15", "\u1F20", "\u1F21", "\u1F22",
+          "\u1F23", "\u1F24", "\u1F25", "\u1F26", "\u1F27", "\u1F30", "\u1F31",
+          "\u1F32", "\u1F33", "\u1F34", "\u1F35", "\u1F36", "\u1F37", "\u1F40",
+          "\u1F41", "\u1F42", "\u1F43", "\u1F44", "\u1F45", "\u03C5\u0313",
+          "\u03C5\u0313\u0300", "\u03C5\u0313\u0301", "\u03C5\u0313\u0342",
+          "\u1F51", "\u1F53", "\u1F55", "\u1F57", "\u1F60", "\u1F61", "\u1F62",
+          "\u1F63", "\u1F64", "\u1F65", "\u1F66", "\u1F67", "\u1F00\u03B9",
+          "\u1F01\u03B9", "\u1F02\u03B9", "\u1F03\u03B9", "\u1F04\u03B9",
+          "\u1F05\u03B9", "\u1F06\u03B9", "\u1F07\u03B9", "\u1F00\u03B9",
+          "\u1F01\u03B9", "\u1F02\u03B9", "\u1F03\u03B9", "\u1F04\u03B9",
+          "\u1F05\u03B9", "\u1F06\u03B9", "\u1F07\u03B9", "\u1F20\u03B9",
+          "\u1F21\u03B9", "\u1F22\u03B9", "\u1F23\u03B9", "\u1F24\u03B9",
+          "\u1F25\u03B9", "\u1F26\u03B9", "\u1F27\u03B9", "\u1F20\u03B9",
+          "\u1F21\u03B9", "\u1F22\u03B9", "\u1F23\u03B9", "\u1F24\u03B9",
+          "\u1F25\u03B9", "\u1F26\u03B9", "\u1F27\u03B9", "\u1F60\u03B9",
+          "\u1F61\u03B9", "\u1F62\u03B9", "\u1F63\u03B9", "\u1F64\u03B9",
+          "\u1F65\u03B9", "\u1F66\u03B9", "\u1F67\u03B9", "\u1F60\u03B9",
+          "\u1F61\u03B9", "\u1F62\u03B9", "\u1F63\u03B9", "\u1F64\u03B9",
+          "\u1F65\u03B9", "\u1F66\u03B9", "\u1F67\u03B9", "\u1F70\u03B9",
+          "\u03B1\u03B9", "\u03AC\u03B9", "\u03B1\u0342", "\u03B1\u0342\u03B9",
+          "\u1FB0", "\u1FB1", "\u1F70", "\u1F71", "\u03B1\u03B9", "\u03B9",
+          "\u1F74\u03B9", "\u03B7\u03B9", "\u03AE\u03B9", "\u03B7\u0342",
+          "\u03B7\u0342\u03B9", "\u1F72", "\u1F73", "\u1F74", "\u1F75",
+          "\u03B7\u03B9", "\u03B9\u0308\u0300", "\u03B9\u0308\u0301",
+          "\u03B9\u0342", "\u03B9\u0308\u0342", "\u1FD0", "\u1FD1", "\u1F76",
+          "\u1F77", "\u03C5\u0308\u0300", "\u03C5\u0308\u0301", "\u03C1\u0313",
+          "\u03C5\u0342", "\u03C5\u0308\u0342", "\u1FE0", "\u1FE1", "\u1F7A",
+          "\u1F7B", "\u1FE5", "\u1F7C\u03B9", "\u03C9\u03B9", "\u03CE\u03B9",
+          "\u03C9\u0342", "\u03C9\u0342\u03B9", "\u1F78", "\u1F79", "\u1F7C",
+          "\u1F7D", "\u03C9\u03B9", "\u0072\u0073", "\u0063", "\u00B0\u0063",
+          "\u025B", "\u00B0\u0066", "\u0068", "\u0068", "\u0068", "\u0069",
+          "\u0069", "\u006C", "\u006E", "\u006E\u006F", "\u0070", "\u0071",
+          "\u0072", "\u0072", "\u0072", "\u0073\u006D", "\u0074\u0065\u006C",
+          "\u0074\u006D", "\u007A", "\u03C9", "\u007A", "\u006B", "\u00E5",
+          "\u0062", "\u0063", "\u0065", "\u0066", "\u006D", "\u03B3", "\u03C0",
+          "\u0064", "\u2170", "\u2171", "\u2172", "\u2173", "\u2174", "\u2175",
+          "\u2176", "\u2177", "\u2178", "\u2179", "\u217A", "\u217B", "\u217C",
+          "\u217D", "\u217E", "\u217F", "\u24D0", "\u24D1", "\u24D2", "\u24D3",
+          "\u24D4", "\u24D5", "\u24D6", "\u24D7", "\u24D8", "\u24D9", "\u24DA",
+          "\u24DB", "\u24DC", "\u24DD", "\u24DE", "\u24DF", "\u24E0", "\u24E1",
+          "\u24E2", "\u24E3", "\u24E4", "\u24E5", "\u24E6", "\u24E7", "\u24E8",
+          "\u24E9", "\u0068\u0070\u0061", "\u0061\u0075", "\u006F\u0076",
+          "\u0070\u0061", "\u006E\u0061", "\u03BC\u0061", "\u006D\u0061",
+          "\u006B\u0061", "\u006B\u0062", "\u006D\u0062", "\u0067\u0062",
+          "\u0070\u0066", "\u006E\u0066", "\u03BC\u0066", "\u0068\u007A",
+          "\u006B\u0068\u007A", "\u006D\u0068\u007A", "\u0067\u0068\u007A",
+          "\u0074\u0068\u007A", "\u0070\u0061", "\u006B\u0070\u0061",
+          "\u006D\u0070\u0061", "\u0067\u0070\u0061", "\u0070\u0076",
+          "\u006E\u0076", "\u03BC\u0076", "\u006D\u0076", "\u006B\u0076",
+          "\u006D\u0076", "\u0070\u0077", "\u006E\u0077", "\u03BC\u0077",
+          "\u006D\u0077", "\u006B\u0077", "\u006D\u0077", "\u006B\u03C9",
+          "\u006D\u03C9", "\u0062\u0071", "\u0063\u2215\u006B\u0067",
+          "\u0063\u006F\u002E", "\u0064\u0062", "\u0067\u0079", "\u0068\u0070",
+          "\u006B\u006B", "\u006B\u006D", "\u0070\u0068", "\u0070\u0070\u006D",
+          "\u0070\u0072", "\u0073\u0076", "\u0077\u0062", "\u0066\u0066",
+          "\u0066\u0069", "\u0066\u006C", "\u0066\u0066\u0069",
+          "\u0066\u0066\u006C", "\u0073\u0074", "\u0073\u0074", "\u0574\u0576",
+          "\u0574\u0565", "\u0574\u056B", "\u057E\u0576", "\u0574\u056D",
+          "\uFF41", "\uFF42", "\uFF43", "\uFF44", "\uFF45", "\uFF46", "\uFF47",
+          "\uFF48", "\uFF49", "\uFF4A", "\uFF4B", "\uFF4C", "\uFF4D", "\uFF4E",
+          "\uFF4F", "\uFF50", "\uFF51", "\uFF52", "\uFF53", "\uFF54", "\uFF55",
+          "\uFF56", "\uFF57", "\uFF58", "\uFF59", "\uFF5A" };
       for (int count = 0; count < upperCaseArr.length; count++)
       {
-        caseMappingTable.put(upperCaseArr[count],
-            lowerCaseFoldedArr[count]);
+        CASE_MAP_TABLE.put(upperCaseArr[count], lowerCaseFoldedArr[count]);
       }
     }
 
 
 
     // Gets the mapped String.
-    private static void map(StringBuilder buffer,
-        ByteSequence sequence, boolean trim, boolean foldCase)
+    private static void map(final StringBuilder buffer,
+        final ByteSequence sequence, final boolean trim, final boolean foldCase)
     {
       final String value = sequence.toString();
       for (int i = 0; i < value.length(); i++)
       {
         final char c = value.charAt(i);
-        if (map2null.contains(c))
+        if (MAP_2_NULL.contains(c))
         {
           continue;
         }
 
-        if (map2space.contains(c))
+        if (MAP_2_SPACE.contains(c))
         {
           final int buffLen = buffer.length();
           if (trim && buffLen == 0 || buffLen > 0
               && buffer.charAt(buffLen - 1) == SPACE_CHAR)
           {
             /**
-             * Do not map this character into a space if: a . trimming
-             * is wanted and this was the first char. b. The last
-             * character was a space.
+             * Do not map this character into a space if: a . trimming is wanted
+             * and this was the first char. b. The last character was a space.
              **/
             continue;
           }
@@ -528,7 +415,7 @@
 
         if (foldCase)
         {
-          final String mapping = caseMappingTable.get(c);
+          final String mapping = CASE_MAP_TABLE.get(c);
           if (mapping != null)
           {
             buffer.append(mapping);
@@ -539,8 +426,17 @@
         buffer.append(c);
       }
     }
+
+
+
+    private MappingTable()
+    {
+      // Prevent instantiation.
+    }
   }
 
+
+
   /**
    * Defines SPACE character.
    */
@@ -552,45 +448,42 @@
   public static final boolean CASE_FOLD = true;
 
   /**
-   * Indicates whether case should not be folded during string
-   * preparation.
+   * Indicates whether case should not be folded during string preparation.
    */
   public static final boolean NO_CASE_FOLD = false;
 
   /**
-   * Indicates whether leading and trailing spaces should be trimmed
-   * during string preparation.
+   * Indicates whether leading and trailing spaces should be trimmed during
+   * string preparation.
    */
   public static final boolean TRIM = true;
 
 
 
   /**
-   * Prepares an attribute or assertion value as per stringprep
-   * algorithm defined in RFC 4518.
-   * 
+   * Prepares an attribute or assertion value as per stringprep algorithm
+   * defined in RFC 4518.
+   *
    * @param buffer
-   *          The buffer to which the prepared form of the string should
-   *          be appended.
+   *          The buffer to which the prepared form of the string should be
+   *          appended.
    * @param sequence
-   *          The {@link org.opends.sdk.ByteSequence} that
-   *          needs preparation.
+   *          The {@link org.opends.sdk.ByteSequence} that needs preparation.
    * @param trim
-   *          Indicates whether leading and trailing spaces should be
-   *          omitted from the string representation.
+   *          Indicates whether leading and trailing spaces should be omitted
+   *          from the string representation.
    * @param foldCase
    *          Indicates whether the case will be folded during mapping.
-   * @see <a href="http://www.rfc-editor.org/rfc/rfc4518.txt">
-   *      Internationalized String Preparation</a>
+   * @see <a href="http://www.rfc-editor.org/rfc/rfc4518.txt"> Internationalized
+   *      String Preparation</a>
    */
-  public static void prepareUnicode(StringBuilder buffer,
-      ByteSequence sequence, boolean trim, boolean foldCase)
+  public static void prepareUnicode(final StringBuilder buffer,
+      final ByteSequence sequence, final boolean trim, final boolean foldCase)
   {
     ensureNotNull(buffer);
     ensureNotNull(sequence);
     // Optimize in the case of purely ascii characters which is the most
-    // common
-    // case.
+    // common case.
     final int length = sequence.length();
     for (int i = 0; i < length; i++)
     {
@@ -624,9 +517,9 @@
               && buffer.charAt(buffLen - 1) == ' ')
           {
             /**
-             * Do not map this character into a space if: a . trimming
-             * is desired and this was the leading char. b. The last
-             * character was a space.
+             * Do not map this character into a space if: a . trimming is
+             * desired and this was the leading char. b. The last character was
+             * a space.
              **/
             break;
           }
@@ -674,8 +567,8 @@
 
 
   // Checks each character and replaces it with its mapping.
-  private static void map(StringBuilder buffer, ByteSequence value,
-      boolean trim, boolean foldCase)
+  private static void map(final StringBuilder buffer, final ByteSequence value,
+      final boolean trim, final boolean foldCase)
   {
     MappingTable.map(buffer, value, trim, foldCase);
   }
@@ -683,7 +576,7 @@
 
 
   // Normalizes the input string with NFKC Form.
-  private static void normalize(StringBuilder buffer)
+  private static void normalize(final StringBuilder buffer)
   {
     Platform.normalize(buffer);
   }
diff --git a/sdk/src/com/sun/opends/sdk/util/SubstringReader.java b/sdk/src/com/sun/opends/sdk/util/SubstringReader.java
index 8dec1fd..04d46d6 100644
--- a/sdk/src/com/sun/opends/sdk/util/SubstringReader.java
+++ b/sdk/src/com/sun/opends/sdk/util/SubstringReader.java
@@ -22,82 +22,159 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package com.sun.opends.sdk.util;
 
+
+
 /**
  * A sub-string reader.
  */
 public class SubstringReader
 {
-  private String source;
+  // The source string.
+  private final String source;
+  // The current position.
   private int pos;
+  // The marked position.
   private int mark;
+  // The length of the source.
+  private final int length;
 
-  public SubstringReader(String s) {
+
+
+  /**
+   * Creates an instance of SubstringReader.
+   *
+   * @param s
+   *          the source of the reader.
+   */
+  public SubstringReader(final String s)
+  {
     Validator.ensureNotNull(s);
     source = s;
+    length = s.length();
     pos = 0;
     mark = 0;
   }
 
+
+
   /**
-   * Attemps to read a substring of the specified length.
+   * Returns the source string.
    *
-   * @param length The number of characters to read.
-   * @return The substring.
+   * @return source string.
    */
-  public String read(int length)
-  {
-    String substring = source.substring(pos, pos + length);
-    pos += length;
-    return substring;
-  }
-
-  public char read()
-  {
-    return source.charAt(pos++);
-  }
-
   public String getString()
   {
     return source;
   }
 
-  public int pos()
-  {
-    return pos;
-  }
 
-  public int remaining()
-  {
-    return source.length() - pos;
-  }
 
   /**
-   * Marks the present position in the stream. Subsequent calls
-   * to reset() will reposition the stream to this point.
+   * Marks the present position in the stream. Subsequent calls to reset() will
+   * reposition the stream to this point.
    */
   public void mark()
   {
     mark = pos;
   }
 
+
+
   /**
-   * Resets the stream to the most recent mark, or to the beginning
-   * of the string if it has never been marked.
+   * Returns the current position of the reader.
+   *
+   * @return current position of the reader.
+   */
+  public int pos()
+  {
+    return pos;
+  }
+
+
+
+  /**
+   * Attemps to read a character from the current position. The caller must
+   * ensure that the source string has the data available from the current
+   * position.
+   *
+   * @return The characted at the current position.
+   * @Exception StringIndexOutOfBoundsException if there is no more data
+   *            available to read.
+   */
+  public char read()
+  {
+    if (pos >= length)
+    {
+      throw new StringIndexOutOfBoundsException();
+    }
+    return source.charAt(pos++);
+  }
+
+
+
+  /**
+   * Attemps to read a substring of the specified length from the current
+   * position. The caller must ensure that the requested length is within the
+   * bounds i.e. the requested length from the current position should not
+   * exceed the length of the source string.
+   *
+   * @param length
+   *          The number of characters to read.
+   * @return The substring.
+   * @Exception StringIndexOutOfBoundsException if the length exceeds the
+   *            allowed length.
+   */
+  public String read(final int length)
+  {
+    if (length > this.length || pos + length > this.length)
+    {
+      throw new StringIndexOutOfBoundsException();
+    }
+    final String substring = source.substring(pos, pos + length);
+    pos += length;
+    return substring;
+  }
+
+
+
+  /**
+   * Returns the remaining length of the available data.
+   *
+   * @return remaining length.
+   */
+  public int remaining()
+  {
+    return length - pos;
+  }
+
+
+
+  /**
+   * Resets the stream to the most recent mark, or to the beginning of the
+   * string if it has never been marked.
    */
   public void reset()
   {
     pos = mark;
   }
 
+
+
+  /**
+   * Skips the whitespace characters and advances the reader to the next non
+   * whitespace character.
+   *
+   * @return number of whitespace characters skipped.
+   */
   public int skipWhitespaces()
   {
     int skipped = 0;
-    while(pos < source.length() && source.charAt(pos) == ' ')
+    while (pos < length && source.charAt(pos) == ' ')
     {
       skipped++;
       pos++;
diff --git a/sdk/src/com/sun/opends/sdk/util/Validator.java b/sdk/src/com/sun/opends/sdk/util/Validator.java
index a36b5f1..11718c4 100644
--- a/sdk/src/com/sun/opends/sdk/util/Validator.java
+++ b/sdk/src/com/sun/opends/sdk/util/Validator.java
@@ -36,32 +36,31 @@
 {
 
   /**
-   * Throws a {@code NullPointerException} if the provided argument is
-   * {@code null}. This method returns a reference to its single
-   * parameter so that it can be easily used in constructors.
+   * Throws a {@code NullPointerException} if any of the provided arguments are
+   * {@code null}.
    *
-   * @param <T>
-   *          The type of {@code o1}.
-   * @param o1
-   *          The object to test.
-   * @return A reference to {@code o1}.
+   * @param objects
+   *          The objects to test.
    * @throws NullPointerException
-   *           If the provided argument is {@code null}.
+   *           If any of the provided arguments are {@code null}.
    */
-  public static <T> T ensureNotNull(T o1) throws NullPointerException
+  public static void ensureNotNull(final Object... objects)
+      throws NullPointerException
   {
-    if (o1 == null)
+    for (final Object o : objects)
     {
-      throw new NullPointerException();
+      if (o == null)
+      {
+        throw new NullPointerException();
+      }
     }
-    return o1;
   }
 
 
 
   /**
-   * Throws a {@code NullPointerException} if any of the provided
-   * arguments are {@code null}.
+   * Throws a {@code NullPointerException} if any of the provided arguments are
+   * {@code null}.
    *
    * @param o1
    *          The first object to test.
@@ -70,7 +69,7 @@
    * @throws NullPointerException
    *           If any of the provided arguments are {@code null}.
    */
-  public static void ensureNotNull(Object o1, Object o2)
+  public static void ensureNotNull(final Object o1, final Object o2)
       throws NullPointerException
   {
     if (o1 == null || o2 == null)
@@ -82,8 +81,8 @@
 
 
   /**
-   * Throws a {@code NullPointerException} if any of the provided
-   * arguments are {@code null}.
+   * Throws a {@code NullPointerException} if any of the provided arguments are
+   * {@code null}.
    *
    * @param o1
    *          The first object to test.
@@ -94,8 +93,8 @@
    * @throws NullPointerException
    *           If any of the provided arguments are {@code null}.
    */
-  public static void ensureNotNull(Object o1, Object o2, Object o3)
-      throws NullPointerException
+  public static void ensureNotNull(final Object o1, final Object o2,
+      final Object o3) throws NullPointerException
   {
     if (o1 == null || o2 == null || o3 == null)
     {
@@ -106,8 +105,8 @@
 
 
   /**
-   * Throws a {@code NullPointerException} if any of the provided
-   * arguments are {@code null}.
+   * Throws a {@code NullPointerException} if any of the provided arguments are
+   * {@code null}.
    *
    * @param o1
    *          The first object to test.
@@ -120,8 +119,8 @@
    * @throws NullPointerException
    *           If any of the provided arguments are {@code null}.
    */
-  public static void ensureNotNull(Object o1, Object o2, Object o3,
-      Object o4) throws NullPointerException
+  public static void ensureNotNull(final Object o1, final Object o2,
+      final Object o3, final Object o4) throws NullPointerException
   {
     if (o1 == null || o2 == null || o3 == null || o4 == null)
     {
@@ -132,8 +131,8 @@
 
 
   /**
-   * Throws a {@code NullPointerException} if any of the provided
-   * arguments are {@code null}.
+   * Throws a {@code NullPointerException} if any of the provided arguments are
+   * {@code null}.
    *
    * @param o1
    *          The first object to test.
@@ -148,11 +147,11 @@
    * @throws NullPointerException
    *           If any of the provided arguments are {@code null}.
    */
-  public static void ensureNotNull(Object o1, Object o2, Object o3,
-      Object o4, Object o5) throws NullPointerException
+  public static void ensureNotNull(final Object o1, final Object o2,
+      final Object o3, final Object o4, final Object o5)
+      throws NullPointerException
   {
-    if (o1 == null || o2 == null || o3 == null || o4 == null
-        || o5 == null)
+    if (o1 == null || o2 == null || o3 == null || o4 == null || o5 == null)
     {
       throw new NullPointerException();
     }
@@ -161,42 +160,41 @@
 
 
   /**
-   * Throws a {@code NullPointerException} if any of the provided
-   * arguments are {@code null}.
+   * Throws a {@code NullPointerException} if the provided argument is {@code
+   * null}. This method returns a reference to its single parameter so that it
+   * can be easily used in constructors.
    *
-   * @param objects
-   *          The objects to test.
+   * @param <T>
+   *          The type of {@code o1}.
+   * @param o1
+   *          The object to test.
+   * @return A reference to {@code o1}.
    * @throws NullPointerException
-   *           If any of the provided arguments are {@code null}.
+   *           If the provided argument is {@code null}.
    */
-  public static void ensureNotNull(Object... objects)
-      throws NullPointerException
+  public static <T> T ensureNotNull(final T o1) throws NullPointerException
   {
-    for (Object o : objects)
+    if (o1 == null)
     {
-      if (o == null)
-      {
-        throw new NullPointerException();
-      }
+      throw new NullPointerException();
     }
+    return o1;
   }
 
 
 
   /**
-   * Throws an {@code IllegalArgumentException} if the provided
-   * condition is {@code false}.
+   * Throws an {@code IllegalArgumentException} if the provided condition is
+   * {@code false}.
    *
    * @param condition
-   *          The condition, which must be {@code true} to avoid an
-   *          exception.
+   *          The condition, which must be {@code true} to avoid an exception.
    * @param message
-   *          The error message to include in the exception if it is
-   *          thrown.
+   *          The error message to include in the exception if it is thrown.
    * @throws IllegalArgumentException
    *           If {@code condition} was {@code false}.
    */
-  public static void ensureTrue(boolean condition, String message)
+  public static void ensureTrue(final boolean condition, final String message)
       throws IllegalArgumentException
   {
     if (!condition)
diff --git a/sdk/src/org/opends/sdk/sasl/package-info.java b/sdk/src/com/sun/opends/sdk/util/package-info.java
old mode 100755
new mode 100644
similarity index 91%
rename from sdk/src/org/opends/sdk/sasl/package-info.java
rename to sdk/src/com/sun/opends/sdk/util/package-info.java
index 6683fa9..25ebe0f
--- a/sdk/src/org/opends/sdk/sasl/package-info.java
+++ b/sdk/src/com/sun/opends/sdk/util/package-info.java
@@ -26,6 +26,9 @@
  */
 
 /**
- * Classes and interfaces for common LDAP SASL Bind requests.
+ * Classes providing utility functionality.
  */
-package org.opends.sdk.sasl;
+package com.sun.opends.sdk.util;
+
+
+
diff --git a/sdk/src/org/opends/sdk/AVA.java b/sdk/src/org/opends/sdk/AVA.java
new file mode 100644
index 0000000..b6868ce
--- /dev/null
+++ b/sdk/src/org/opends/sdk/AVA.java
@@ -0,0 +1,954 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.util.StaticUtils.*;
+
+import org.opends.sdk.schema.*;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.SubstringReader;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * An attribute value assertion (AVA) as defined in RFC 4512 section 2.3
+ * consists of an attribute description with zero options and an attribute
+ * value.
+ * <p>
+ * The following are examples of string representations of AVAs:
+ *
+ * <pre>
+ * uid=12345
+ * ou=Engineering
+ * cn=Kurt Zeilenga
+ * </pre>
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4512#section-2.3">RFC 4512 -
+ *      Lightweight Directory Access Protocol (LDAP): Directory Information
+ *      Models </a>
+ */
+public final class AVA implements Comparable<AVA>
+{
+  /**
+   * Parses the provided LDAP string representation of an AVA using the default
+   * schema.
+   *
+   * @param ava
+   *          The LDAP string representation of an AVA.
+   * @return The parsed RDN.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code ava} is not a valid LDAP string representation of a
+   *           AVA.
+   * @throws NullPointerException
+   *           If {@code ava} was {@code null}.
+   */
+  public static AVA valueOf(final String ava)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    return valueOf(ava, Schema.getDefaultSchema());
+  }
+
+
+
+  /**
+   * Parses the provided LDAP string representation of an AVA using the provided
+   * schema.
+   *
+   * @param ava
+   *          The LDAP string representation of a AVA.
+   * @param schema
+   *          The schema to use when parsing the AVA.
+   * @return The parsed AVA.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code ava} is not a valid LDAP string representation of a
+   *           AVA.
+   * @throws NullPointerException
+   *           If {@code ava} or {@code schema} was {@code null}.
+   */
+  public static AVA valueOf(final String ava, final Schema schema)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    final SubstringReader reader = new SubstringReader(ava);
+    try
+    {
+      return decode(reader, schema);
+    }
+    catch (final UnknownSchemaElementException e)
+    {
+      final LocalizableMessage message = ERR_RDN_TYPE_NOT_FOUND.get(ava, e
+          .getMessageObject());
+      throw new LocalizedIllegalArgumentException(message);
+    }
+  }
+
+
+
+  static AVA decode(final SubstringReader reader, final Schema schema)
+      throws LocalizedIllegalArgumentException, UnknownSchemaElementException
+  {
+    // Skip over any spaces at the beginning.
+    reader.skipWhitespaces();
+
+    final AttributeType attribute = readAttributeName(reader, schema);
+
+    // Make sure that we're not at the end of the DN string because
+    // that would be invalid.
+    if (reader.remaining() == 0)
+    {
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME
+          .get(reader.getString(), attribute.getNameOrOID());
+      throw new LocalizedIllegalArgumentException(message);
+    }
+
+    // Skip over any spaces if we have.
+    reader.skipWhitespaces();
+
+    // The next character must be an equal sign. If it is not, then
+    // that's an error.
+    char c;
+    if ((c = reader.read()) != '=')
+    {
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_NO_EQUAL.get(reader
+          .getString(), attribute.getNameOrOID(), c);
+      throw new LocalizedIllegalArgumentException(message);
+    }
+
+    // Skip over any spaces after the equal sign.
+    reader.skipWhitespaces();
+
+    // Parse the value for this RDN component.
+    final ByteString value = readAttributeValue(reader);
+
+    return new AVA(attribute, value);
+  }
+
+
+
+  private static void appendHexChars(final SubstringReader reader,
+      final StringBuilder valueBuffer, final StringBuilder hexBuffer)
+      throws DecodeException
+  {
+    final int length = hexBuffer.length();
+    if (length == 0)
+    {
+      return;
+    }
+
+    if ((length % 2) == 1)
+    {
+      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_LENGTH
+          .get(hexBuffer);
+      DecodeException.error(message);
+    }
+
+    int pos = 0;
+    final int arrayLength = (length / 2);
+    final byte[] hexArray = new byte[arrayLength];
+    for (int i = 0; i < arrayLength; i++)
+    {
+      switch (hexBuffer.charAt(pos++))
+      {
+      case '0':
+        hexArray[i] = 0x00;
+        break;
+      case '1':
+        hexArray[i] = 0x10;
+        break;
+      case '2':
+        hexArray[i] = 0x20;
+        break;
+      case '3':
+        hexArray[i] = 0x30;
+        break;
+      case '4':
+        hexArray[i] = 0x40;
+        break;
+      case '5':
+        hexArray[i] = 0x50;
+        break;
+      case '6':
+        hexArray[i] = 0x60;
+        break;
+      case '7':
+        hexArray[i] = 0x70;
+        break;
+      case '8':
+        hexArray[i] = (byte) 0x80;
+        break;
+      case '9':
+        hexArray[i] = (byte) 0x90;
+        break;
+      case 'A':
+      case 'a':
+        hexArray[i] = (byte) 0xA0;
+        break;
+      case 'B':
+      case 'b':
+        hexArray[i] = (byte) 0xB0;
+        break;
+      case 'C':
+      case 'c':
+        hexArray[i] = (byte) 0xC0;
+        break;
+      case 'D':
+      case 'd':
+        hexArray[i] = (byte) 0xD0;
+        break;
+      case 'E':
+      case 'e':
+        hexArray[i] = (byte) 0xE0;
+        break;
+      case 'F':
+      case 'f':
+        hexArray[i] = (byte) 0xF0;
+        break;
+      default:
+        final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER
+            .get(hexBuffer, hexBuffer.charAt(pos - 1));
+        throw DecodeException.error(message);
+      }
+
+      switch (hexBuffer.charAt(pos++))
+      {
+      case '0':
+        // No action required.
+        break;
+      case '1':
+        hexArray[i] |= 0x01;
+        break;
+      case '2':
+        hexArray[i] |= 0x02;
+        break;
+      case '3':
+        hexArray[i] |= 0x03;
+        break;
+      case '4':
+        hexArray[i] |= 0x04;
+        break;
+      case '5':
+        hexArray[i] |= 0x05;
+        break;
+      case '6':
+        hexArray[i] |= 0x06;
+        break;
+      case '7':
+        hexArray[i] |= 0x07;
+        break;
+      case '8':
+        hexArray[i] |= 0x08;
+        break;
+      case '9':
+        hexArray[i] |= 0x09;
+        break;
+      case 'A':
+      case 'a':
+        hexArray[i] |= 0x0A;
+        break;
+      case 'B':
+      case 'b':
+        hexArray[i] |= 0x0B;
+        break;
+      case 'C':
+      case 'c':
+        hexArray[i] |= 0x0C;
+        break;
+      case 'D':
+      case 'd':
+        hexArray[i] |= 0x0D;
+        break;
+      case 'E':
+      case 'e':
+        hexArray[i] |= 0x0E;
+        break;
+      case 'F':
+      case 'f':
+        hexArray[i] |= 0x0F;
+        break;
+      default:
+        final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER
+            .get(hexBuffer, hexBuffer.charAt(pos - 1));
+        throw DecodeException.error(message);
+      }
+    }
+    try
+    {
+      valueBuffer.append(new String(hexArray, "UTF-8"));
+    }
+    catch (final Exception e)
+    {
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ATTR_VALUE_DECODE_FAILURE
+          .get(reader.getString(), String.valueOf(e));
+      throw DecodeException.error(message);
+    }
+    // Clean up the hex buffer.
+    hexBuffer.setLength(0);
+  }
+
+
+
+  private static ByteString delimitAndEvaluateEscape(
+      final SubstringReader reader) throws DecodeException
+  {
+    char c = '\u0000';
+    final StringBuilder valueBuffer = new StringBuilder();
+    final StringBuilder hexBuffer = new StringBuilder();
+    reader.skipWhitespaces();
+
+    boolean escaped = false;
+    while (reader.remaining() > 0)
+    {
+      c = reader.read();
+      if (escaped)
+      {
+        // This character is escaped.
+        if (isHexDigit(c))
+        {
+          // Unicode characters.
+          if (!(reader.remaining() > 0))
+          {
+            final LocalizableMessage msg = ERR_ATTR_SYNTAX_DN_ESCAPED_HEX_VALUE_INVALID
+                .get(reader.getString());
+            DecodeException.error(msg);
+          }
+          // Check the next byte for hex.
+          final char c2 = reader.read();
+          if (isHexDigit(c2))
+          {
+            hexBuffer.append(c);
+            hexBuffer.append(c2);
+            // We may be at the end.
+            if (reader.remaining() == 0)
+            {
+              appendHexChars(reader, valueBuffer, hexBuffer);
+            }
+          }
+          else
+          {
+            final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ESCAPED_HEX_VALUE_INVALID
+                .get(reader.getString());
+            DecodeException.error(message);
+          }
+        }
+        else
+        {
+          appendHexChars(reader, valueBuffer, hexBuffer);
+          valueBuffer.append(c);
+        }
+        escaped = false;
+      }
+      else if (c == 0x5C) // The backslash character
+      {
+        // We found an escape.
+        escaped = true;
+      }
+      else
+      {
+        // Check for delimited chars.
+        if (c == '+' || c == ',' || c == ';')
+        {
+          reader.reset();
+          // Return what we have got here so far.
+          appendHexChars(reader, valueBuffer, hexBuffer);
+          return ByteString.valueOf(valueBuffer.toString());
+        }
+        // It is definitely not a delimiter at this point.
+        appendHexChars(reader, valueBuffer, hexBuffer);
+        valueBuffer.append(c);
+        // reader.mark();
+      }
+      reader.mark();
+    }
+
+    reader.reset();
+    return ByteString.valueOf(valueBuffer.toString());
+  }
+
+
+
+  private static AttributeType readAttributeName(final SubstringReader reader,
+      final Schema schema) throws LocalizedIllegalArgumentException,
+      UnknownSchemaElementException
+  {
+    int length = 1;
+    reader.mark();
+
+    // The next character must be either numeric (for an OID) or
+    // alphabetic (for an attribute description).
+    char c = reader.read();
+    if (isDigit(c))
+    {
+      boolean lastWasPeriod = false;
+      while (reader.remaining() > 0 && (c = reader.read()) != '=')
+      {
+        if (c == '.')
+        {
+          if (lastWasPeriod)
+          {
+            final LocalizableMessage message = ERR_ATTR_SYNTAX_OID_CONSECUTIVE_PERIODS
+                .get(reader.getString(), reader.pos() - 1);
+            throw new LocalizedIllegalArgumentException(message);
+          }
+          else
+          {
+            lastWasPeriod = true;
+          }
+        }
+        else if (!isDigit(c))
+        {
+          // This must have been an illegal character.
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_OID_ILLEGAL_CHARACTER
+              .get(reader.getString(), reader.pos() - 1);
+          throw new LocalizedIllegalArgumentException(message);
+        }
+        else
+        {
+          lastWasPeriod = false;
+        }
+        length++;
+      }
+    }
+    else if (isAlpha(c))
+    {
+      // This must be an attribute description. In this case, we will
+      // only accept alphabetic characters, numeric digits, and the hyphen.
+      while (reader.remaining() > 0)
+      {
+        c = reader.read();
+        if (length == 0 && !isAlpha(c))
+        {
+          // This is an illegal character.
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR
+              .get(reader.getString(), c, reader.pos() - 1);
+          throw new LocalizedIllegalArgumentException(message);
+        }
+
+        if (c == '=')
+        {
+          // End of the attribute.
+          break;
+        }
+        else if (c == ' ')
+        {
+          // Got a whitespace.It MUST be the end of the attribute
+          // Make sure that the next non-whitespace character is '='.
+          reader.skipWhitespaces();
+          // Read back the next char.
+          c = reader.read();
+          if (c == '=')
+          {
+            break;
+          }
+          else
+          {
+            // This is an illegal character.
+            final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR
+                .get(reader.getString(), c, reader.pos() - 1);
+            throw new LocalizedIllegalArgumentException(message);
+          }
+        }
+        else if (!isAlpha(c) && !isDigit(c) && c != '-')
+        {
+          // This is an illegal character.
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR
+              .get(reader.getString(), c, reader.pos() - 1);
+          throw new LocalizedIllegalArgumentException(message);
+        }
+
+        length++;
+      }
+    }
+    else
+    {
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR
+          .get(reader.getString(), c, reader.pos() - 1);
+      throw new LocalizedIllegalArgumentException(message);
+    }
+
+    reader.reset();
+
+    // Return the position of the first non-space character after the
+    // token.
+
+    return schema.getAttributeType(reader.read(length));
+  }
+
+
+
+  private static ByteString readAttributeValue(final SubstringReader reader)
+      throws LocalizedIllegalArgumentException
+  {
+    // All leading spaces have already been stripped so we can start
+    // reading the value. However, it may be empty so check for that.
+    if (reader.remaining() == 0)
+    {
+      return ByteString.empty();
+    }
+
+    reader.mark();
+
+    // Look at the first character. If it is an octothorpe (#), then
+    // that means that the value should be a hex string.
+    char c = reader.read();
+    int length = 0;
+    if (c == '#')
+    {
+      // The first two characters must be hex characters.
+      reader.mark();
+      if (reader.remaining() < 2)
+      {
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_HEX_VALUE_TOO_SHORT
+            .get(reader.getString());
+        throw new LocalizedIllegalArgumentException(message);
+      }
+
+      for (int i = 0; i < 2; i++)
+      {
+        c = reader.read();
+        if (isHexDigit(c))
+        {
+          length++;
+        }
+        else
+        {
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT
+              .get(reader.getString(), c);
+          throw new LocalizedIllegalArgumentException(message);
+        }
+      }
+
+      // The rest of the value must be a multiple of two hex
+      // characters. The end of the value may be designated by the
+      // end of the DN, a comma or semicolon, or a space.
+      while (reader.remaining() > 0)
+      {
+        c = reader.read();
+        if (isHexDigit(c))
+        {
+          length++;
+
+          if (reader.remaining() > 0)
+          {
+            c = reader.read();
+            if (isHexDigit(c))
+            {
+              length++;
+            }
+            else
+            {
+              final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT
+                  .get(reader.getString(), c);
+              throw new LocalizedIllegalArgumentException(message);
+            }
+          }
+          else
+          {
+            final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_HEX_VALUE_TOO_SHORT
+                .get(reader.getString());
+            throw new LocalizedIllegalArgumentException(message);
+          }
+        }
+        else if ((c == ' ') || (c == ',') || (c == ';'))
+        {
+          // This denotes the end of the value.
+          break;
+        }
+        else
+        {
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT
+              .get(reader.getString(), c);
+          throw new LocalizedIllegalArgumentException(message);
+        }
+      }
+
+      // At this point, we should have a valid hex string. Convert it
+      // to a byte array and set that as the value of the provided
+      // octet string.
+      try
+      {
+        reader.reset();
+        return ByteString.wrap(hexStringToByteArray(reader.read(length)));
+      }
+      catch (final Exception e)
+      {
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ATTR_VALUE_DECODE_FAILURE
+            .get(reader.getString(), String.valueOf(e));
+        throw new LocalizedIllegalArgumentException(message);
+      }
+    }
+
+    // If the first character is a quotation mark, then the value
+    // should continue until the corresponding closing quotation mark.
+    else if (c == '"')
+    {
+      reader.mark();
+      while (true)
+      {
+        if (reader.remaining() <= 0)
+        {
+          // We hit the end of the AVA before the closing quote.
+          // That's an error.
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_UNMATCHED_QUOTE
+              .get(reader.getString());
+          throw new LocalizedIllegalArgumentException(message);
+        }
+
+        if (reader.read() == '"')
+        {
+          // This is the end of the value.
+          break;
+        }
+        length++;
+      }
+      reader.reset();
+      final ByteString retString = ByteString.valueOf(reader.read(length));
+      reader.read();
+      return retString;
+    }
+
+    // Otherwise, use general parsing to find the end of the value.
+    else
+    {
+      reader.reset();
+      ByteString bytes;
+      try
+      {
+        bytes = delimitAndEvaluateEscape(reader);
+      }
+      catch (final DecodeException e)
+      {
+        throw new LocalizedIllegalArgumentException(e.getMessageObject());
+      }
+      if (bytes.length() == 0)
+      {
+        // We don't allow an empty attribute value.
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_INVALID_REQUIRES_ESCAPE_CHAR
+            .get(reader.getString(), reader.pos());
+        throw new LocalizedIllegalArgumentException(message);
+      }
+      return bytes;
+    }
+  }
+
+
+
+  private final AttributeType attributeType;
+
+  private final ByteString attributeValue;
+
+
+
+  /**
+   * Creates a new attribute value assertion (AVA) using the provided attribute
+   * type and value.
+   *
+   * @param attributeType
+   *          The attribute type.
+   * @param attributeValue
+   *          The attribute value.
+   * @throws NullPointerException
+   *           If {@code attributeType} or {@code attributeValue} was {@code
+   *           null}.
+   */
+  public AVA(final AttributeType attributeType, final ByteString attributeValue)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(attributeType, attributeValue);
+
+    this.attributeType = attributeType;
+    this.attributeValue = attributeValue;
+  }
+
+
+
+  /**
+   * Creates a new attribute value assertion (AVA) using the provided attribute
+   * type and value decoded using the default schema.
+   * <p>
+   * If {@code attributeValue} is not an instance of {@code ByteString} then it
+   * will be converted using the {@link ByteString#valueOf(Object)} method.
+   *
+   * @param attributeType
+   *          The attribute type.
+   * @param attributeValue
+   *          The attribute value.
+   * @throws UnknownSchemaElementException
+   *           If {@code attributeType} was not found in the default schema.
+   * @throws NullPointerException
+   *           If {@code attributeType} or {@code attributeValue} was {@code
+   *           null}.
+   */
+  public AVA(final String attributeType, final Object attributeValue)
+      throws UnknownSchemaElementException, NullPointerException
+  {
+    Validator.ensureNotNull(attributeType, attributeValue);
+
+    this.attributeType = Schema.getDefaultSchema().getAttributeType(
+        attributeType);
+    this.attributeValue = ByteString.valueOf(attributeValue);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public int compareTo(final AVA ava)
+  {
+    int result = attributeType.compareTo(ava.attributeType);
+    if (result != 0)
+    {
+      return result > 0 ? 1 : -1;
+    }
+    final ByteString normalizedValue = getNormalizeValue();
+    final MatchingRule rule = attributeType.getOrderingMatchingRule();
+    try
+    {
+      if (rule != null)
+      {
+        // Check equality assertion first.
+        final Assertion lteAssertion = rule
+            .getLessOrEqualAssertion(ava.attributeValue);
+        final ConditionResult lteResult = lteAssertion.matches(normalizedValue);
+        final Assertion gteAssertion = rule
+            .getGreaterOrEqualAssertion(ava.attributeValue);
+        final ConditionResult gteResult = gteAssertion.matches(normalizedValue);
+
+        if (lteResult.equals(gteResult))
+        {
+          // it is equal to the assertion value.
+          return 0;
+        }
+        else if (lteResult == ConditionResult.TRUE)
+        {
+          return -1;
+        }
+        else
+        {
+          return 1;
+        }
+      }
+    }
+    catch (final DecodeException de)
+    {
+      // use the bytestring comparison as default.
+    }
+
+    if (result == 0)
+    {
+      final ByteString nv1 = normalizedValue;
+      final ByteString nv2 = ava.getNormalizeValue();
+      result = nv1.compareTo(nv2);
+    }
+
+    return result;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean equals(final Object obj)
+  {
+    if (this == obj)
+    {
+      return true;
+    }
+    else if (obj instanceof AVA)
+    {
+      return compareTo((AVA) obj) == 0;
+    }
+    else
+    {
+      return false;
+    }
+  }
+
+
+
+  /**
+   * Returns the attribute type associated with this AVA.
+   *
+   * @return The attribute type associated with this AVA.
+   */
+  public AttributeType getAttributeType()
+  {
+    return attributeType;
+  }
+
+
+
+  /**
+   * Returns the attribute value associated with this AVA.
+   *
+   * @return The attribute value associated with this AVA.
+   */
+  public ByteString getAttributeValue()
+  {
+    return attributeValue;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int hashCode()
+  {
+    return attributeType.hashCode() * 31 + getNormalizeValue().hashCode();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    return toString(builder).toString();
+  }
+
+
+
+  StringBuilder toNormalizedString(final StringBuilder builder)
+  {
+    return toString(builder, true);
+  }
+
+
+
+  StringBuilder toString(final StringBuilder builder)
+  {
+    return toString(builder, false);
+  }
+
+
+
+  private ByteString getNormalizeValue()
+  {
+    final MatchingRule matchingRule = attributeType.getEqualityMatchingRule();
+    if (matchingRule != null)
+    {
+      try
+      {
+        return matchingRule.normalizeAttributeValue(attributeValue);
+      }
+      catch (final DecodeException de)
+      {
+        // Ignore - we'll drop back to the user provided value.
+      }
+    }
+    return attributeValue;
+  }
+
+
+
+  private StringBuilder toString(final StringBuilder builder,
+      final boolean normalize)
+  {
+    final ByteString value = normalize ? getNormalizeValue() : attributeValue;
+
+    if (!attributeType.getNames().iterator().hasNext())
+    {
+      builder.append(attributeType.getOID());
+      builder.append("=#");
+      StaticUtils.toHex(value, builder);
+    }
+    else
+    {
+      final String name = attributeType.getNameOrOID();
+      if (normalize)
+      {
+        // Normalizing.
+        StaticUtils.toLowerCase(name, builder);
+      }
+      else
+      {
+        builder.append(name);
+      }
+
+      builder.append("=");
+
+      final Syntax syntax = attributeType.getSyntax();
+      if (!syntax.isHumanReadable())
+      {
+        builder.append("#");
+        StaticUtils.toHex(value, builder);
+      }
+      else
+      {
+        final String str = value.toString();
+        if (str.length() == 0)
+        {
+          return builder;
+        }
+        char c = str.charAt(0);
+        int startPos = 0;
+        if ((c == ' ') || (c == '#'))
+        {
+          builder.append('\\');
+          builder.append(c);
+          startPos = 1;
+        }
+        final int length = str.length();
+        for (int si = startPos; si < length; si++)
+        {
+          c = str.charAt(si);
+          if (c < ' ')
+          {
+            for (final byte b : getBytes(String.valueOf(c)))
+            {
+              builder.append('\\');
+              builder.append(StaticUtils.byteToLowerHex(b));
+            }
+          }
+          else
+          {
+            if ((c == ' ' && si == length - 1)
+                || (c == '"' || c == '+' || c == ',' || c == ';' || c == '<'
+                    || c == '=' || c == '>' || c == '\\' || c == '\u0000'))
+            {
+              builder.append('\\');
+            }
+            builder.append(c);
+          }
+        }
+      }
+    }
+    return builder;
+  }
+}
diff --git a/sdk/src/org/opends/sdk/AbstractAsynchronousConnection.java b/sdk/src/org/opends/sdk/AbstractAsynchronousConnection.java
index 65d9b30..0f2ae0d 100644
--- a/sdk/src/org/opends/sdk/AbstractAsynchronousConnection.java
+++ b/sdk/src/org/opends/sdk/AbstractAsynchronousConnection.java
@@ -29,18 +29,16 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_NO_SEARCH_RESULT_ENTRIES;
+import static com.sun.opends.sdk.messages.Messages.ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES;
+import static com.sun.opends.sdk.messages.Messages.ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES;
 
 import java.util.Collection;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 
-import org.opends.sdk.requests.Requests;
-import org.opends.sdk.requests.SearchRequest;
-import org.opends.sdk.responses.Responses;
-import org.opends.sdk.responses.Result;
-import org.opends.sdk.responses.SearchResultEntry;
-import org.opends.sdk.responses.SearchResultReference;
+import org.opends.sdk.requests.*;
+import org.opends.sdk.responses.*;
 import org.opends.sdk.schema.Schema;
 
 
@@ -71,14 +69,14 @@
 
 
     private SingleEntryFuture(
-        ResultHandler<? super SearchResultEntry> handler)
+        final ResultHandler<? super SearchResultEntry> handler)
     {
       this.handler = handler;
     }
 
 
 
-    public boolean cancel(boolean mayInterruptIfRunning)
+    public boolean cancel(final boolean mayInterruptIfRunning)
     {
       return future.cancel(mayInterruptIfRunning);
     }
@@ -94,9 +92,8 @@
 
 
 
-    public SearchResultEntry get(long timeout, TimeUnit unit)
-        throws ErrorResultException, TimeoutException,
-        InterruptedException
+    public SearchResultEntry get(final long timeout, final TimeUnit unit)
+        throws ErrorResultException, TimeoutException, InterruptedException
     {
       future.get(timeout, unit);
       return get0();
@@ -104,46 +101,6 @@
 
 
 
-    private SearchResultEntry get0() throws ErrorResultException
-    {
-      if (entryCount == 0)
-      {
-        // Did not find any entries.
-        Result result = Responses.newResult(
-            ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
-            .setDiagnosticMessage(
-                ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
-        throw ErrorResultException.wrap(result);
-      }
-      else if (entryCount > 1)
-      {
-        // Got more entries than expected.
-        Result result = Responses.newResult(
-            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
-            .setDiagnosticMessage(
-                ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(entryCount)
-                    .toString());
-        throw ErrorResultException.wrap(result);
-      }
-      else if (firstReference != null)
-      {
-        // Got an unexpected search result reference.
-        Result result = Responses.newResult(
-            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
-            .setDiagnosticMessage(
-                ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get(
-                    firstReference.getURIs().iterator().next())
-                    .toString());
-        throw ErrorResultException.wrap(result);
-      }
-      else
-      {
-        return firstEntry;
-      }
-    }
-
-
-
     public int getRequestID()
     {
       return future.getRequestID();
@@ -151,18 +108,19 @@
 
 
 
-    public void handleEntry(SearchResultEntry entry)
+    public boolean handleEntry(final SearchResultEntry entry)
     {
       if (firstEntry == null)
       {
         firstEntry = entry;
       }
       entryCount++;
+      return true;
     }
 
 
 
-    public void handleErrorResult(ErrorResultException error)
+    public void handleErrorResult(final ErrorResultException error)
     {
       if (handler != null)
       {
@@ -172,17 +130,18 @@
 
 
 
-    public void handleReference(SearchResultReference reference)
+    public boolean handleReference(final SearchResultReference reference)
     {
       if (firstReference == null)
       {
         firstReference = reference;
       }
+      return true;
     }
 
 
 
-    public void handleResult(Result result)
+    public void handleResult(final Result result)
     {
       if (handler != null)
       {
@@ -190,7 +149,7 @@
         {
           handler.handleResult(get0());
         }
-        catch (ErrorResultException e)
+        catch (final ErrorResultException e)
         {
           handler.handleErrorResult(e);
         }
@@ -213,7 +172,44 @@
 
 
 
-    private void setResultFuture(FutureResult<Result> future)
+    private SearchResultEntry get0() throws ErrorResultException
+    {
+      if (entryCount == 0)
+      {
+        // Did not find any entries.
+        final Result result = Responses.newResult(
+            ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED).setDiagnosticMessage(
+            ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
+        throw ErrorResultException.wrap(result);
+      }
+      else if (entryCount > 1)
+      {
+        // Got more entries than expected.
+        final Result result = Responses
+            .newResult(ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
+            .setDiagnosticMessage(
+                ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(entryCount).toString());
+        throw ErrorResultException.wrap(result);
+      }
+      else if (firstReference != null)
+      {
+        // Got an unexpected search result reference.
+        final Result result = Responses.newResult(
+            ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
+            .setDiagnosticMessage(
+                ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get(
+                    firstReference.getURIs().iterator().next()).toString());
+        throw ErrorResultException.wrap(result);
+      }
+      else
+      {
+        return firstEntry;
+      }
+    }
+
+
+
+    private void setResultFuture(final FutureResult<Result> future)
     {
       this.future = future;
     }
@@ -234,6 +230,32 @@
   /**
    * {@inheritDoc}
    */
+  public FutureResult<Result> add(final AddRequest request,
+      final ResultHandler<Result> handler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    return add(request, handler, null);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<BindResult> bind(final BindRequest request,
+      final ResultHandler<? super BindResult> handler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    return bind(request, handler, null);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
   public void close()
   {
     close(Requests.newUnbindRequest(), null);
@@ -244,15 +266,90 @@
   /**
    * {@inheritDoc}
    */
-  public FutureResult<SearchResultEntry> readEntry(DN name,
-      Collection<String> attributeDescriptions,
-      ResultHandler<? super SearchResultEntry> handler)
+  public FutureResult<CompareResult> compare(final CompareRequest request,
+      final ResultHandler<? super CompareResult> handler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException
   {
-    SearchRequest request = Requests.newSearchRequest(name,
-        SearchScope.BASE_OBJECT, Filter.getObjectClassPresentFilter())
-        .addAttribute(attributeDescriptions);
+    return compare(request, handler, null);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Result> delete(final DeleteRequest request,
+      final ResultHandler<Result> handler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    return delete(request, handler, null);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+      final ExtendedRequest<R> request, final ResultHandler<? super R> handler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    return extendedRequest(request, handler, null);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Connection getSynchronousConnection()
+  {
+    return new SynchronousConnection(this);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Result> modify(final ModifyRequest request,
+      final ResultHandler<Result> handler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    return modify(request, handler, null);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+      final ResultHandler<Result> handler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    return modifyDN(request, handler, null);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<SearchResultEntry> readEntry(final DN name,
+      final Collection<String> attributeDescriptions,
+      final ResultHandler<? super SearchResultEntry> handler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final SearchRequest request = Requests.newSearchRequest(name,
+        SearchScope.BASE_OBJECT, Filter.getObjectClassPresentFilter());
+    request.getAttributes().addAll(attributeDescriptions);
     return searchSingleEntry(request, handler);
   }
 
@@ -261,8 +358,7 @@
   /**
    * {@inheritDoc}
    */
-  public FutureResult<RootDSE> readRootDSE(
-      ResultHandler<RootDSE> handler)
+  public FutureResult<RootDSE> readRootDSE(final ResultHandler<RootDSE> handler)
       throws UnsupportedOperationException, IllegalStateException
   {
     return RootDSE.readRootDSE(this, handler);
@@ -273,8 +369,8 @@
   /**
    * {@inheritDoc}
    */
-  public FutureResult<Schema> readSchema(DN name,
-      ResultHandler<Schema> handler)
+  public FutureResult<Schema> readSchema(final DN name,
+      final ResultHandler<Schema> handler)
       throws UnsupportedOperationException, IllegalStateException
   {
     return Schema.readSchema(this, name, handler);
@@ -285,8 +381,8 @@
   /**
    * {@inheritDoc}
    */
-  public FutureResult<Schema> readSchemaForEntry(DN name,
-      ResultHandler<Schema> handler)
+  public FutureResult<Schema> readSchemaForEntry(final DN name,
+      final ResultHandler<Schema> handler)
       throws UnsupportedOperationException, IllegalStateException
   {
     return Schema.readSchema(this, name, handler);
@@ -297,9 +393,23 @@
   /**
    * {@inheritDoc}
    */
+  public FutureResult<Result> search(final SearchRequest request,
+      final ResultHandler<Result> resultHandler,
+      final SearchResultHandler searchResulthandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    return search(request, resultHandler, searchResulthandler, null);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
   public FutureResult<SearchResultEntry> searchSingleEntry(
-      SearchRequest request,
-      ResultHandler<? super SearchResultEntry> handler)
+      final SearchRequest request,
+      final ResultHandler<? super SearchResultEntry> handler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException
   {
@@ -309,5 +419,4 @@
     innerFuture.setResultFuture(future);
     return innerFuture;
   }
-
 }
diff --git a/sdk/src/org/opends/sdk/AbstractAttribute.java b/sdk/src/org/opends/sdk/AbstractAttribute.java
index 47f1a1f..7d8ecfa 100644
--- a/sdk/src/org/opends/sdk/AbstractAttribute.java
+++ b/sdk/src/org/opends/sdk/AbstractAttribute.java
@@ -39,29 +39,28 @@
 
 
 /**
- * This class provides a skeletal implementation of the {@code
- * Attribute} interface, to minimize the effort required to implement
- * this interface.
+ * This class provides a skeletal implementation of the {@code Attribute}
+ * interface, to minimize the effort required to implement this interface.
  */
 public abstract class AbstractAttribute extends AbstractSet<ByteString>
     implements Attribute
 {
 
   /**
-   * Returns {@code true} if {@code object} is an attribute which is
-   * equal to {@code attribute}. Two attributes are considered equal if
-   * their attribute descriptions are equal, they both have the same
-   * number of attribute values, and every attribute value contained in
-   * the first attribute is also contained in the second attribute.
+   * Returns {@code true} if {@code object} is an attribute which is equal to
+   * {@code attribute}. Two attributes are considered equal if their attribute
+   * descriptions are equal, they both have the same number of attribute values,
+   * and every attribute value contained in the first attribute is also
+   * contained in the second attribute.
    *
    * @param attribute
    *          The attribute to be tested for equality.
    * @param object
    *          The object to be tested for equality with the attribute.
-   * @return {@code true} if {@code object} is an attribute which is
-   *         equal to {@code attribute}, or {@code false} if not.
+   * @return {@code true} if {@code object} is an attribute which is equal to
+   *         {@code attribute}, or {@code false} if not.
    */
-  static boolean equals(Attribute attribute, Object object)
+  static boolean equals(final Attribute attribute, final Object object)
   {
     if (attribute == object)
     {
@@ -73,7 +72,7 @@
       return false;
     }
 
-    Attribute other = (Attribute) object;
+    final Attribute other = (Attribute) object;
     if (!attribute.getAttributeDescription().equals(
         other.getAttributeDescription()))
     {
@@ -92,18 +91,18 @@
 
 
   /**
-   * Returns the hash code for {@code attribute}. It will be calculated
-   * as the sum of the hash codes of the attribute description and all
-   * of the attribute values.
+   * Returns the hash code for {@code attribute}. It will be calculated as the
+   * sum of the hash codes of the attribute description and all of the attribute
+   * values.
    *
    * @param attribute
    *          The attribute whose hash code should be calculated.
    * @return The hash code for {@code attribute}.
    */
-  static int hashCode(Attribute attribute)
+  static int hashCode(final Attribute attribute)
   {
     int hashCode = attribute.getAttributeDescription().hashCode();
-    for (ByteString value : attribute)
+    for (final ByteString value : attribute)
     {
       hashCode += normalizeValue(attribute, value).hashCode();
     }
@@ -113,30 +112,30 @@
 
 
   /**
-   * Returns the normalized form of {@code value} normalized using
-   * {@code attribute}'s equality matching rule.
+   * Returns the normalized form of {@code value} normalized using {@code
+   * attribute}'s equality matching rule.
    *
    * @param attribute
-   *          The attribute whose equality matching rule should be used
-   *          for normalization.
+   *          The attribute whose equality matching rule should be used for
+   *          normalization.
    * @param value
    *          The attribute value to be normalized.
-   * @return The normalized form of {@code value} normalized using
-   *         {@code attribute}'s equality matching rule.
+   * @return The normalized form of {@code value} normalized using {@code
+   *         attribute}'s equality matching rule.
    */
-  static ByteString normalizeValue(Attribute attribute, ByteString value)
+  static ByteString normalizeValue(final Attribute attribute,
+      final ByteString value)
   {
-    AttributeDescription attributeDescription = attribute
+    final AttributeDescription attributeDescription = attribute
         .getAttributeDescription();
-    AttributeType attributeType = attributeDescription
-        .getAttributeType();
-    MatchingRule matchingRule = attributeType.getEqualityMatchingRule();
+    final AttributeType attributeType = attributeDescription.getAttributeType();
+    final MatchingRule matchingRule = attributeType.getEqualityMatchingRule();
 
     try
     {
       return matchingRule.normalizeAttributeValue(value);
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
       // Fall back to provided value.
       return value;
@@ -149,19 +148,18 @@
    * Returns a string representation of {@code attribute}.
    *
    * @param attribute
-   *          The attribute whose string representation should be
-   *          returned.
+   *          The attribute whose string representation should be returned.
    * @return The string representation of {@code attribute}.
    */
-  static String toString(Attribute attribute)
+  static String toString(final Attribute attribute)
   {
-    StringBuilder builder = new StringBuilder();
+    final StringBuilder builder = new StringBuilder();
     builder.append("Attribute(");
     builder.append(attribute.getAttributeDescriptionAsString());
     builder.append(", {");
 
     boolean firstValue = true;
-    for (ByteString value : attribute)
+    for (final ByteString value : attribute)
     {
       if (!firstValue)
       {
@@ -191,6 +189,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public abstract boolean add(ByteString value)
       throws UnsupportedOperationException, NullPointerException;
 
@@ -199,7 +198,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean add(Object firstValue, Object... remainingValues)
+  public boolean add(final Object firstValue, final Object... remainingValues)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(firstValue);
@@ -207,7 +206,7 @@
     boolean modified = add(ByteString.valueOf(firstValue));
     if (remainingValues != null)
     {
-      for (Object value : remainingValues)
+      for (final Object value : remainingValues)
       {
         modified |= add(ByteString.valueOf(value));
       }
@@ -220,7 +219,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean addAll(Collection<? extends ByteString> values)
+  @Override
+  public boolean addAll(final Collection<? extends ByteString> values)
       throws UnsupportedOperationException, NullPointerException
   {
     return addAll(values, null);
@@ -231,12 +231,12 @@
   /**
    * {@inheritDoc}
    */
-  public boolean addAll(Collection<? extends ByteString> values,
-      Collection<? super ByteString> duplicateValues)
+  public boolean addAll(final Collection<? extends ByteString> values,
+      final Collection<? super ByteString> duplicateValues)
       throws UnsupportedOperationException, NullPointerException
   {
     boolean modified = false;
-    for (ByteString value : values)
+    for (final ByteString value : values)
     {
       if (add(value))
       {
@@ -255,18 +255,19 @@
   /**
    * {@inheritDoc}
    */
-  public abstract boolean contains(Object value)
-      throws NullPointerException;
+  @Override
+  public abstract boolean contains(Object value) throws NullPointerException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  public boolean containsAll(Collection<?> values)
+  @Override
+  public boolean containsAll(final Collection<?> values)
       throws NullPointerException
   {
-    for (Object value : values)
+    for (final Object value : values)
     {
       if (!contains(value))
       {
@@ -281,7 +282,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean equals(Object object)
+  @Override
+  public boolean equals(final Object object)
   {
     return equals(this, object);
   }
@@ -328,6 +330,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public int hashCode()
   {
     return hashCode(this);
@@ -338,6 +341,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public abstract Iterator<ByteString> iterator();
 
 
@@ -345,6 +349,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public abstract boolean remove(Object value)
       throws UnsupportedOperationException, NullPointerException;
 
@@ -353,7 +358,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean removeAll(Collection<?> values)
+  @Override
+  public boolean removeAll(final Collection<?> values)
       throws UnsupportedOperationException, NullPointerException
   {
     return removeAll(values, null);
@@ -364,12 +370,12 @@
   /**
    * {@inheritDoc}
    */
-  public <T> boolean removeAll(Collection<T> values,
-      Collection<? super T> missingValues)
+  public <T> boolean removeAll(final Collection<T> values,
+      final Collection<? super T> missingValues)
       throws UnsupportedOperationException, NullPointerException
   {
     boolean modified = false;
-    for (T value : values)
+    for (final T value : values)
     {
       if (remove(value))
       {
@@ -388,7 +394,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean retainAll(Collection<?> values)
+  @Override
+  public boolean retainAll(final Collection<?> values)
       throws UnsupportedOperationException, NullPointerException
   {
     return retainAll(values, null);
@@ -399,8 +406,8 @@
   /**
    * {@inheritDoc}
    */
-  public <T> boolean retainAll(Collection<T> values,
-      Collection<? super T> missingValues)
+  public <T> boolean retainAll(final Collection<T> values,
+      final Collection<? super T> missingValues)
       throws UnsupportedOperationException, NullPointerException
   {
     if (values.isEmpty())
@@ -420,7 +427,7 @@
     {
       if (missingValues != null)
       {
-        for (T value : values)
+        for (final T value : values)
         {
           missingValues.add(value);
         }
@@ -428,20 +435,20 @@
       return false;
     }
 
-    Map<ByteString, T> valuesToRetain = new HashMap<ByteString, T>(
-        values.size());
-    for (T value : values)
+    final Map<ByteString, T> valuesToRetain = new HashMap<ByteString, T>(values
+        .size());
+    for (final T value : values)
     {
-      valuesToRetain.put(
-          normalizeValue(this, ByteString.valueOf(value)), value);
+      valuesToRetain
+          .put(normalizeValue(this, ByteString.valueOf(value)), value);
     }
 
     boolean modified = false;
-    Iterator<ByteString> iterator = iterator();
+    final Iterator<ByteString> iterator = iterator();
     while (iterator.hasNext())
     {
-      ByteString value = iterator.next();
-      ByteString normalizedValue = normalizeValue(this, value);
+      final ByteString value = iterator.next();
+      final ByteString normalizedValue = normalizeValue(this, value);
       if (valuesToRetain.remove(normalizedValue) == null)
       {
         modified = true;
@@ -462,6 +469,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public abstract int size();
 
 
@@ -469,6 +477,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public ByteString[] toArray()
   {
     return toArray(new ByteString[size()]);
@@ -479,6 +488,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public String toString()
   {
     return toString(this);
diff --git a/sdk/src/org/opends/sdk/AbstractConnection.java b/sdk/src/org/opends/sdk/AbstractConnection.java
index 53fc0bc..64576de 100644
--- a/sdk/src/org/opends/sdk/AbstractConnection.java
+++ b/sdk/src/org/opends/sdk/AbstractConnection.java
@@ -29,7 +29,9 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_NO_SEARCH_RESULT_ENTRIES;
+import static com.sun.opends.sdk.messages.Messages.ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES;
+import static com.sun.opends.sdk.messages.Messages.ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES;
 
 import java.util.Collection;
 import java.util.LinkedList;
@@ -45,15 +47,13 @@
 
 
 /**
- * This class provides a skeletal implementation of the {@code
- * Connection} interface, to minimize the effort required to implement
- * this interface.
+ * This class provides a skeletal implementation of the {@code Connection}
+ * interface, to minimize the effort required to implement this interface.
  */
 public abstract class AbstractConnection implements Connection
 {
 
-  private static final class SingleEntryHandler implements
-      SearchResultHandler
+  private static final class SingleEntryHandler implements SearchResultHandler
   {
     private volatile SearchResultEntry firstEntry = null;
 
@@ -63,23 +63,25 @@
 
 
 
-    public void handleEntry(SearchResultEntry entry)
+    public boolean handleEntry(final SearchResultEntry entry)
     {
       if (firstEntry == null)
       {
         firstEntry = entry;
       }
       entryCount++;
+      return true;
     }
 
 
 
-    public void handleReference(SearchResultReference reference)
+    public boolean handleReference(final SearchResultReference reference)
     {
       if (firstReference == null)
       {
         firstReference = reference;
       }
+      return true;
     }
 
   }
@@ -96,7 +98,10 @@
 
 
 
-  public Result add(Entry entry) throws ErrorResultException,
+  /**
+   * {@inheritDoc}
+   */
+  public Result add(final Entry entry) throws ErrorResultException,
       InterruptedException, UnsupportedOperationException,
       IllegalStateException, NullPointerException
   {
@@ -105,7 +110,10 @@
 
 
 
-  public Result add(String... ldifLines) throws ErrorResultException,
+  /**
+   * {@inheritDoc}
+   */
+  public Result add(final String... ldifLines) throws ErrorResultException,
       InterruptedException, UnsupportedOperationException,
       LocalizedIllegalArgumentException, IllegalStateException,
       NullPointerException
@@ -115,7 +123,10 @@
 
 
 
-  public BindResult bind(String name, String password)
+  /**
+   * {@inheritDoc}
+   */
+  public BindResult bind(final String name, final String password)
       throws ErrorResultException, InterruptedException,
       LocalizedIllegalArgumentException, UnsupportedOperationException,
       IllegalStateException, NullPointerException
@@ -125,19 +136,25 @@
 
 
 
-  public CompareResult compare(String name,
-      String attributeDescription, String assertionValue)
+  /**
+   * {@inheritDoc}
+   */
+  public CompareResult compare(final String name,
+      final String attributeDescription, final String assertionValue)
       throws ErrorResultException, InterruptedException,
       LocalizedIllegalArgumentException, UnsupportedOperationException,
       IllegalStateException, NullPointerException
   {
-    return compare(Requests.newCompareRequest(name,
-        attributeDescription, assertionValue));
+    return compare(Requests.newCompareRequest(name, attributeDescription,
+        assertionValue));
   }
 
 
 
-  public Result delete(String name) throws ErrorResultException,
+  /**
+   * {@inheritDoc}
+   */
+  public Result delete(final String name) throws ErrorResultException,
       InterruptedException, LocalizedIllegalArgumentException,
       UnsupportedOperationException, IllegalStateException,
       NullPointerException
@@ -147,28 +164,37 @@
 
 
 
-  public GenericExtendedResult extendedRequest(String requestName,
-      ByteString requestValue) throws ErrorResultException,
+  /**
+   * {@inheritDoc}
+   */
+  public GenericExtendedResult extendedRequest(final String requestName,
+      final ByteString requestValue) throws ErrorResultException,
       InterruptedException, UnsupportedOperationException,
       IllegalStateException, NullPointerException
   {
-    return extendedRequest(Requests.newGenericExtendedRequest(
-        requestName, requestValue));
+    return extendedRequest(Requests.newGenericExtendedRequest(requestName,
+        requestValue));
   }
 
 
 
-  public Result modify(String... ldifLines)
-      throws ErrorResultException, InterruptedException,
-      UnsupportedOperationException, LocalizedIllegalArgumentException,
-      IllegalStateException, NullPointerException
+  /**
+   * {@inheritDoc}
+   */
+  public Result modify(final String... ldifLines) throws ErrorResultException,
+      InterruptedException, UnsupportedOperationException,
+      LocalizedIllegalArgumentException, IllegalStateException,
+      NullPointerException
   {
     return modify(Requests.newModifyRequest(ldifLines));
   }
 
 
 
-  public Result modifyDN(String name, String newRDN)
+  /**
+   * {@inheritDoc}
+   */
+  public Result modifyDN(final String name, final String newRDN)
       throws ErrorResultException, InterruptedException,
       LocalizedIllegalArgumentException, UnsupportedOperationException,
       IllegalStateException, NullPointerException
@@ -178,12 +204,15 @@
 
 
 
-  public SearchResultEntry readEntry(DN baseObject,
-      String... attributeDescriptions) throws ErrorResultException,
+  /**
+   * {@inheritDoc}
+   */
+  public SearchResultEntry readEntry(final DN baseObject,
+      final String... attributeDescriptions) throws ErrorResultException,
       InterruptedException, UnsupportedOperationException,
       IllegalStateException, NullPointerException
   {
-    SearchRequest request = Requests.newSearchRequest(baseObject,
+    final SearchRequest request = Requests.newSearchRequest(baseObject,
         SearchScope.BASE_OBJECT, Filter.getObjectClassPresentFilter(),
         attributeDescriptions);
     return searchSingleEntry(request);
@@ -191,8 +220,11 @@
 
 
 
-  public SearchResultEntry readEntry(String baseObject,
-      String... attributeDescriptions) throws ErrorResultException,
+  /**
+   * {@inheritDoc}
+   */
+  public SearchResultEntry readEntry(final String baseObject,
+      final String... attributeDescriptions) throws ErrorResultException,
       InterruptedException, LocalizedIllegalArgumentException,
       UnsupportedOperationException, IllegalStateException,
       NullPointerException
@@ -217,7 +249,7 @@
   /**
    * {@inheritDoc}
    */
-  public Schema readSchema(DN name) throws ErrorResultException,
+  public Schema readSchema(final DN name) throws ErrorResultException,
       InterruptedException, UnsupportedOperationException,
       IllegalStateException
   {
@@ -229,7 +261,7 @@
   /**
    * {@inheritDoc}
    */
-  public Schema readSchema(String name) throws ErrorResultException,
+  public Schema readSchema(final String name) throws ErrorResultException,
       InterruptedException, LocalizedIllegalArgumentException,
       UnsupportedOperationException, IllegalStateException
   {
@@ -241,9 +273,9 @@
   /**
    * {@inheritDoc}
    */
-  public Schema readSchemaForEntry(DN name)
-      throws ErrorResultException, InterruptedException,
-      UnsupportedOperationException, IllegalStateException
+  public Schema readSchemaForEntry(final DN name) throws ErrorResultException,
+      InterruptedException, UnsupportedOperationException,
+      IllegalStateException
   {
     return Schema.readSchemaForEntry(this, name);
   }
@@ -253,7 +285,7 @@
   /**
    * {@inheritDoc}
    */
-  public Schema readSchemaForEntry(String name)
+  public Schema readSchemaForEntry(final String name)
       throws ErrorResultException, InterruptedException,
       LocalizedIllegalArgumentException, UnsupportedOperationException,
       IllegalStateException
@@ -278,8 +310,8 @@
   /**
    * {@inheritDoc}
    */
-  public Result search(SearchRequest request,
-      Collection<? super SearchResultEntry> entries)
+  public Result search(final SearchRequest request,
+      final Collection<? super SearchResultEntry> entries)
       throws ErrorResultException, InterruptedException,
       UnsupportedOperationException, IllegalStateException,
       NullPointerException
@@ -289,7 +321,10 @@
 
 
 
-  public Result search(SearchRequest request,
+  /**
+   * {@inheritDoc}
+   */
+  public Result search(final SearchRequest request,
       final Collection<? super SearchResultEntry> entries,
       final Collection<? super SearchResultReference> references)
       throws ErrorResultException, InterruptedException,
@@ -299,22 +334,24 @@
     Validator.ensureNotNull(request, entries);
 
     // FIXME: does this need to be thread safe?
-    SearchResultHandler handler = new SearchResultHandler()
+    final SearchResultHandler handler = new SearchResultHandler()
     {
 
-      public void handleEntry(SearchResultEntry entry)
+      public boolean handleEntry(final SearchResultEntry entry)
       {
         entries.add(entry);
+        return true;
       }
 
 
 
-      public void handleReference(SearchResultReference reference)
+      public boolean handleReference(final SearchResultReference reference)
       {
         if (references != null)
         {
           references.add(reference);
         }
+        return true;
       }
     };
 
@@ -323,52 +360,58 @@
 
 
 
-  public List<SearchResultEntry> search(String baseObject,
-      SearchScope scope, String filter, String... attributeDescriptions)
-      throws ErrorResultException, InterruptedException,
-      LocalizedIllegalArgumentException, UnsupportedOperationException,
-      IllegalStateException, NullPointerException
+  /**
+   * {@inheritDoc}
+   */
+  public List<SearchResultEntry> search(final String baseObject,
+      final SearchScope scope, final String filter,
+      final String... attributeDescriptions) throws ErrorResultException,
+      InterruptedException, LocalizedIllegalArgumentException,
+      UnsupportedOperationException, IllegalStateException,
+      NullPointerException
   {
-    List<SearchResultEntry> entries = new LinkedList<SearchResultEntry>();
-    SearchRequest request = Requests.newSearchRequest(baseObject,
-        scope, filter, attributeDescriptions);
+    final List<SearchResultEntry> entries = new LinkedList<SearchResultEntry>();
+    final SearchRequest request = Requests.newSearchRequest(baseObject, scope,
+        filter, attributeDescriptions);
     search(request, entries);
     return entries;
   }
 
 
 
-  public SearchResultEntry searchSingleEntry(SearchRequest request)
+  /**
+   * {@inheritDoc}
+   */
+  public SearchResultEntry searchSingleEntry(final SearchRequest request)
       throws ErrorResultException, InterruptedException,
       UnsupportedOperationException, IllegalStateException,
       NullPointerException
   {
-    SingleEntryHandler handler = new SingleEntryHandler();
+    final SingleEntryHandler handler = new SingleEntryHandler();
     search(request, handler);
 
     if (handler.entryCount == 0)
     {
       // Did not find any entries.
-      Result result = Responses.newResult(
-          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
-          .setDiagnosticMessage(
-              ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
+      final Result result = Responses.newResult(
+          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED).setDiagnosticMessage(
+          ERR_NO_SEARCH_RESULT_ENTRIES.get().toString());
       throw ErrorResultException.wrap(result);
     }
     else if (handler.entryCount > 1)
     {
       // Got more entries than expected.
-      Result result = Responses.newResult(
+      final Result result = Responses.newResult(
           ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
           .setDiagnosticMessage(
-              ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(
-                  handler.entryCount).toString());
+              ERR_UNEXPECTED_SEARCH_RESULT_ENTRIES.get(handler.entryCount)
+                  .toString());
       throw ErrorResultException.wrap(result);
     }
     else if (handler.firstReference != null)
     {
       // Got an unexpected search result reference.
-      Result result = Responses.newResult(
+      final Result result = Responses.newResult(
           ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
           .setDiagnosticMessage(
               ERR_UNEXPECTED_SEARCH_RESULT_REFERENCES.get(
@@ -384,14 +427,18 @@
 
 
 
-  public SearchResultEntry searchSingleEntry(String baseObject,
-      SearchScope scope, String filter, String... attributeDescriptions)
-      throws ErrorResultException, InterruptedException,
-      LocalizedIllegalArgumentException, UnsupportedOperationException,
-      IllegalStateException, NullPointerException
+  /**
+   * {@inheritDoc}
+   */
+  public SearchResultEntry searchSingleEntry(final String baseObject,
+      final SearchScope scope, final String filter,
+      final String... attributeDescriptions) throws ErrorResultException,
+      InterruptedException, LocalizedIllegalArgumentException,
+      UnsupportedOperationException, IllegalStateException,
+      NullPointerException
   {
-    SearchRequest request = Requests.newSearchRequest(baseObject,
-        scope, filter, attributeDescriptions);
+    final SearchRequest request = Requests.newSearchRequest(baseObject, scope,
+        filter, attributeDescriptions);
     return searchSingleEntry(request);
   }
 
diff --git a/sdk/src/org/opends/sdk/AbstractConnectionFactory.java b/sdk/src/org/opends/sdk/AbstractConnectionFactory.java
index 6fa60c4..4805de0 100644
--- a/sdk/src/org/opends/sdk/AbstractConnectionFactory.java
+++ b/sdk/src/org/opends/sdk/AbstractConnectionFactory.java
@@ -29,18 +29,12 @@
 
 
 
-import org.opends.sdk.responses.Responses;
-import org.opends.sdk.responses.Result;
-
-
-
 /**
  * This class provides a skeletal implementation of the {@code
- * ConnectionFactory} interface, to minimize the effort required to
- * implement this interface.
+ * ConnectionFactory} interface, to minimize the effort required to implement
+ * this interface.
  */
-public abstract class AbstractConnectionFactory implements
-    ConnectionFactory
+public abstract class AbstractConnectionFactory implements ConnectionFactory
 {
   /**
    * Creates a new abstract connection factory.
@@ -63,57 +57,27 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to convert the asynchronous
-   * connection returned from {@code
-   * blockingGetAsynchronousConnection()} to a synchronous connection
-   * using a {@link SynchronousConnection} as per the following code:
+   * The default implementation is to convert the asynchronous connection
+   * returned from {@code blockingGetAsynchronousConnection()} to a synchronous
+   * connection using a {@link SynchronousConnection} as per the following code:
    *
    * <pre>
    * return new SynchronousConnection(blockingGetAsynchronousConnection());
    * </pre>
    *
-   * Implementations should override this method if they wish to return
-   * a different type of synchronous connection.
+   * Implementations should override this method if they wish to return a
+   * different type of synchronous connection.
    *
    * @return A connection to the Directory Server associated with this
    *         connection factory.
    * @throws ErrorResultException
    *           If the connection request failed for some reason.
+   * @throws InterruptedException
+   *           If the current thread was interrupted while waiting.
    */
-  public Connection getConnection() throws ErrorResultException
+  public Connection getConnection() throws ErrorResultException,
+      InterruptedException
   {
-    return new SynchronousConnection(
-        blockingGetAsynchronousConnection());
-  }
-
-
-
-  /**
-   * Invokes {@code getAsynchronousConnection}, blocking until the
-   * asynchronous connection is obtained or the attempt fails.
-   *
-   * @return An asynchronous connection obtained using {@code
-   *         getAsynchronousConnection}.
-   * @throws ErrorResultException
-   *           If the connection request failed for some reason.
-   */
-  protected final AsynchronousConnection blockingGetAsynchronousConnection()
-      throws ErrorResultException
-  {
-    FutureResult<AsynchronousConnection> future = getAsynchronousConnection(null);
-    try
-    {
-      return future.get();
-    }
-    catch (InterruptedException e)
-    {
-      // Cancel the request if possible.
-      future.cancel(false);
-
-      Result result = Responses.newResult(
-          ResultCode.CLIENT_SIDE_CONNECT_ERROR).setCause(e)
-          .setDiagnosticMessage(e.getLocalizedMessage());
-      throw ErrorResultException.wrap(result);
-    }
+    return getAsynchronousConnection(null).get().getSynchronousConnection();
   }
 }
diff --git a/sdk/src/org/opends/sdk/AbstractEntry.java b/sdk/src/org/opends/sdk/AbstractEntry.java
index 809edcd..8a6379a 100644
--- a/sdk/src/org/opends/sdk/AbstractEntry.java
+++ b/sdk/src/org/opends/sdk/AbstractEntry.java
@@ -29,36 +29,27 @@
 
 
 
-import org.opends.sdk.schema.ObjectClass;
+import java.util.Collection;
 
-import com.sun.opends.sdk.util.*;
+import com.sun.opends.sdk.util.Iterables;
+import com.sun.opends.sdk.util.Predicate;
+import com.sun.opends.sdk.util.Validator;
 
 
 
 /**
- * This class provides a skeletal implementation of the {@code Entry}
- * interface, to minimize the effort required to implement this
- * interface.
+ * This class provides a skeletal implementation of the {@code Entry} interface,
+ * to minimize the effort required to implement this interface.
  */
 public abstract class AbstractEntry implements Entry
 {
 
-  // Function used for getObjectClasses
-  private static final Function<ByteString, String, Void> BYTE_STRING_TO_STRING_FUNCTION = new Function<ByteString, String, Void>()
-  {
-
-    public String apply(ByteString value, Void p)
-    {
-      return value.toString();
-    }
-
-  };
-
   // Predicate used for findAttributes.
-  private static final Predicate<Attribute, AttributeDescription> FIND_ATTRIBUTES_PREDICATE = new Predicate<Attribute, AttributeDescription>()
+  private static final Predicate<Attribute, AttributeDescription>
+    FIND_ATTRIBUTES_PREDICATE = new Predicate<Attribute, AttributeDescription>()
   {
 
-    public boolean matches(Attribute value, AttributeDescription p)
+    public boolean matches(final Attribute value, final AttributeDescription p)
     {
       return value.getAttributeDescription().isSubTypeOf(p);
     }
@@ -68,20 +59,20 @@
 
 
   /**
-   * Returns {@code true} if {@code object} is an entry which is equal
-   * to {@code entry}. Two entry are considered equal if their
-   * distinguished names are equal, they both have the same number of
-   * attributes, and every attribute contained in the first entry is
-   * also contained in the second entry.
+   * Returns {@code true} if {@code object} is an entry which is equal to
+   * {@code entry}. Two entry are considered equal if their distinguished names
+   * are equal, they both have the same number of attributes, and every
+   * attribute contained in the first entry is also contained in the second
+   * entry.
    *
    * @param entry
    *          The entry to be tested for equality.
    * @param object
    *          The object to be tested for equality with the entry.
-   * @return {@code true} if {@code object} is an entry which is equal
-   *         to {@code entry}, or {@code false} if not.
+   * @return {@code true} if {@code object} is an entry which is equal to
+   *         {@code entry}, or {@code false} if not.
    */
-  static boolean equals(Entry entry, Object object)
+  static boolean equals(final Entry entry, final Object object)
   {
     if (entry == object)
     {
@@ -93,7 +84,7 @@
       return false;
     }
 
-    Entry other = (Entry) object;
+    final Entry other = (Entry) object;
     if (!entry.getName().equals(other.getName()))
     {
       return false;
@@ -105,9 +96,9 @@
       return false;
     }
 
-    for (Attribute attribute : entry.getAttributes())
+    for (final Attribute attribute : entry.getAllAttributes())
     {
-      Attribute otherAttribute = other.getAttribute(attribute
+      final Attribute otherAttribute = other.getAttribute(attribute
           .getAttributeDescription());
 
       if (!attribute.equals(otherAttribute))
@@ -122,18 +113,17 @@
 
 
   /**
-   * Returns the hash code for {@code entry}. It will be calculated as
-   * the sum of the hash codes of the distinguished name and all of the
-   * attributes.
+   * Returns the hash code for {@code entry}. It will be calculated as the sum
+   * of the hash codes of the distinguished name and all of the attributes.
    *
    * @param entry
    *          The entry whose hash code should be calculated.
    * @return The hash code for {@code entry}.
    */
-  static int hashCode(Entry entry)
+  static int hashCode(final Entry entry)
   {
     int hashCode = entry.getName().hashCode();
-    for (Attribute attribute : entry.getAttributes())
+    for (final Attribute attribute : entry.getAllAttributes())
     {
       hashCode += attribute.hashCode();
     }
@@ -149,15 +139,15 @@
    *          The entry whose string representation should be returned.
    * @return The string representation of {@code entry}.
    */
-  static String toString(Entry entry)
+  static String toString(final Entry entry)
   {
-    StringBuilder builder = new StringBuilder();
+    final StringBuilder builder = new StringBuilder();
     builder.append("Entry(");
     builder.append(entry.getName());
     builder.append(", {");
 
     boolean firstValue = true;
-    for (Attribute attribute : entry.getAttributes())
+    for (final Attribute attribute : entry.getAllAttributes())
     {
       if (!firstValue)
       {
@@ -187,7 +177,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean addAttribute(Attribute attribute)
+  public boolean addAttribute(final Attribute attribute)
       throws UnsupportedOperationException, NullPointerException
   {
     return addAttribute(attribute, null);
@@ -198,8 +188,8 @@
   /**
    * {@inheritDoc}
    */
-  public Entry addAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
+  public Entry addAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException
   {
     addAttribute(new LinkedAttribute(attributeDescription, values), null);
@@ -211,11 +201,34 @@
   /**
    * {@inheritDoc}
    */
-  public boolean containsAttribute(String attributeDescription)
-      throws LocalizedIllegalArgumentException, NullPointerException
+  public boolean containsAttribute(final Attribute attribute,
+      final Collection<ByteString> missingValues) throws NullPointerException
   {
-    return containsAttribute(AttributeDescription
-        .valueOf(attributeDescription));
+    final Attribute a = getAttribute(attribute.getAttributeDescription());
+    if (a == null)
+    {
+      if (missingValues != null)
+      {
+        missingValues.addAll(attribute);
+      }
+      return false;
+    }
+    else
+    {
+      boolean result = true;
+      for (final ByteString value : attribute)
+      {
+        if (!a.contains(value))
+        {
+          if (missingValues != null)
+          {
+            missingValues.add(value);
+          }
+          result = false;
+        }
+      }
+      return result;
+    }
   }
 
 
@@ -223,10 +236,12 @@
   /**
    * {@inheritDoc}
    */
-  public boolean containsObjectClass(ObjectClass objectClass)
-      throws NullPointerException
+  public boolean containsAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
+      NullPointerException
   {
-    return containsObjectClass(objectClass.getOID());
+    return containsAttribute(new LinkedAttribute(attributeDescription, values),
+        null);
   }
 
 
@@ -234,22 +249,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean containsObjectClass(String objectClass)
-      throws NullPointerException
-  {
-    Validator.ensureNotNull(objectClass);
-
-    Attribute attribute = getAttribute(AttributeDescription
-        .objectClass());
-    return attribute != null ? attribute.contains(objectClass) : false;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean equals(Object object)
+  @Override
+  public boolean equals(final Object object)
   {
     return equals(this, object);
   }
@@ -259,13 +260,13 @@
   /**
    * {@inheritDoc}
    */
-  public Iterable<Attribute> findAttributes(
-      AttributeDescription attributeDescription)
+  public Iterable<Attribute> getAllAttributes(
+      final AttributeDescription attributeDescription)
       throws NullPointerException
   {
     Validator.ensureNotNull(attributeDescription);
 
-    return Iterables.filter(getAttributes(), FIND_ATTRIBUTES_PREDICATE,
+    return Iterables.filter(getAllAttributes(), FIND_ATTRIBUTES_PREDICATE,
         attributeDescription);
   }
 
@@ -274,11 +275,10 @@
   /**
    * {@inheritDoc}
    */
-  public Iterable<Attribute> findAttributes(String attributeDescription)
+  public Iterable<Attribute> getAllAttributes(final String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
-    return findAttributes(AttributeDescription
-        .valueOf(attributeDescription));
+    return getAllAttributes(AttributeDescription.valueOf(attributeDescription));
   }
 
 
@@ -286,11 +286,10 @@
   /**
    * {@inheritDoc}
    */
-  public Attribute getAttribute(String attributeDescription)
+  public Attribute getAttribute(final String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
-    return getAttribute(AttributeDescription
-        .valueOf(attributeDescription));
+    return getAttribute(AttributeDescription.valueOf(attributeDescription));
   }
 
 
@@ -298,27 +297,7 @@
   /**
    * {@inheritDoc}
    */
-  public Iterable<String> getObjectClasses()
-  {
-    Attribute attribute = getAttribute(AttributeDescription
-        .objectClass());
-
-    if (attribute == null)
-    {
-      return Iterables.empty();
-    }
-    else
-    {
-      return Iterables.transform(attribute,
-          BYTE_STRING_TO_STRING_FUNCTION);
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
+  @Override
   public int hashCode()
   {
     return hashCode(this);
@@ -329,12 +308,10 @@
   /**
    * {@inheritDoc}
    */
-  public boolean removeAttribute(
-      AttributeDescription attributeDescription)
+  public boolean removeAttribute(final AttributeDescription attributeDescription)
       throws UnsupportedOperationException, NullPointerException
   {
-    return removeAttribute(Types.emptyAttribute(attributeDescription),
-        null);
+    return removeAttribute(Types.emptyAttribute(attributeDescription), null);
   }
 
 
@@ -342,11 +319,11 @@
   /**
    * {@inheritDoc}
    */
-  public Entry removeAttribute(String attributeDescription)
-      throws LocalizedIllegalArgumentException,
+  public Entry removeAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException
   {
-    removeAttribute(new LinkedAttribute(attributeDescription), null);
+    removeAttribute(new LinkedAttribute(attributeDescription, values), null);
     return this;
   }
 
@@ -355,21 +332,7 @@
   /**
    * {@inheritDoc}
    */
-  public Entry removeAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
-  {
-    removeAttribute(new LinkedAttribute(attributeDescription, values),
-        null);
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean replaceAttribute(Attribute attribute)
+  public boolean replaceAttribute(final Attribute attribute)
       throws UnsupportedOperationException, NullPointerException
   {
     if (attribute.isEmpty())
@@ -379,7 +342,7 @@
     else
     {
       removeAttribute(attribute.getAttributeDescription());
-      addAttribute(attribute);
+      addAttribute(attribute, null);
       return true;
     }
   }
@@ -389,8 +352,8 @@
   /**
    * {@inheritDoc}
    */
-  public Entry replaceAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
+  public Entry replaceAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException
   {
     replaceAttribute(new LinkedAttribute(attributeDescription, values));
@@ -402,9 +365,9 @@
   /**
    * {@inheritDoc}
    */
-  public Entry setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
+  public Entry setName(final String dn)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
   {
     return setName(DN.valueOf(dn));
   }
@@ -414,6 +377,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public String toString()
   {
     return toString(this);
diff --git a/sdk/src/org/opends/sdk/AbstractFilterVisitor.java b/sdk/src/org/opends/sdk/AbstractFilterVisitor.java
index 7f14f15..71aba58 100644
--- a/sdk/src/org/opends/sdk/AbstractFilterVisitor.java
+++ b/sdk/src/org/opends/sdk/AbstractFilterVisitor.java
@@ -34,20 +34,19 @@
 
 
 /**
- * An abstract filter visitor whose default implementation for all
- * {@code Visitor} methods is to invoke
- * {@link #visitDefaultFilter(Object)}.
+ * An abstract filter visitor whose default implementation for all {@code
+ * Visitor} methods is to invoke {@link #visitDefaultFilter(Object)}.
  * <p>
  * Implementations can override the methods on a case by case behavior.
  *
  * @param <R>
  *          The return type of this visitor's methods. Use
- *          {@link java.lang.Void} for visitors that do not need to
- *          return results.
+ *          {@link java.lang.Void} for visitors that do not need to return
+ *          results.
  * @param <P>
- *          The type of the additional parameter to this visitor's
- *          methods. Use {@link java.lang.Void} for visitors that do not
- *          need an additional parameter.
+ *          The type of the additional parameter to this visitor's methods. Use
+ *          {@link java.lang.Void} for visitors that do not need an additional
+ *          parameter.
  */
 public abstract class AbstractFilterVisitor<R, P> implements
     FilterVisitor<R, P>
@@ -66,10 +65,9 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitAndFilter(P p, List<Filter> subFilters)
+  public R visitAndFilter(final P p, final List<Filter> subFilters)
   {
     return visitDefaultFilter(p);
   }
@@ -79,11 +77,10 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitApproxMatchFilter(P p, String attributeDescription,
-      ByteString assertionValue)
+  public R visitApproxMatchFilter(final P p, final String attributeDescription,
+      final ByteString assertionValue)
   {
     return visitDefaultFilter(p);
   }
@@ -91,8 +88,8 @@
 
 
   /**
-   * Visits any filters which are not explicitly handled by other
-   * visitor methods.
+   * Visits any filters which are not explicitly handled by other visitor
+   * methods.
    * <p>
    * The default implementation of this method is to return {@code null}.
    *
@@ -100,7 +97,7 @@
    *          A visitor specified parameter.
    * @return A visitor specified result.
    */
-  public R visitDefaultFilter(P p)
+  public R visitDefaultFilter(final P p)
   {
     return null;
   }
@@ -110,11 +107,10 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitEqualityMatchFilter(P p, String attributeDescription,
-      ByteString assertionValue)
+  public R visitEqualityMatchFilter(final P p,
+      final String attributeDescription, final ByteString assertionValue)
   {
     return visitDefaultFilter(p);
   }
@@ -124,12 +120,11 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitExtensibleMatchFilter(P p, String matchingRule,
-      String attributeDescription, ByteString assertionValue,
-      boolean dnAttributes)
+  public R visitExtensibleMatchFilter(final P p, final String matchingRule,
+      final String attributeDescription, final ByteString assertionValue,
+      final boolean dnAttributes)
   {
     return visitDefaultFilter(p);
   }
@@ -139,11 +134,10 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitGreaterOrEqualFilter(P p, String attributeDescription,
-      ByteString assertionValue)
+  public R visitGreaterOrEqualFilter(final P p,
+      final String attributeDescription, final ByteString assertionValue)
   {
     return visitDefaultFilter(p);
   }
@@ -153,11 +147,10 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitLessOrEqualFilter(P p, String attributeDescription,
-      ByteString assertionValue)
+  public R visitLessOrEqualFilter(final P p, final String attributeDescription,
+      final ByteString assertionValue)
   {
     return visitDefaultFilter(p);
   }
@@ -167,10 +160,9 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitNotFilter(P p, Filter subFilter)
+  public R visitNotFilter(final P p, final Filter subFilter)
   {
     return visitDefaultFilter(p);
   }
@@ -180,10 +172,9 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitOrFilter(P p, List<Filter> subFilters)
+  public R visitOrFilter(final P p, final List<Filter> subFilters)
   {
     return visitDefaultFilter(p);
   }
@@ -193,10 +184,9 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitPresentFilter(P p, String attributeDescription)
+  public R visitPresentFilter(final P p, final String attributeDescription)
   {
     return visitDefaultFilter(p);
   }
@@ -206,12 +196,11 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitSubstringsFilter(P p, String attributeDescription,
-      ByteString initialSubstring, List<ByteString> anySubstrings,
-      ByteString finalSubstring)
+  public R visitSubstringsFilter(final P p, final String attributeDescription,
+      final ByteString initialSubstring, final List<ByteString> anySubstrings,
+      final ByteString finalSubstring)
   {
     return visitDefaultFilter(p);
   }
@@ -221,11 +210,10 @@
   /**
    * {@inheritDoc}
    * <p>
-   * The default implementation is to call
-   * {@link #visitDefaultFilter(Object)}.
+   * The default implementation is to call {@link #visitDefaultFilter(Object)}.
    */
-  public R visitUnrecognizedFilter(P p, byte filterTag,
-      ByteString filterBytes)
+  public R visitUnrecognizedFilter(final P p, final byte filterTag,
+      final ByteString filterBytes)
   {
     return visitDefaultFilter(p);
   }
diff --git a/sdk/src/org/opends/sdk/AbstractMapEntry.java b/sdk/src/org/opends/sdk/AbstractMapEntry.java
new file mode 100644
index 0000000..800a6b5
--- /dev/null
+++ b/sdk/src/org/opends/sdk/AbstractMapEntry.java
@@ -0,0 +1,204 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.util.Collection;
+import java.util.Map;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * Abstract implementation for {@code Map} based entries.
+ */
+abstract class AbstractMapEntry extends AbstractEntry
+{
+  private final Map<AttributeDescription, Attribute> attributes;
+
+  private DN name;
+
+
+
+  /**
+   * Creates an empty entry using the provided distinguished name and {@code
+   * Map}.
+   *
+   * @param name
+   *          The distinguished name of this entry.
+   * @param attributes
+   *          The attribute map.
+   */
+  AbstractMapEntry(final DN name,
+      final Map<AttributeDescription, Attribute> attributes)
+      throws NullPointerException
+  {
+    this.name = name;
+    this.attributes = attributes;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final boolean addAttribute(final Attribute attribute,
+      final Collection<ByteString> duplicateValues) throws NullPointerException
+  {
+    Validator.ensureNotNull(attribute);
+
+    if (!attribute.isEmpty())
+    {
+      final AttributeDescription attributeDescription = attribute
+          .getAttributeDescription();
+      final Attribute oldAttribute = attributes.get(attributeDescription);
+      if (oldAttribute != null)
+      {
+        return oldAttribute.addAll(attribute, duplicateValues);
+      }
+      else
+      {
+        attributes.put(attributeDescription, attribute);
+        return true;
+      }
+    }
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final Entry clearAttributes()
+  {
+    attributes.clear();
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final Iterable<Attribute> getAllAttributes()
+  {
+    return attributes.values();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final Attribute getAttribute(
+      final AttributeDescription attributeDescription)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(attributeDescription);
+
+    return attributes.get(attributeDescription);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final int getAttributeCount()
+  {
+    return attributes.size();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final DN getName()
+  {
+    return name;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final boolean removeAttribute(final Attribute attribute,
+      final Collection<ByteString> missingValues) throws NullPointerException
+  {
+    Validator.ensureNotNull(attribute);
+
+    final AttributeDescription attributeDescription = attribute
+        .getAttributeDescription();
+
+    if (attribute.isEmpty())
+    {
+      return attributes.remove(attributeDescription) != null;
+    }
+    else
+    {
+      final Attribute oldAttribute = attributes.get(attributeDescription);
+      if (oldAttribute != null)
+      {
+        final boolean modified = oldAttribute.removeAll(attribute,
+            missingValues);
+        if (oldAttribute.isEmpty())
+        {
+          attributes.remove(attributeDescription);
+          return true;
+        }
+        return modified;
+      }
+      else
+      {
+        if (missingValues != null)
+        {
+          missingValues.addAll(attribute);
+        }
+        return false;
+      }
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public final Entry setName(final DN dn) throws NullPointerException
+  {
+    Validator.ensureNotNull(dn);
+    this.name = dn;
+    return this;
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/Assertion.java b/sdk/src/org/opends/sdk/Assertion.java
index 2d2a53c..2037281 100644
--- a/sdk/src/org/opends/sdk/Assertion.java
+++ b/sdk/src/org/opends/sdk/Assertion.java
@@ -29,24 +29,20 @@
 
 
 
-
-
-
 /**
  * A compiled attribute value assertion.
  */
 public interface Assertion
 {
   /**
-   * Indicates whether the provided attribute value should be considered
-   * a match for this assertion value according to the matching rule.
+   * Indicates whether the provided attribute value should be considered a match
+   * for this assertion value according to the matching rule.
    *
    * @param attributeValue
    *          The attribute value.
-   * @return {@code TRUE} if the attribute value should be considered a
-   *         match for the provided assertion value, {@code FALSE} if it
-   *         does not match, or {@code UNDEFINED} if the result is
-   *         undefined.
+   * @return {@code TRUE} if the attribute value should be considered a match
+   *         for the provided assertion value, {@code FALSE} if it does not
+   *         match, or {@code UNDEFINED} if the result is undefined.
    */
   public abstract ConditionResult matches(ByteSequence attributeValue);
 }
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/src/org/opends/sdk/AssertionFailureException.java
similarity index 61%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/src/org/opends/sdk/AssertionFailureException.java
index 62b3ae3..32c5432 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/src/org/opends/sdk/AssertionFailureException.java
@@ -22,21 +22,28 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package org.opends.sdk;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.opends.sdk.responses.Result;
 
 
 
 /**
- * Password call-back.
+ * Thrown when the result code returned in a Result indicates that the Request
+ * failed because the filter contained in an assertion control failed to match
+ * the target entry. More specifically, this exception is used for the
+ * {@link ResultCode#ASSERTION_FAILED ASSERTION_FAILED} result code.
  */
-public interface PasswordCallbackHandler
+@SuppressWarnings("serial")
+public class AssertionFailureException extends ErrorResultException
 {
-  public boolean handle(PasswordCallback callback);
+  AssertionFailureException(final Result result)
+  {
+    super(result);
+  }
 }
diff --git a/sdk/src/org/opends/sdk/AsynchronousConnection.java b/sdk/src/org/opends/sdk/AsynchronousConnection.java
index 8e0fb1e..5651403 100644
--- a/sdk/src/org/opends/sdk/AsynchronousConnection.java
+++ b/sdk/src/org/opends/sdk/AsynchronousConnection.java
@@ -33,31 +33,27 @@
 import java.util.Collection;
 
 import org.opends.sdk.requests.*;
-import org.opends.sdk.responses.BindResult;
-import org.opends.sdk.responses.CompareResult;
-import org.opends.sdk.responses.Result;
-import org.opends.sdk.responses.SearchResultEntry;
+import org.opends.sdk.responses.*;
 import org.opends.sdk.schema.Schema;
 
 
 
 /**
- * An asynchronous connection with a Directory Server over which read
- * and update operations may be performed. See RFC 4511 for the LDAPv3
- * protocol specification and more information about the types of
- * operations defined in LDAP.
+ * An asynchronous connection with a Directory Server over which read and update
+ * operations may be performed. See RFC 4511 for the LDAPv3 protocol
+ * specification and more information about the types of operations defined in
+ * LDAP.
  * <p>
  * <h3>Operation processing</h3>
  * <p>
- * All operations are performed asynchronously and return a
- * {@link FutureResult} or sub-type thereof which can be used for
- * retrieving the result using the {@link FutureResult#get} method.
- * Operation failures, for whatever reason, are signalled by the
- * {@link FutureResult#get()} method throwing an
+ * All operations are performed asynchronously and return a {@link FutureResult}
+ * or sub-type thereof which can be used for retrieving the result using the
+ * {@link FutureResult#get} method. Operation failures, for whatever reason, are
+ * signalled by the {@link FutureResult#get()} method throwing an
  * {@link ErrorResultException}.
  * <p>
- * Synchronous operations are easily simulated by immediately getting
- * the result:
+ * Synchronous operations are easily simulated by immediately getting the
+ * result:
  *
  * <pre>
  * Connection connection = ...;
@@ -83,8 +79,8 @@
  * future2.get();
  * </pre>
  *
- * More complex client applications can take advantage of a fully
- * asynchronous event driven design using {@link ResultHandler}s:
+ * More complex client applications can take advantage of a fully asynchronous
+ * event driven design using {@link ResultHandler}s:
  *
  * <pre>
  * Connection connection = ...;
@@ -98,90 +94,104 @@
  * <h3>Closing connections</h3>
  * <p>
  * Applications must ensure that a connection is closed by calling
- * {@link #close()} even if a fatal error occurs on the connection. Once
- * a connection has been closed by the client application, any attempts
- * to continue to use the connection will result in an
- * {@link IllegalStateException} being thrown. Note that, if a fatal
- * error is encountered on the connection, then the application can
- * continue to use the connection. In this case all requests subsequent
- * to the failure will fail with an appropriate
- * {@link ErrorResultException} when their result is retrieved.
+ * {@link #close()} even if a fatal error occurs on the connection. Once a
+ * connection has been closed by the client application, any attempts to
+ * continue to use the connection will result in an
+ * {@link IllegalStateException} being thrown. Note that, if a fatal error is
+ * encountered on the connection, then the application can continue to use the
+ * connection. In this case all requests subsequent to the failure will fail
+ * with an appropriate {@link ErrorResultException} when their result is
+ * retrieved.
  * <p>
  * <h3>Event notification</h3>
  * <p>
- * Applications can choose to be notified when a connection is closed by
- * the application, receives an unsolicited notification, or experiences
- * a fatal error by registering a {@link ConnectionEventListener} with
- * the connection using the {@link #addConnectionEventListener} method.
- * <p>
- * <h3>TO DO</h3>
- * <p>
- * <ul>
- * <li>do we need isClosed() and isValid()?
- * <li>do we need connection event notification of client close? JDBC
- * and JCA have this functionality in their pooled (managed) connection
- * APIs. We need some form of event notification at the app level for
- * unsolicited notifications.
- * <li>method for performing update operation (e.g. LDIF change
- * records).
- * <li>should unsupported methods throw UnsupportedOperationException or
- * throw an ErrorResultException using an UnwillingToPerform result code
- * (or something similar)?
- * <li>Implementations should indicate whether or not they are thread
- * safe and support concurrent requests.
- * </ul>
+ * Applications can choose to be notified when a connection is closed by the
+ * application, receives an unsolicited notification, or experiences a fatal
+ * error by registering a {@link ConnectionEventListener} with the connection
+ * using the {@link #addConnectionEventListener} method.
  *
- * @see <a href="http://tools.ietf.org/html/rfc4511">RFC 4511 -
- *      Lightweight Directory Access Protocol (LDAP): The Protocol </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4511">RFC 4511 - Lightweight
+ *      Directory Access Protocol (LDAP): The Protocol </a>
  */
 public interface AsynchronousConnection extends Closeable
 {
 
   /**
-   * Abandons the unfinished operation identified in the provided
-   * abandon request.
+   * Abandons the unfinished operation identified in the provided abandon
+   * request.
    * <p>
-   * <b>Note:</b> a more convenient approach to abandoning unfinished
-   * operations is provided via the {@link FutureResult#cancel(boolean)}
-   * method.
+   * Since abandon requests do not have a response, invoking the method {@code
+   * get()} on the returned future will not block, nor return anything (it is
+   * {@code Void}), but may throw an exception if a problem occurred while
+   * sending the abandon request.
+   * <p>
+   * <b>Note:</b> a more convenient approach to abandoning unfinished operations
+   * is provided via the {@link FutureResult#cancel(boolean)} method.
    *
    * @param request
    *          The request identifying the operation to be abandoned.
+   * @return An future whose result is {@code Void}.
    * @throws UnsupportedOperationException
    *           If this connection does not support abandon operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
-  void abandon(AbandonRequest request)
+  FutureResult<Void> abandon(AbandonRequest request)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException;
 
 
 
   /**
-   * Adds an entry to the Directory Server using the provided add
-   * request.
+   * Adds an entry to the Directory Server using the provided add request. Any
+   * intermediate responses will be ignored.
    *
    * @param request
    *          The add request.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support add operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
+   * @throws NullPointerException
+   *           If {@code request} was {@code null}.
+   */
+  FutureResult<Result> add(AddRequest request, ResultHandler<Result> handler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException;
+
+
+
+  /**
+   * Adds an entry to the Directory Server using the provided add request.
+   *
+   * @param request
+   *          The add request.
+   * @param resultHandler
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   * @param intermediateResponseHandler
+   *          An intermediate response handler which can be used to process any
+   *          intermediate responses as they are received, may be {@code null}.
+   * @return A future representing the result of the operation.
+   * @throws UnsupportedOperationException
+   *           If this connection does not support add operations.
+   * @throws IllegalStateException
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
   FutureResult<Result> add(AddRequest request,
-      ResultHandler<Result> handler)
+      ResultHandler<Result> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException;
 
@@ -189,15 +199,15 @@
 
   /**
    * Registers the provided connection event listener so that it will be
-   * notified when this connection is closed by the application,
-   * receives an unsolicited notification, or experiences a fatal error.
+   * notified when this connection is closed by the application, receives an
+   * unsolicited notification, or experiences a fatal error.
    *
    * @param listener
-   *          The listener which wants to be notified when events occur
-   *          on this connection.
+   *          The listener which wants to be notified when events occur on this
+   *          connection.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If the {@code listener} was {@code null}.
    */
@@ -207,21 +217,20 @@
 
 
   /**
-   * Authenticates to the Directory Server using the provided bind
-   * request.
+   * Authenticates to the Directory Server using the provided bind request. Any
+   * intermediate responses will be ignored.
    *
    * @param request
    *          The bind request.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support bind operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
@@ -233,14 +242,42 @@
 
 
   /**
-   * Releases any resources associated with this connection. For
-   * physical connections to a Directory Server this will mean that an
-   * unbind request is sent and the underlying socket is closed.
+   * Authenticates to the Directory Server using the provided bind request.
+   *
+   * @param request
+   *          The bind request.
+   * @param resultHandler
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   * @param intermediateResponseHandler
+   *          An intermediate response handler which can be used to process any
+   *          intermediate responses as they are received, may be {@code null}.
+   * @return A future representing the result of the operation.
+   * @throws UnsupportedOperationException
+   *           If this connection does not support bind operations.
+   * @throws IllegalStateException
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
+   * @throws NullPointerException
+   *           If {@code request} was {@code null}.
+   */
+  FutureResult<BindResult> bind(BindRequest request,
+      ResultHandler<? super BindResult> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException;
+
+
+
+  /**
+   * Releases any resources associated with this connection. For physical
+   * connections to a Directory Server this will mean that an unbind request is
+   * sent and the underlying socket is closed.
    * <p>
-   * Other connection implementations may behave differently, and may
-   * choose not to send an unbind request if its use is inappropriate
-   * (for example a pooled connection will be released and returned to
-   * its connection pool without ever issuing an unbind request).
+   * Other connection implementations may behave differently, and may choose not
+   * to send an unbind request if its use is inappropriate (for example a pooled
+   * connection will be released and returned to its connection pool without
+   * ever issuing an unbind request).
    * <p>
    * This method is semantically equivalent to the following code:
    *
@@ -249,56 +286,51 @@
    * connection.close(request);
    * </pre>
    *
-   * Calling {@code close} on a connection that is already closed has no
-   * effect.
+   * Calling {@code close} on a connection that is already closed has no effect.
    */
   void close();
 
 
 
   /**
-   * Releases any resources associated with this connection. For
-   * physical connections to a Directory Server this will mean that the
-   * provided unbind request is sent and the underlying socket is
-   * closed.
+   * Releases any resources associated with this connection. For physical
+   * connections to a Directory Server this will mean that the provided unbind
+   * request is sent and the underlying socket is closed.
    * <p>
-   * Other connection implementations may behave differently, and may
-   * choose to ignore the provided unbind request if its use is
-   * inappropriate (for example a pooled connection will be released and
-   * returned to its connection pool without ever issuing an unbind
-   * request).
+   * Other connection implementations may behave differently, and may choose to
+   * ignore the provided unbind request if its use is inappropriate (for example
+   * a pooled connection will be released and returned to its connection pool
+   * without ever issuing an unbind request).
    * <p>
-   * Calling {@code close} on a connection that is already closed has no
-   * effect.
+   * Calling {@code close} on a connection that is already closed has no effect.
    *
    * @param request
-   *          The unbind request to use in the case where a physical
-   *          connection is closed.
+   *          The unbind request to use in the case where a physical connection
+   *          is closed.
    * @param reason
    *          A reason describing why the connection was closed.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
-  void close(UnbindRequest request, String reason);
+  void close(UnbindRequest request, String reason) throws NullPointerException;
 
 
 
   /**
-   * Compares an entry in the Directory Server using the provided
-   * compare request.
+   * Compares an entry in the Directory Server using the provided compare
+   * request. Any intermediate responses will be ignored.
    *
    * @param request
    *          The compare request.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support compare operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
@@ -310,53 +342,108 @@
 
 
   /**
-   * Deletes an entry from the Directory Server using the provided
-   * delete request.
+   * Compares an entry in the Directory Server using the provided compare
+   * request.
    *
    * @param request
-   *          The delete request.
-   * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          The compare request.
+   * @param resultHandler
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   * @param intermediateResponseHandler
+   *          An intermediate response handler which can be used to process any
+   *          intermediate responses as they are received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
-   *           If this connection does not support delete operations.
+   *           If this connection does not support compare operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
-  FutureResult<Result> delete(DeleteRequest request,
-      ResultHandler<Result> handler)
+  FutureResult<CompareResult> compare(CompareRequest request,
+      ResultHandler<? super CompareResult> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException;
 
 
 
   /**
-   * Requests that the Directory Server performs the provided extended
+   * Deletes an entry from the Directory Server using the provided delete
+   * request. Any intermediate responses will be ignored.
+   *
+   * @param request
+   *          The delete request.
+   * @param handler
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   * @return A future representing the result of the operation.
+   * @throws UnsupportedOperationException
+   *           If this connection does not support delete operations.
+   * @throws IllegalStateException
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
+   * @throws NullPointerException
+   *           If {@code request} was {@code null}.
+   */
+  FutureResult<Result> delete(DeleteRequest request,
+      ResultHandler<Result> handler) throws UnsupportedOperationException,
+      IllegalStateException, NullPointerException;
+
+
+
+  /**
+   * Deletes an entry from the Directory Server using the provided delete
    * request.
    *
+   * @param request
+   *          The delete request.
+   * @param resultHandler
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   * @param intermediateResponseHandler
+   *          An intermediate response handler which can be used to process any
+   *          intermediate responses as they are received, may be {@code null}.
+   * @return A future representing the result of the operation.
+   * @throws UnsupportedOperationException
+   *           If this connection does not support delete operations.
+   * @throws IllegalStateException
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
+   * @throws NullPointerException
+   *           If {@code request} was {@code null}.
+   */
+  FutureResult<Result> delete(DeleteRequest request,
+      ResultHandler<Result> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException;
+
+
+
+  /**
+   * Requests that the Directory Server performs the provided extended request.
+   * Any intermediate responses will be ignored.
+   *
    * @param <R>
    *          The type of result returned by the extended request.
    * @param request
    *          The extended request.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support extended operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
-  <R extends Result> FutureResult<R> extendedRequest(
+  <R extends ExtendedResult> FutureResult<R> extendedRequest(
       ExtendedRequest<R> request, ResultHandler<? super R> handler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException;
@@ -364,20 +451,63 @@
 
 
   /**
-   * Indicates whether or not this connection has been explicitly closed
-   * by calling {@code close}. This method will not return {@code true}
-   * if a fatal error has occurred on the connection unless {@code
-   * close} has been called.
+   * Requests that the Directory Server performs the provided extended request.
    *
-   * @return {@code true} if this connection has been explicitly closed
-   *         by calling {@code close}, or {@code false} otherwise.
+   * @param <R>
+   *          The type of result returned by the extended request.
+   * @param request
+   *          The extended request.
+   * @param resultHandler
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   * @param intermediateResponseHandler
+   *          An intermediate response handler which can be used to process any
+   *          intermediate responses as they are received, may be {@code null}.
+   * @return A future representing the result of the operation.
+   * @throws UnsupportedOperationException
+   *           If this connection does not support extended operations.
+   * @throws IllegalStateException
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
+   * @throws NullPointerException
+   *           If {@code request} was {@code null}.
+   */
+  <R extends ExtendedResult> FutureResult<R> extendedRequest(
+      ExtendedRequest<R> request, ResultHandler<? super R> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException;
+
+
+
+  /**
+   * Returns a synchronous connection sharing the same underlying network
+   * connection as this asynchronous connection.
+   *
+   * @return A synchronous connection sharing the same underlying network
+   *         connection as this asynchronous connection.
+   */
+  Connection getSynchronousConnection();
+
+
+
+  /**
+   * Indicates whether or not this connection has been explicitly closed by
+   * calling {@code close}. This method will not return {@code true} if a fatal
+   * error has occurred on the connection unless {@code close} has been called.
+   *
+   * @return {@code true} if this connection has been explicitly closed by
+   *         calling {@code close}, or {@code false} otherwise.
    */
   boolean isClosed();
 
 
 
   /**
-   * Returns true if the connection has not been closed and is still valid.
+   * Returns {@code true} if this connection has not been closed and no fatal
+   * errors have been detected. This method is guaranteed to return {@code
+   * false} only when it is called after the method {@code close} has been
+   * called.
    *
    * @return {@code true} if the connection is valid, {@code false} otherwise.
    */
@@ -387,51 +517,105 @@
 
   /**
    * Modifies an entry in the Directory Server using the provided modify
-   * request.
+   * request. Any intermediate responses will be ignored.
    *
    * @param request
    *          The modify request.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support modify operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
   FutureResult<Result> modify(ModifyRequest request,
-      ResultHandler<Result> handler)
+      ResultHandler<Result> handler) throws UnsupportedOperationException,
+      IllegalStateException, NullPointerException;
+
+
+
+  /**
+   * Modifies an entry in the Directory Server using the provided modify
+   * request.
+   *
+   * @param request
+   *          The modify request.
+   * @param resultHandler
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   * @param intermediateResponseHandler
+   *          An intermediate response handler which can be used to process any
+   *          intermediate responses as they are received, may be {@code null}.
+   * @return A future representing the result of the operation.
+   * @throws UnsupportedOperationException
+   *           If this connection does not support modify operations.
+   * @throws IllegalStateException
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
+   * @throws NullPointerException
+   *           If {@code request} was {@code null}.
+   */
+  FutureResult<Result> modify(ModifyRequest request,
+      ResultHandler<Result> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException;
 
 
 
   /**
-   * Renames an entry in the Directory Server using the provided modify
-   * DN request.
+   * Renames an entry in the Directory Server using the provided modify DN
+   * request. Any intermediate responses will be ignored.
    *
    * @param request
    *          The modify DN request.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support modify DN operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
   FutureResult<Result> modifyDN(ModifyDNRequest request,
-      ResultHandler<Result> handler)
+      ResultHandler<Result> handler) throws UnsupportedOperationException,
+      IllegalStateException, NullPointerException;
+
+
+
+  /**
+   * Renames an entry in the Directory Server using the provided modify DN
+   * request.
+   *
+   * @param request
+   *          The modify DN request.
+   * @param resultHandler
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   * @param intermediateResponseHandler
+   *          An intermediate response handler which can be used to process any
+   *          intermediate responses as they are received, may be {@code null}.
+   * @return A future representing the result of the operation.
+   * @throws UnsupportedOperationException
+   *           If this connection does not support modify DN operations.
+   * @throws IllegalStateException
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
+   * @throws NullPointerException
+   *           If {@code request} was {@code null}.
+   */
+  FutureResult<Result> modifyDN(ModifyDNRequest request,
+      ResultHandler<Result> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException;
 
@@ -440,34 +624,33 @@
   /**
    * Reads the named entry from the Directory Server.
    * <p>
-   * If the requested entry is not returned by the Directory Server then
-   * the request will fail with an {@link EntryNotFoundException}. More
+   * If the requested entry is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
    * specifically, the returned future will never return {@code null}.
    * <p>
    * This method is equivalent to the following code:
    *
    * <pre>
-   * SearchRequest request = new SearchRequest(name,
-   *     SearchScope.BASE_OBJECT, &quot;(objectClass=*)&quot;, attributeDescriptions);
+   * SearchRequest request = new SearchRequest(name, SearchScope.BASE_OBJECT,
+   *     &quot;(objectClass=*)&quot;, attributeDescriptions);
    * connection.searchSingleEntry(request, resultHandler, p);
    * </pre>
    *
    * @param name
    *          The distinguished name of the entry to be read.
    * @param attributeDescriptions
-   *          The names of the attributes to be included with the entry,
-   *          which may be {@code null} or empty indicating that all
-   *          user attributes should be returned.
+   *          The names of the attributes to be included with the entry, which
+   *          may be {@code null} or empty indicating that all user attributes
+   *          should be returned.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If the {@code name} was {@code null}.
    */
@@ -482,20 +665,19 @@
   /**
    * Reads the Root DSE from the Directory Server.
    * <p>
-   * If the Root DSE is not returned by the Directory Server then the
-   * request will fail with an {@link EntryNotFoundException}. More
-   * specifically, the returned future will never return {@code null}.
+   * If the Root DSE is not returned by the Directory Server then the request
+   * will fail with an {@link EntryNotFoundException}. More specifically, the
+   * returned future will never return {@code null}.
    *
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    */
   FutureResult<RootDSE> readRootDSE(ResultHandler<RootDSE> handler)
       throws UnsupportedOperationException, IllegalStateException;
@@ -503,29 +685,26 @@
 
 
   /**
-   * Reads the schema from the Directory Server contained in the named
-   * subschema sub-entry.
+   * Reads the schema from the Directory Server contained in the named subschema
+   * sub-entry.
    * <p>
-   * If the requested schema is not returned by the Directory Server
-   * then the request will fail with an {@link EntryNotFoundException}.
-   * More specifically, the returned future will never return {@code
-   * null}.
+   * If the requested schema is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
+   * specifically, the returned future will never return {@code null}.
    * <p>
-   * Implementations may choose to perform optimizations such as
-   * caching.
+   * Implementations may choose to perform optimizations such as caching.
    *
    * @param name
    *          The distinguished name of the subschema sub-entry.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    */
   FutureResult<Schema> readSchema(DN name, ResultHandler<Schema> handler)
       throws UnsupportedOperationException, IllegalStateException;
@@ -533,48 +712,45 @@
 
 
   /**
-   * Reads the schema from the Directory Server which applies to the
-   * named entry.
+   * Reads the schema from the Directory Server which applies to the named
+   * entry.
    * <p>
-   * If the requested entry or its associated schema are not returned by
-   * the Directory Server then the request will fail with an
-   * {@link EntryNotFoundException}. More specifically, the returned
-   * future will never return {@code null}.
+   * If the requested entry or its associated schema are not returned by the
+   * Directory Server then the request will fail with an
+   * {@link EntryNotFoundException}. More specifically, the returned future will
+   * never return {@code null}.
    * <p>
-   * A typical implementation will first read the {@code
-   * subschemaSubentry} attribute of the entry in order to locate the
-   * schema. However, implementations may choose to perform other
-   * optimizations, such as caching.
+   * A typical implementation will first read the {@code subschemaSubentry}
+   * attribute of the entry in order to locate the schema. However,
+   * implementations may choose to perform other optimizations, such as caching.
    *
    * @param name
-   *          The distinguished name of the entry whose schema is to be
-   *          located.
+   *          The distinguished name of the entry whose schema is to be located.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}. Optional additional handler parameter.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   *          Optional additional handler parameter.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    */
-  FutureResult<Schema> readSchemaForEntry(DN name,
-      ResultHandler<Schema> handler)
+  FutureResult<Schema> readSchemaForEntry(DN name, ResultHandler<Schema> handler)
       throws UnsupportedOperationException, IllegalStateException;
 
 
 
   /**
-   * Removes the provided connection event listener from this connection
-   * so that it will no longer be notified when this connection is
-   * closed by the application, receives an unsolicited notification, or
-   * experiences a fatal error.
+   * Removes the provided connection event listener from this connection so that
+   * it will no longer be notified when this connection is closed by the
+   * application, receives an unsolicited notification, or experiences a fatal
+   * error.
    *
    * @param listener
-   *          The listener which no longer wants to be notified when
-   *          events occur on this connection.
+   *          The listener which no longer wants to be notified when events
+   *          occur on this connection.
    * @throws NullPointerException
    *           If the {@code listener} was {@code null}.
    */
@@ -584,24 +760,24 @@
 
 
   /**
-   * Searches the Directory Server using the provided search request.
+   * Searches the Directory Server using the provided search request. Any
+   * intermediate responses will be ignored.
    *
    * @param request
    *          The search request.
    * @param resultHandler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @param searchResulthandler
-   *          A search result handler which can be used to
-   *          asynchronously process the search result entries and
-   *          references as they are received, may be {@code null}.
+   *          A search result handler which can be used to asynchronously
+   *          process the search result entries and references as they are
+   *          received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
@@ -614,33 +790,63 @@
 
 
   /**
-   * Searches the Directory Server for a single entry using the provided
-   * search request.
-   * <p>
-   * If the requested entry is not returned by the Directory Server then
-   * the request will fail with an {@link EntryNotFoundException}. More
-   * specifically, the returned future will never return {@code null}.
-   * If multiple matching entries are returned by the Directory Server
-   * then the request will fail with an
-   * {@link MultipleEntriesFoundException}.
+   * Searches the Directory Server using the provided search request.
    *
    * @param request
    *          The search request.
-   * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   * @param resultHandler
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   * @param searchResulthandler
+   *          A search result handler which can be used to asynchronously
+   *          process the search result entries and references as they are
+   *          received, may be {@code null}.
+   * @param intermediateResponseHandler
+   *          An intermediate response handler which can be used to process any
+   *          intermediate responses as they are received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
+   * @throws NullPointerException
+   *           If {@code request} was {@code null}.
+   */
+  FutureResult<Result> search(SearchRequest request,
+      ResultHandler<Result> resultHandler,
+      SearchResultHandler searchResulthandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException, IllegalStateException,
+      NullPointerException;
+
+
+
+  /**
+   * Searches the Directory Server for a single entry using the provided search
+   * request.
+   * <p>
+   * If the requested entry is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
+   * specifically, the returned future will never return {@code null}. If
+   * multiple matching entries are returned by the Directory Server then the
+   * request will fail with an {@link MultipleEntriesFoundException}.
+   *
+   * @param request
+   *          The search request.
+   * @param handler
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
+   * @return A future representing the result of the operation.
+   * @throws UnsupportedOperationException
+   *           If this connection does not support search operations.
+   * @throws IllegalStateException
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If the {@code request} was {@code null}.
    */
-  FutureResult<SearchResultEntry> searchSingleEntry(
-      SearchRequest request,
+  FutureResult<SearchResultEntry> searchSingleEntry(SearchRequest request,
       ResultHandler<? super SearchResultEntry> handler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException;
diff --git a/sdk/src/org/opends/sdk/Attribute.java b/sdk/src/org/opends/sdk/Attribute.java
index b070f70..42d2439 100644
--- a/sdk/src/org/opends/sdk/Attribute.java
+++ b/sdk/src/org/opends/sdk/Attribute.java
@@ -40,12 +40,11 @@
  * An attribute, comprising of an attribute description and zero or more
  * attribute values.
  * <p>
- * Any methods which perform comparisons between attribute values use
- * the equality matching rule associated with the attribute description.
+ * Any methods which perform comparisons between attribute values use the
+ * equality matching rule associated with the attribute description.
  * <p>
- * Any methods which accept {@code Object} based attribute values
- * convert the attribute values to instances of {@code ByteString} as
- * follows:
+ * Any methods which accept {@code Object} based attribute values convert the
+ * attribute values to instances of {@code ByteString} as follows:
  *
  * <pre>
  * Object object = ...;
@@ -65,18 +64,15 @@
 public interface Attribute extends Set<ByteString>
 {
   /**
-   * Adds {@code value} to this attribute if it is not already present
-   * (optional operation). If this attribute already contains {@code
-   * value}, the call leaves the attribute unchanged and returns {@code
-   * false}.
+   * Adds {@code value} to this attribute if it is not already present (optional
+   * operation). If this attribute already contains {@code value}, the call
+   * leaves the attribute unchanged and returns {@code false}.
    *
    * @param value
    *          The attribute value to be added to this attribute.
-   * @return {@code true} if this attribute changed as a result of this
-   *         call.
+   * @return {@code true} if this attribute changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this attribute does not support addition of attribute
-   *           values.
+   *           If this attribute does not support addition of attribute values.
    * @throws NullPointerException
    *           If {@code value} was {@code null}.
    */
@@ -86,23 +82,19 @@
 
 
   /**
-   * Adds all of the provided attribute values to this attribute if they
-   * are not already present (optional operation).
+   * Adds all of the provided attribute values to this attribute if they are not
+   * already present (optional operation).
    * <p>
-   * Any attribute values which are not instances of {@code ByteString}
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param firstValue
    *          The first attribute value to be added to this attribute.
    * @param remainingValues
-   *          The remaining attribute values to be added to this
-   *          attribute.
-   * @return {@code true} if this attribute changed as a result of this
-   *         call.
+   *          The remaining attribute values to be added to this attribute.
+   * @return {@code true} if this attribute changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this attribute does not support addition of attribute
-   *           values.
+   *           If this attribute does not support addition of attribute values.
    * @throws NullPointerException
    *           If {@code firstValue} was {@code null}.
    */
@@ -112,9 +104,8 @@
 
 
   /**
-   * Adds all of the attribute values contained in {@code values} to
-   * this attribute if they are not already present (optional
-   * operation).
+   * Adds all of the attribute values contained in {@code values} to this
+   * attribute if they are not already present (optional operation).
    * <p>
    * An invocation of this method is equivalent to:
    *
@@ -124,11 +115,9 @@
    *
    * @param values
    *          The attribute values to be added to this attribute.
-   * @return {@code true} if this attribute changed as a result of this
-   *         call.
+   * @return {@code true} if this attribute changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this attribute does not support addition of attribute
-   *           values.
+   *           If this attribute does not support addition of attribute values.
    * @throws NullPointerException
    *           If {@code values} was {@code null}.
    */
@@ -138,21 +127,19 @@
 
 
   /**
-   * Adds all of the attribute values contained in {@code values} to
-   * this attribute if they are not already present (optional
-   * operation). Any attribute values which are already present will be
-   * added to {@code duplicateValues} if specified.
+   * Adds all of the attribute values contained in {@code values} to this
+   * attribute if they are not already present (optional operation). Any
+   * attribute values which are already present will be added to {@code
+   * duplicateValues} if specified.
    *
    * @param values
    *          The attribute values to be added to this attribute.
    * @param duplicateValues
-   *          A collection into which duplicate values will be added, or
-   *          {@code null} if duplicate values should not be saved.
-   * @return {@code true} if this attribute changed as a result of this
-   *         call.
+   *          A collection into which duplicate values will be added, or {@code
+   *          null} if duplicate values should not be saved.
+   * @return {@code true} if this attribute changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this attribute does not support addition of attribute
-   *           values.
+   *           If this attribute does not support addition of attribute values.
    * @throws NullPointerException
    *           If {@code values} was {@code null}.
    */
@@ -165,6 +152,9 @@
   /**
    * Removes all of the attribute values from this attribute (optional
    * operation). This attribute will be empty after this call returns.
+   *
+   * @throws UnsupportedOperationException
+   *           If this attribute does not support removal of attribute values.
    */
   void clear() throws UnsupportedOperationException;
 
@@ -173,15 +163,14 @@
   /**
    * Returns {@code true} if this attribute contains {@code value}.
    * <p>
-   * If {@code value} is not an instance of {@code ByteString} then it
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * If {@code value} is not an instance of {@code ByteString} then it will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param value
-   *          The attribute value whose presence in this attribute is to
-   *          be tested.
-   * @return {@code true} if this attribute contains {@code value}, or
-   *         {@code false} if not.
+   *          The attribute value whose presence in this attribute is to be
+   *          tested.
+   * @return {@code true} if this attribute contains {@code value}, or {@code
+   *         false} if not.
    * @throws NullPointerException
    *           If {@code value} was {@code null}.
    */
@@ -190,19 +179,17 @@
 
 
   /**
-   * Returns {@code true} if this attribute contains all of the
-   * attribute values contained in {@code values}.
+   * Returns {@code true} if this attribute contains all of the attribute values
+   * contained in {@code values}.
    * <p>
-   * Any attribute values which are not instances of {@code ByteString}
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param values
-   *          The attribute values whose presence in this attribute is
-   *          to be tested.
-   * @return {@code true} if this attribute contains all of the
-   *         attribute values contained in {@code values}, or {@code
-   *         false} if not.
+   *          The attribute values whose presence in this attribute is to be
+   *          tested.
+   * @return {@code true} if this attribute contains all of the attribute values
+   *         contained in {@code values}, or {@code false} if not.
    * @throws NullPointerException
    *           If {@code values} was {@code null}.
    */
@@ -211,16 +198,16 @@
 
 
   /**
-   * Returns {@code true} if {@code object} is an attribute which is
-   * equal to this attribute. Two attributes are considered equal if
-   * their attribute descriptions are equal, they both have the same
-   * number of attribute values, and every attribute value contained in
-   * the first attribute is also contained in the second attribute.
+   * Returns {@code true} if {@code object} is an attribute which is equal to
+   * this attribute. Two attributes are considered equal if their attribute
+   * descriptions are equal, they both have the same number of attribute values,
+   * and every attribute value contained in the first attribute is also
+   * contained in the second attribute.
    *
    * @param object
    *          The object to be tested for equality with this attribute.
-   * @return {@code true} if {@code object} is an attribute which is
-   *         equal to this attribute, or {@code false} if not.
+   * @return {@code true} if {@code object} is an attribute which is equal to
+   *         this attribute, or {@code false} if not.
    */
   boolean equals(Object object);
 
@@ -238,11 +225,11 @@
 
 
   /**
-   * Returns the first attribute value in this attribute decoded as a
-   * UTF-8 string.
+   * Returns the first attribute value in this attribute decoded as a UTF-8
+   * string.
    *
-   * @return The first attribute value in this attribute decoded as a
-   *         UTF-8 string.
+   * @return The first attribute value in this attribute decoded as a UTF-8
+   *         string.
    * @throws NoSuchElementException
    *           If this attribute is empty.
    */
@@ -251,8 +238,8 @@
 
 
   /**
-   * Returns the attribute description of this attribute, which includes
-   * its attribute type and any options.
+   * Returns the attribute description of this attribute, which includes its
+   * attribute type and any options.
    *
    * @return The attribute description.
    */
@@ -261,8 +248,8 @@
 
 
   /**
-   * Returns the string representation of the attribute description of
-   * this attribute, which includes its attribute type and any options.
+   * Returns the string representation of the attribute description of this
+   * attribute, which includes its attribute type and any options.
    *
    * @return The string representation of the attribute description.
    */
@@ -271,9 +258,9 @@
 
 
   /**
-   * Returns the hash code for this attribute. It will be calculated as
-   * the sum of the hash codes of the attribute description and all of
-   * the attribute values.
+   * Returns the hash code for this attribute. It will be calculated as the sum
+   * of the hash codes of the attribute description and all of the attribute
+   * values.
    *
    * @return The hash code for this attribute.
    */
@@ -282,20 +269,18 @@
 
 
   /**
-   * Returns {@code true} if this attribute contains no attribute
-   * values.
+   * Returns {@code true} if this attribute contains no attribute values.
    *
-   * @return {@code true} if this attribute contains no attribute
-   *         values.
+   * @return {@code true} if this attribute contains no attribute values.
    */
   boolean isEmpty();
 
 
 
   /**
-   * Returns an iterator over the attribute values in this attribute.
-   * The attribute values are returned in no particular order, unless
-   * the implementation of this attribute provides such a guarantee.
+   * Returns an iterator over the attribute values in this attribute. The
+   * attribute values are returned in no particular order, unless the
+   * implementation of this attribute provides such a guarantee.
    *
    * @return An iterator over the attribute values in this attribute.
    */
@@ -304,22 +289,18 @@
 
 
   /**
-   * Removes {@code value} from this attribute if it is present
-   * (optional operation). If this attribute does not contain {@code
-   * value}, the call leaves the attribute unchanged and returns {@code
-   * false}.
+   * Removes {@code value} from this attribute if it is present (optional
+   * operation). If this attribute does not contain {@code value}, the call
+   * leaves the attribute unchanged and returns {@code false}.
    * <p>
-   * If {@code value} is not an instance of {@code ByteString} then it
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * If {@code value} is not an instance of {@code ByteString} then it will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param value
    *          The attribute value to be removed from this attribute.
-   * @return {@code true} if this attribute changed as a result of this
-   *         call.
+   * @return {@code true} if this attribute changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this attribute does not support removal of attribute
-   *           values.
+   *           If this attribute does not support removal of attribute values.
    * @throws NullPointerException
    *           If {@code value} was {@code null}.
    */
@@ -329,12 +310,11 @@
 
 
   /**
-   * Removes all of the attribute values contained in {@code values}
-   * from this attribute if they are present (optional operation).
+   * Removes all of the attribute values contained in {@code values} from this
+   * attribute if they are present (optional operation).
    * <p>
-   * Any attribute values which are not instances of {@code ByteString}
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    * <p>
    * An invocation of this method is equivalent to:
    *
@@ -344,41 +324,36 @@
    *
    * @param values
    *          The attribute values to be removed from this attribute.
-   * @return {@code true} if this attribute changed as a result of this
-   *         call.
+   * @return {@code true} if this attribute changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this attribute does not support removal of attribute
-   *           values.
+   *           If this attribute does not support removal of attribute values.
    * @throws NullPointerException
    *           If {@code values} was {@code null}.
    */
-  boolean removeAll(Collection<?> values)
-      throws UnsupportedOperationException, NullPointerException;
+  boolean removeAll(Collection<?> values) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Removes all of the attribute values contained in {@code values}
-   * from this attribute if they are present (optional operation). Any
-   * attribute values which are not already present will be added to
-   * {@code missingValues} if specified.
+   * Removes all of the attribute values contained in {@code values} from this
+   * attribute if they are present (optional operation). Any attribute values
+   * which are not already present will be added to {@code missingValues} if
+   * specified.
    * <p>
-   * Any attribute values which are not instances of {@code ByteString}
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param <T>
    *          The type of the attribute value objects being removed.
    * @param values
    *          The attribute values to be removed from this attribute.
    * @param missingValues
-   *          A collection into which missing values will be added, or
-   *          {@code null} if missing values should not be saved.
-   * @return {@code true} if this attribute changed as a result of this
-   *         call.
+   *          A collection into which missing values will be added, or {@code
+   *          null} if missing values should not be saved.
+   * @return {@code true} if this attribute changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this attribute does not support removal of attribute
-   *           values.
+   *           If this attribute does not support removal of attribute values.
    * @throws NullPointerException
    *           If {@code values} was {@code null}.
    */
@@ -389,12 +364,11 @@
 
 
   /**
-   * Retains only the attribute values in this attribute which are
-   * contained in {@code values} (optional operation).
+   * Retains only the attribute values in this attribute which are contained in
+   * {@code values} (optional operation).
    * <p>
-   * Any attribute values which are not instances of {@code ByteString}
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    * <p>
    * An invocation of this method is equivalent to:
    *
@@ -404,41 +378,35 @@
    *
    * @param values
    *          The attribute values to be retained in this attribute.
-   * @return {@code true} if this attribute changed as a result of this
-   *         call.
+   * @return {@code true} if this attribute changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this attribute does not support removal of attribute
-   *           values.
+   *           If this attribute does not support removal of attribute values.
    * @throws NullPointerException
    *           If {@code values} was {@code null}.
    */
-  boolean retainAll(Collection<?> values)
-      throws UnsupportedOperationException, NullPointerException;
+  boolean retainAll(Collection<?> values) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Retains only the attribute values in this attribute which are
-   * contained in {@code values} (optional operation). Any attribute
-   * values which are not already present will be added to {@code
-   * missingValues} if specified.
+   * Retains only the attribute values in this attribute which are contained in
+   * {@code values} (optional operation). Any attribute values which are not
+   * already present will be added to {@code missingValues} if specified.
    * <p>
-   * Any attribute values which are not instances of {@code ByteString}
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param <T>
    *          The type of the attribute value objects being retained.
    * @param values
    *          The attribute values to be retained in this attribute.
    * @param missingValues
-   *          A collection into which missing values will be added, or
-   *          {@code null} if missing values should not be saved.
-   * @return {@code true} if this attribute changed as a result of this
-   *         call.
+   *          A collection into which missing values will be added, or {@code
+   *          null} if missing values should not be saved.
+   * @return {@code true} if this attribute changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this attribute does not support removal of attribute
-   *           values.
+   *           If this attribute does not support removal of attribute values.
    * @throws NullPointerException
    *           If {@code values} was {@code null}.
    */
@@ -458,45 +426,52 @@
 
 
   /**
-   * Returns an array containing all of the attribute values contained
-   * in this attribute.
+   * Returns an array containing all of the attribute values contained in this
+   * attribute.
    * <p>
-   * If this attribute makes any guarantees as to what order its
-   * attribute values are returned by its iterator, this method must
-   * return the attribute values in the same order.
+   * If this attribute makes any guarantees as to what order its attribute
+   * values are returned by its iterator, this method must return the attribute
+   * values in the same order.
    * <p>
    * The returned array will be "safe" in that no references to it are
    * maintained by this attribute. The caller is thus free to modify the
    * returned array.
+   *
+   * @return An array containing all of the attribute values contained in this
+   *         attribute.
    */
   ByteString[] toArray();
 
 
 
   /**
-   * Returns an array containing all of the attribute values in this
-   * attribute; the runtime type of the returned array is that of the
-   * specified array.
+   * Returns an array containing all of the attribute values in this attribute;
+   * the runtime type of the returned array is that of the specified array.
    * <p>
-   * If the set fits in the specified array, it is returned therein.
-   * Otherwise, a new array is allocated with the runtime type of the
-   * specified array and the size of this attribute. If this attribute
-   * fits in the specified array with room to spare (i.e., the array has
-   * more elements than this attribute), the elements in the array
-   * immediately following the end of the set is set to {@code null}.
+   * If the set fits in the specified array, it is returned therein. Otherwise,
+   * a new array is allocated with the runtime type of the specified array and
+   * the size of this attribute. If this attribute fits in the specified array
+   * with room to spare (i.e., the array has more elements than this attribute),
+   * the elements in the array immediately following the end of the set is set
+   * to {@code null}.
    * <p>
-   * If this attribute makes any guarantees as to what order its
-   * attribute values are returned by its iterator, this method must
-   * return the attribute values in the same order.
+   * If this attribute makes any guarantees as to what order its attribute
+   * values are returned by its iterator, this method must return the attribute
+   * values in the same order.
    *
+   * @param <T>
+   *          The type of elements contained in {@code array}.
+   * @param array
+   *          An array into which the elements of this attribute should be put.
+   * @return An array containing all of the attribute values contained in this
+   *         attribute.
    * @throws ArrayStoreException
-   *           If the runtime type of {@code array} is not a supertype
-   *           of {@code ByteString}.
+   *           If the runtime type of {@code array} is not a supertype of
+   *           {@code ByteString}.
    * @throws NullPointerException
    *           If {@code array} was {@code null}.
    */
-  <T> T[] toArray(T[] array) throws ArrayStoreException,
-      NullPointerException;
+  <T> T[] toArray(T[] array) throws ArrayStoreException, NullPointerException;
 
 
 
diff --git a/sdk/src/org/opends/sdk/AttributeDescription.java b/sdk/src/org/opends/sdk/AttributeDescription.java
index d02fe25..07d3e22 100644
--- a/sdk/src/org/opends/sdk/AttributeDescription.java
+++ b/sdk/src/org/opends/sdk/AttributeDescription.java
@@ -30,7 +30,7 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
 
 import java.util.*;
 
@@ -38,19 +38,20 @@
 import org.opends.sdk.schema.Schema;
 import org.opends.sdk.schema.UnknownSchemaElementException;
 
-import com.sun.opends.sdk.util.*;
+import com.sun.opends.sdk.util.ASCIICharProp;
+import com.sun.opends.sdk.util.Iterators;
+import com.sun.opends.sdk.util.Validator;
 
 
 
 /**
- * An attribute description as defined in RFC 4512 section 2.5.
- * Attribute descriptions are used to identify an attribute in an entry
- * and are composed of an attribute type and a set of zero or more
- * attribute options.
+ * An attribute description as defined in RFC 4512 section 2.5. Attribute
+ * descriptions are used to identify an attribute in an entry and are composed
+ * of an attribute type and a set of zero or more attribute options.
  *
- * @see <a href="http://tools.ietf.org/html/rfc4512#section-2.5">RFC
- *      4512 - Lightweight Directory Access Protocol (LDAP): Directory
- *      Information Models </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4512#section-2.5">RFC 4512 -
+ *      Lightweight Directory Access Protocol (LDAP): Directory Information
+ *      Models </a>
  */
 public final class AttributeDescription implements
     Comparable<AttributeDescription>
@@ -112,7 +113,8 @@
 
 
 
-    private MultiOptionImpl(String[] options, String[] normalizedOptions)
+    private MultiOptionImpl(final String[] options,
+        final String[] normalizedOptions)
     {
       if (normalizedOptions.length < 2)
       {
@@ -126,7 +128,7 @@
 
 
     @Override
-    public int compareTo(Impl other)
+    public int compareTo(final Impl other)
     {
       final int thisSize = normalizedOptions.length;
       final int otherSize = other.size();
@@ -162,7 +164,7 @@
 
 
     @Override
-    public boolean containsOption(String normalizedOption)
+    public boolean containsOption(final String normalizedOption)
     {
       final int sz = normalizedOptions.length;
       for (int i = 0; i < sz; i++)
@@ -178,7 +180,7 @@
 
 
     @Override
-    public boolean equals(Impl other)
+    public boolean equals(final Impl other)
     {
       if (other instanceof MultiOptionImpl)
       {
@@ -218,7 +220,7 @@
 
 
     @Override
-    public boolean isSubTypeOf(Impl other)
+    public boolean isSubTypeOf(final Impl other)
     {
       // Must contain a super-set of other's options.
       if (other == ZERO_OPTION_IMPL)
@@ -254,7 +256,7 @@
 
 
     @Override
-    public boolean isSuperTypeOf(Impl other)
+    public boolean isSuperTypeOf(final Impl other)
     {
       // Must contain a sub-set of other's options.
       for (final String normalizedOption : normalizedOptions)
@@ -295,7 +297,7 @@
 
 
 
-    private SingleOptionImpl(String option, String normalizedOption)
+    private SingleOptionImpl(final String option, final String normalizedOption)
     {
       this.option = option;
       this.normalizedOption = normalizedOption;
@@ -304,7 +306,7 @@
 
 
     @Override
-    public int compareTo(Impl other)
+    public int compareTo(final Impl other)
     {
       if (other == ZERO_OPTION_IMPL)
       {
@@ -314,8 +316,7 @@
       else if (other.size() == 1)
       {
         // Same number of options, so compare.
-        return normalizedOption
-            .compareTo(other.firstNormalizedOption());
+        return normalizedOption.compareTo(other.firstNormalizedOption());
       }
       else
       {
@@ -327,7 +328,7 @@
 
 
     @Override
-    public boolean containsOption(String normalizedOption)
+    public boolean containsOption(final String normalizedOption)
     {
       return this.normalizedOption.equals(normalizedOption);
     }
@@ -335,10 +336,9 @@
 
 
     @Override
-    public boolean equals(Impl other)
+    public boolean equals(final Impl other)
     {
-      return other.size() == 1
-          && other.containsOption(normalizedOption);
+      return other.size() == 1 && other.containsOption(normalizedOption);
     }
 
 
@@ -368,7 +368,7 @@
 
 
     @Override
-    public boolean isSubTypeOf(Impl other)
+    public boolean isSubTypeOf(final Impl other)
     {
       // Other must have no options or the same option.
       if (other == ZERO_OPTION_IMPL)
@@ -384,7 +384,7 @@
 
 
     @Override
-    public boolean isSuperTypeOf(Impl other)
+    public boolean isSuperTypeOf(final Impl other)
     {
       // Other must have this option.
       return other.containsOption(normalizedOption);
@@ -419,7 +419,7 @@
 
 
     @Override
-    public int compareTo(Impl other)
+    public int compareTo(final Impl other)
     {
       // If other has options then this sorts before.
       return this == other ? 0 : -1;
@@ -428,7 +428,7 @@
 
 
     @Override
-    public boolean containsOption(String normalizedOption)
+    public boolean containsOption(final String normalizedOption)
     {
       return false;
     }
@@ -436,7 +436,7 @@
 
 
     @Override
-    public boolean equals(Impl other)
+    public boolean equals(final Impl other)
     {
       return this == other;
     }
@@ -470,7 +470,7 @@
 
 
     @Override
-    public boolean isSubTypeOf(Impl other)
+    public boolean isSubTypeOf(final Impl other)
     {
       // Can only be a sub-type if other has no options.
       return this == other;
@@ -479,7 +479,7 @@
 
 
     @Override
-    public boolean isSuperTypeOf(Impl other)
+    public boolean isSuperTypeOf(final Impl other)
     {
       // Will always be a super-type.
       return true;
@@ -504,7 +504,9 @@
 
 
 
-  private static final ThreadLocal<WeakHashMap<Schema, Map<String, AttributeDescription>>> CACHE = new ThreadLocal<WeakHashMap<Schema, Map<String, AttributeDescription>>>()
+  private static final ThreadLocal<WeakHashMap<
+    Schema, Map<String, AttributeDescription>>> CACHE =
+      new ThreadLocal<WeakHashMap<Schema, Map<String, AttributeDescription>>>()
   {
 
     /**
@@ -526,8 +528,8 @@
   {
     final AttributeType attributeType = Schema.getCoreSchema()
         .getAttributeType("2.5.4.0");
-    OBJECT_CLASS = new AttributeDescription(attributeType
-        .getNameOrOID(), attributeType, ZERO_OPTION_IMPL);
+    OBJECT_CLASS = new AttributeDescription(attributeType.getNameOrOID(),
+        attributeType, ZERO_OPTION_IMPL);
   }
 
   // This is the size of the per-thread per-schema attribute description
@@ -538,9 +540,9 @@
 
 
   /**
-   * Creates an attribute description having the same attribute type and
-   * options as the provided attribute description and, in addition, the
-   * provided list of options.
+   * Creates an attribute description having the same attribute type and options
+   * as the provided attribute description and, in addition, the provided list
+   * of options.
    *
    * @param attributeDescription
    *          The attribute description.
@@ -548,11 +550,11 @@
    *          The attribute options.
    * @return The new attribute description containing {@code options}.
    * @throws NullPointerException
-   *           If {@code attributeDescription} or {@code options} was
-   *           {@code null}.
+   *           If {@code attributeDescription} or {@code options} was {@code
+   *           null}.
    */
   public static AttributeDescription create(
-      AttributeDescription attributeDescription, String... options)
+      final AttributeDescription attributeDescription, final String... options)
       throws NullPointerException
   {
     Validator.ensureNotNull(attributeDescription, options);
@@ -569,9 +571,9 @@
 
 
   /**
-   * Creates an attribute description having the same attribute type and
-   * options as the provided attribute description and, in addition, the
-   * provided new option.
+   * Creates an attribute description having the same attribute type and options
+   * as the provided attribute description and, in addition, the provided new
+   * option.
    *
    * @param attributeDescription
    *          The attribute description.
@@ -579,11 +581,11 @@
    *          The attribute option.
    * @return The new attribute description containing {@code option}.
    * @throws NullPointerException
-   *           If {@code attributeDescription} or {@code option} was
-   *           {@code null}.
+   *           If {@code attributeDescription} or {@code option} was {@code
+   *           null}.
    */
   public static AttributeDescription create(
-      AttributeDescription attributeDescription, String option)
+      final AttributeDescription attributeDescription, final String option)
       throws NullPointerException
   {
     Validator.ensureNotNull(attributeDescription, option);
@@ -595,8 +597,9 @@
     }
 
     final String oldAttributeDescription = attributeDescription.attributeDescription;
-    final StringBuilder builder = new StringBuilder(
-        oldAttributeDescription.length() + option.length() + 1);
+    final StringBuilder builder = new StringBuilder(oldAttributeDescription
+        .length()
+        + option.length() + 1);
     builder.append(oldAttributeDescription);
     builder.append(';');
     builder.append(option);
@@ -606,8 +609,8 @@
     if (impl instanceof ZeroOptionImpl)
     {
       return new AttributeDescription(newAttributeDescription,
-          attributeDescription.attributeType, new SingleOptionImpl(
-              option, normalizedOption));
+          attributeDescription.attributeType, new SingleOptionImpl(option,
+              normalizedOption));
 
     }
     else if (impl instanceof SingleOptionImpl)
@@ -626,8 +629,8 @@
       }
 
       return new AttributeDescription(newAttributeDescription,
-          attributeDescription.attributeType, new MultiOptionImpl(
-              newOptions, newNormalizedOptions));
+          attributeDescription.attributeType, new MultiOptionImpl(newOptions,
+              newNormalizedOptions));
     }
     else
     {
@@ -672,16 +675,16 @@
       }
 
       return new AttributeDescription(newAttributeDescription,
-          attributeDescription.attributeType, new MultiOptionImpl(
-              newOptions, newNormalizedOptions));
+          attributeDescription.attributeType, new MultiOptionImpl(newOptions,
+              newNormalizedOptions));
     }
   }
 
 
 
   /**
-   * Creates an attribute description having the provided attribute type
-   * and no options.
+   * Creates an attribute description having the provided attribute type and no
+   * options.
    *
    * @param attributeType
    *          The attribute type.
@@ -689,7 +692,7 @@
    * @throws NullPointerException
    *           If {@code attributeType} was {@code null}.
    */
-  public static AttributeDescription create(AttributeType attributeType)
+  public static AttributeDescription create(final AttributeType attributeType)
       throws NullPointerException
   {
     Validator.ensureNotNull(attributeType);
@@ -710,8 +713,8 @@
 
 
   /**
-   * Creates an attribute description having the provided attribute type
-   * and single option.
+   * Creates an attribute description having the provided attribute type and
+   * single option.
    *
    * @param attributeType
    *          The attribute type.
@@ -719,12 +722,10 @@
    *          The attribute option.
    * @return The attribute description.
    * @throws NullPointerException
-   *           If {@code attributeType} or {@code option} was {@code
-   *           null}.
+   *           If {@code attributeType} or {@code option} was {@code null}.
    */
-  public static AttributeDescription create(
-      AttributeType attributeType, String option)
-      throws NullPointerException
+  public static AttributeDescription create(final AttributeType attributeType,
+      final String option) throws NullPointerException
   {
     Validator.ensureNotNull(attributeType, option);
 
@@ -737,15 +738,15 @@
     final String attributeDescription = builder.toString();
     final String normalizedOption = toLowerCase(option);
 
-    return new AttributeDescription(attributeDescription,
-        attributeType, new SingleOptionImpl(option, normalizedOption));
+    return new AttributeDescription(attributeDescription, attributeType,
+        new SingleOptionImpl(option, normalizedOption));
   }
 
 
 
   /**
-   * Creates an attribute description having the provided attribute type
-   * and options.
+   * Creates an attribute description having the provided attribute type and
+   * options.
    *
    * @param attributeType
    *          The attribute type.
@@ -753,12 +754,10 @@
    *          The attribute options.
    * @return The attribute description.
    * @throws NullPointerException
-   *           If {@code attributeType} or {@code options} was {@code
-   *           null}.
+   *           If {@code attributeType} or {@code options} was {@code null}.
    */
-  public static AttributeDescription create(
-      AttributeType attributeType, String... options)
-      throws NullPointerException
+  public static AttributeDescription create(final AttributeType attributeType,
+      final String... options) throws NullPointerException
   {
     Validator.ensureNotNull(attributeType, options);
 
@@ -789,9 +788,8 @@
       Arrays.sort(normalizedOptions);
 
       final String attributeDescription = builder.toString();
-      return new AttributeDescription(attributeDescription,
-          attributeType, new MultiOptionImpl(optionsList,
-              normalizedOptions));
+      return new AttributeDescription(attributeDescription, attributeType,
+          new MultiOptionImpl(optionsList, normalizedOptions));
     }
 
   }
@@ -799,8 +797,8 @@
 
 
   /**
-   * Returns an attribute description representing the object class
-   * attribute type with no options.
+   * Returns an attribute description representing the object class attribute
+   * type with no options.
    *
    * @return The object class attribute description.
    */
@@ -812,20 +810,19 @@
 
 
   /**
-   * Parses the provided LDAP string representation of an attribute
-   * description using the default schema.
+   * Parses the provided LDAP string representation of an attribute description
+   * using the default schema.
    *
    * @param attributeDescription
-   *          The LDAP string representation of an attribute
-   *          description.
+   *          The LDAP string representation of an attribute description.
    * @return The parsed attribute description.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} is not a valid LDAP
-   *           string representation of an attribute description.
+   *           If {@code attributeDescription} is not a valid LDAP string
+   *           representation of an attribute description.
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
-  public static AttributeDescription valueOf(String attributeDescription)
+  public static AttributeDescription valueOf(final String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     return valueOf(attributeDescription, Schema.getDefaultSchema());
@@ -834,26 +831,25 @@
 
 
   /**
-   * Parses the provided LDAP string representation of an attribute
-   * description using the provided schema.
+   * Parses the provided LDAP string representation of an attribute description
+   * using the provided schema.
    *
    * @param attributeDescription
-   *          The LDAP string representation of an attribute
-   *          description.
+   *          The LDAP string representation of an attribute description.
    * @param schema
    *          The schema to use when parsing the attribute description.
    * @return The parsed attribute description.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} is not a valid LDAP
-   *           string representation of an attribute description.
+   *           If {@code attributeDescription} is not a valid LDAP string
+   *           representation of an attribute description.
    * @throws NullPointerException
-   *           If {@code attributeDescription} or {@code schema} was
-   *           {@code null}.
+   *           If {@code attributeDescription} or {@code schema} was {@code
+   *           null}.
    */
   @SuppressWarnings("serial")
-  public static AttributeDescription valueOf(
-      String attributeDescription, Schema schema)
-      throws LocalizedIllegalArgumentException, NullPointerException
+  public static AttributeDescription valueOf(final String attributeDescription,
+      final Schema schema) throws LocalizedIllegalArgumentException,
+      NullPointerException
   {
     Validator.ensureNotNull(attributeDescription, schema);
 
@@ -871,7 +867,7 @@
       {
         @Override
         protected boolean removeEldestEntry(
-            Map.Entry<String, AttributeDescription> eldest)
+            final Map.Entry<String, AttributeDescription> eldest)
         {
           return size() > ATTRIBUTE_DESCRIPTION_CACHE_SIZE;
         }
@@ -895,9 +891,8 @@
 
 
 
-  private static int skipTrailingWhiteSpace(
-      String attributeDescription, int i, int length)
-      throws LocalizedIllegalArgumentException
+  private static int skipTrailingWhiteSpace(final String attributeDescription,
+      int i, final int length) throws LocalizedIllegalArgumentException
   {
     char c;
     while (i < length)
@@ -918,7 +913,7 @@
 
   // Uncached valueOf implementation.
   private static AttributeDescription valueOf0(
-      String attributeDescription, Schema schema)
+      final String attributeDescription, final Schema schema)
       throws LocalizedIllegalArgumentException
   {
     int i = 0;
@@ -1028,8 +1023,8 @@
     }
     else
     {
-      oid = attributeDescription.substring(attributeTypeStart,
-          attributeTypeEnd);
+      oid = attributeDescription
+          .substring(attributeTypeStart, attributeTypeEnd);
     }
 
     if (oid.length() == 0)
@@ -1065,8 +1060,8 @@
       }
       else
       {
-        return new AttributeDescription(attributeDescription,
-            attributeType, ZERO_OPTION_IMPL);
+        return new AttributeDescription(attributeDescription, attributeType,
+            ZERO_OPTION_IMPL);
       }
     }
 
@@ -1135,8 +1130,8 @@
     // only contains a single option.
     if (i == length)
     {
-      return new AttributeDescription(attributeDescription,
-          attributeType, new SingleOptionImpl(option, normalizedOption));
+      return new AttributeDescription(attributeDescription, attributeType,
+          new SingleOptionImpl(option, normalizedOption));
     }
 
     // Multiple options need sorting and duplicates removed - we could
@@ -1213,10 +1208,9 @@
       normalizedOptions.add(normalizedOption);
     }
 
-    return new AttributeDescription(attributeDescription,
-        attributeType, new MultiOptionImpl(options
-            .toArray(new String[options.size()]), normalizedOptions
-            .toArray(new String[normalizedOptions.size()])));
+    return new AttributeDescription(attributeDescription, attributeType,
+        new MultiOptionImpl(options.toArray(new String[options.size()]),
+            normalizedOptions.toArray(new String[normalizedOptions.size()])));
   }
 
 
@@ -1230,8 +1224,8 @@
 
 
   // Private constructor.
-  private AttributeDescription(String attributeDescription,
-      AttributeType attributeType, Impl pimpl)
+  private AttributeDescription(final String attributeDescription,
+      final AttributeType attributeType, final Impl pimpl)
   {
     this.attributeDescription = attributeDescription;
     this.attributeType = attributeType;
@@ -1241,19 +1235,19 @@
 
 
   /**
-   * Compares this attribute description to the provided attribute
-   * description. The attribute types are compared first and then, if
-   * equal, the options are normalized, sorted, and compared.
+   * Compares this attribute description to the provided attribute description.
+   * The attribute types are compared first and then, if equal, the options are
+   * normalized, sorted, and compared.
    *
    * @param other
    *          The attribute description to be compared.
-   * @return A negative integer, zero, or a positive integer as this
-   *         attribute description is less than, equal to, or greater
-   *         than the specified attribute description.
+   * @return A negative integer, zero, or a positive integer as this attribute
+   *         description is less than, equal to, or greater than the specified
+   *         attribute description.
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public int compareTo(AttributeDescription other)
+  public int compareTo(final AttributeDescription other)
       throws NullPointerException
   {
     final int result = attributeType.compareTo(other.attributeType);
@@ -1271,17 +1265,17 @@
 
 
   /**
-   * Indicates whether or not this attribute description contains the
-   * provided option.
+   * Indicates whether or not this attribute description contains the provided
+   * option.
    *
    * @param option
    *          The option for which to make the determination.
-   * @return {@code true} if this attribute description has the provided
-   *         option, or {@code false} if not.
+   * @return {@code true} if this attribute description has the provided option,
+   *         or {@code false} if not.
    * @throws NullPointerException
    *           If {@code option} was {@code null}.
    */
-  public boolean containsOption(String option)
+  public boolean containsOption(final String option)
       throws NullPointerException
   {
     final String normalizedOption = toLowerCase(option);
@@ -1291,19 +1285,18 @@
 
 
   /**
-   * Indicates whether the provided object is an attribute description
-   * which is equal to this attribute description. It will be considered
-   * equal if the attribute type and normalized sorted list of options
-   * are identical.
+   * Indicates whether the provided object is an attribute description which is
+   * equal to this attribute description. It will be considered equal if the
+   * attribute type and normalized sorted list of options are identical.
    *
    * @param o
    *          The object for which to make the determination.
-   * @return {@code true} if the provided object is an attribute
-   *         description that is equal to this attribute description, or
-   *         {@code false} if not.
+   * @return {@code true} if the provided object is an attribute description
+   *         that is equal to this attribute description, or {@code false} if
+   *         not.
    */
   @Override
-  public boolean equals(Object o)
+  public boolean equals(final Object o)
   {
     if (this == o)
     {
@@ -1328,11 +1321,9 @@
 
 
   /**
-   * Returns the attribute type associated with this attribute
-   * description.
+   * Returns the attribute type associated with this attribute description.
    *
-   * @return The attribute type associated with this attribute
-   *         description.
+   * @return The attribute type associated with this attribute description.
    */
   public AttributeType getAttributeType()
   {
@@ -1342,10 +1333,10 @@
 
 
   /**
-   * Returns an {@code Iterable} containing the options contained in
-   * this attribute description. Attempts to remove options using an
-   * iterator's {@code remove()} method are not permitted and will
-   * result in an {@code UnsupportedOperationException} being thrown.
+   * Returns an {@code Iterable} containing the options contained in this
+   * attribute description. Attempts to remove options using an iterator's
+   * {@code remove()} method are not permitted and will result in an {@code
+   * UnsupportedOperationException} being thrown.
    *
    * @return An {@code Iterable} containing the options.
    */
@@ -1357,9 +1348,9 @@
 
 
   /**
-   * Returns the hash code for this attribute description. It will be
-   * calculated as the sum of the hash codes of the attribute type and
-   * normalized sorted list of options.
+   * Returns the hash code for this attribute description. It will be calculated
+   * as the sum of the hash codes of the attribute type and normalized sorted
+   * list of options.
    *
    * @return The hash code for this attribute description.
    */
@@ -1373,11 +1364,10 @@
 
 
   /**
-   * Indicates whether or not this attribute description has any
-   * options.
+   * Indicates whether or not this attribute description has any options.
    *
-   * @return {@code true} if this attribute description has any options,
-   *         or {@code false} if not.
+   * @return {@code true} if this attribute description has any options, or
+   *         {@code false} if not.
    */
   public boolean hasOptions()
   {
@@ -1391,8 +1381,8 @@
    * objectClass} attribute description with no options.
    *
    * @return {@code true} if this attribute description is the {@code
-   *         objectClass} attribute description with no options, or
-   *         {@code false} if not.
+   *         objectClass} attribute description with no options, or {@code
+   *         false} if not.
    */
   public boolean isObjectClass()
   {
@@ -1402,30 +1392,27 @@
 
 
   /**
-   * Indicates whether or not this attribute description is a sub-type
-   * of the provided attribute description as defined in RFC 4512
-   * section 2.5. Specifically, this method will return {@code true} if
-   * and only if the following conditions are both {@code true}:
+   * Indicates whether or not this attribute description is a sub-type of the
+   * provided attribute description as defined in RFC 4512 section 2.5.
+   * Specifically, this method will return {@code true} if and only if the
+   * following conditions are both {@code true}:
    * <ul>
-   * <li>This attribute description has an attribute type which is equal
-   * to, or is a sub-type of, the attribute type in the provided
-   * attribute description.
-   * <li>This attribute description contains all of the options
-   * contained in the provided attribute description.
+   * <li>This attribute description has an attribute type which is equal to, or
+   * is a sub-type of, the attribute type in the provided attribute description.
+   * <li>This attribute description contains all of the options contained in the
+   * provided attribute description.
    * </ul>
    * Note that this method will return {@code true} if this attribute
    * description is equal to the provided attribute description.
    *
    * @param other
-   *          The attribute description for which to make the
-   *          determination.
-   * @return {@code true} if this attribute description is a sub-type of
-   *         the provided attribute description, or {@code false} if
-   *         not.
+   *          The attribute description for which to make the determination.
+   * @return {@code true} if this attribute description is a sub-type of the
+   *         provided attribute description, or {@code false} if not.
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public boolean isSubTypeOf(AttributeDescription other)
+  public boolean isSubTypeOf(final AttributeDescription other)
       throws NullPointerException
   {
     if (!attributeType.isSubTypeOf(other.attributeType))
@@ -1441,30 +1428,28 @@
 
 
   /**
-   * Indicates whether or not this attribute description is a super-type
-   * of the provided attribute description as defined in RFC 4512
-   * section 2.5. Specifically, this method will return {@code true} if
-   * and only if the following conditions are both {@code true}:
+   * Indicates whether or not this attribute description is a super-type of the
+   * provided attribute description as defined in RFC 4512 section 2.5.
+   * Specifically, this method will return {@code true} if and only if the
+   * following conditions are both {@code true}:
    * <ul>
-   * <li>This attribute description has an attribute type which is equal
-   * to, or is a super-type of, the attribute type in the provided
-   * attribute description.
-   * <li>This attribute description contains a sub-set of the options
-   * contained in the provided attribute description.
+   * <li>This attribute description has an attribute type which is equal to, or
+   * is a super-type of, the attribute type in the provided attribute
+   * description.
+   * <li>This attribute description contains a sub-set of the options contained
+   * in the provided attribute description.
    * </ul>
    * Note that this method will return {@code true} if this attribute
    * description is equal to the provided attribute description.
    *
    * @param other
-   *          The attribute description for which to make the
-   *          determination.
-   * @return {@code true} if this attribute description is a super-type
-   *         of the provided attribute description, or {@code false} if
-   *         not.
+   *          The attribute description for which to make the determination.
+   * @return {@code true} if this attribute description is a super-type of the
+   *         provided attribute description, or {@code false} if not.
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public boolean isSuperTypeOf(AttributeDescription other)
+  public boolean isSuperTypeOf(final AttributeDescription other)
       throws NullPointerException
   {
     if (!other.attributeType.isSubTypeOf(attributeType))
@@ -1480,8 +1465,8 @@
 
 
   /**
-   * Returns the string representation of this attribute description as
-   * defined in RFC4512 section 2.5.
+   * Returns the string representation of this attribute description as defined
+   * in RFC4512 section 2.5.
    *
    * @return The string representation of this attribute description.
    */
diff --git a/sdk/src/org/opends/sdk/AttributeFactory.java b/sdk/src/org/opends/sdk/AttributeFactory.java
new file mode 100644
index 0000000..3bd3af5
--- /dev/null
+++ b/sdk/src/org/opends/sdk/AttributeFactory.java
@@ -0,0 +1,54 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+/**
+ * Attribute factories are included with a set of {@code DecodeOptions} in order
+ * to allow application to control how {@code Attribute} instances are created
+ * when decoding requests and responses.
+ *
+ * @see Attribute
+ * @see DecodeOptions
+ */
+public interface AttributeFactory
+{
+  /**
+   * Creates an attribute using the provided attribute description and no
+   * values.
+   *
+   * @param attributeDescription
+   *          The attribute description.
+   * @return The new attribute.
+   * @throws NullPointerException
+   *           If {@code attributeDescription} was {@code null}.
+   */
+  Attribute newAttribute(AttributeDescription attributeDescription)
+      throws NullPointerException;
+}
diff --git a/sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java b/sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java
index df3a43b..a0030c0 100644
--- a/sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java
+++ b/sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java
@@ -32,10 +32,7 @@
 import java.util.Collection;
 
 import org.opends.sdk.requests.*;
-import org.opends.sdk.responses.BindResult;
-import org.opends.sdk.responses.CompareResult;
-import org.opends.sdk.responses.Result;
-import org.opends.sdk.responses.SearchResultEntry;
+import org.opends.sdk.responses.*;
 import org.opends.sdk.schema.Schema;
 
 import com.sun.opends.sdk.util.FutureResultTransformer;
@@ -44,70 +41,26 @@
 
 
 /**
- * An authenticated connection factory can be used to create
- * pre-authenticated connections to a Directory Server.
+ * An authenticated connection factory can be used to create pre-authenticated
+ * connections to a Directory Server.
  * <p>
- * The connections returned by an authenticated connection factory
- * support all operations with the exception of Bind requests. Attempts
- * to perform a Bind will result in an {@code
- * UnsupportedOperationException}.
+ * The connections returned by an authenticated connection factory support all
+ * operations with the exception of Bind requests. Attempts to perform a Bind
+ * will result in an {@code UnsupportedOperationException}.
  * <p>
- * If the Bind request fails for some reason (e.g. invalid credentials),
- * then the connection attempt will fail and an {@code
- * ErrorResultException} will be thrown.
+ * If the Bind request fails for some reason (e.g. invalid credentials), then
+ * the connection attempt will fail and an {@code ErrorResultException} will be
+ * thrown.
  */
-final class AuthenticatedConnectionFactory extends
-    AbstractConnectionFactory
+final class AuthenticatedConnectionFactory extends AbstractConnectionFactory
 {
 
-  private final BindRequest request;
-
-  private final ConnectionFactory parentFactory;
-
-
-
   /**
-   * Creates a new authenticated connection factory which will obtain
-   * connections using the provided connection factory and immediately
-   * perform the provided Bind request.
-   *
-   * @param factory
-   *          The connection factory to use for connecting to the
-   *          Directory Server.
-   * @param request
-   *          The Bind request to use for authentication.
+   * An authenticated asynchronous connection supports all operations except
+   * Bind operations.
    */
-  AuthenticatedConnectionFactory(ConnectionFactory factory,
-      BindRequest request) throws NullPointerException
-  {
-    this.parentFactory = factory;
-
-    // FIXME: should do a defensive copy.
-    this.request = request;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
-      ResultHandler<AsynchronousConnection> handler)
-  {
-    FutureResultImpl future = new FutureResultImpl(request, handler);
-    future.futureConnectionResult.setFutureResult(parentFactory
-        .getAsynchronousConnection(future.futureConnectionResult));
-    return future.futureBindResult;
-  }
-
-
-
-  /**
-   * An authenticated asynchronous connection supports all operations
-   * except Bind operations.
-   */
-  public static final class AuthenticatedAsynchronousConnection
-      implements AsynchronousConnection
+  public static final class AuthenticatedAsynchronousConnection implements
+      AsynchronousConnection
   {
 
     private final AsynchronousConnection connection;
@@ -115,24 +68,24 @@
 
 
     private AuthenticatedAsynchronousConnection(
-        AsynchronousConnection connection)
+        final AsynchronousConnection connection)
     {
       this.connection = connection;
     }
 
 
 
-    public void abandon(AbandonRequest request)
+    public FutureResult<Void> abandon(final AbandonRequest request)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
-      connection.abandon(request);
+      return connection.abandon(request);
     }
 
 
 
-    public FutureResult<Result> add(AddRequest request,
-        ResultHandler<Result> handler)
+    public FutureResult<Result> add(final AddRequest request,
+        final ResultHandler<Result> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -141,8 +94,20 @@
 
 
 
+    public FutureResult<Result> add(final AddRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection
+          .add(request, resultHandler, intermediateResponseHandler);
+    }
+
+
+
     public void addConnectionEventListener(
-        ConnectionEventListener listener) throws IllegalStateException,
+        final ConnectionEventListener listener) throws IllegalStateException,
         NullPointerException
     {
       connection.addConnectionEventListener(listener);
@@ -151,12 +116,11 @@
 
 
     /**
-     * Bind operations are not supported by pre-authenticated
-     * connections. This method will always throw {@code
-     * UnsupportedOperationException}.
+     * Bind operations are not supported by pre-authenticated connections. This
+     * method will always throw {@code UnsupportedOperationException}.
      */
-    public FutureResult<BindResult> bind(BindRequest request,
-        ResultHandler<? super BindResult> handler)
+    public FutureResult<BindResult> bind(final BindRequest request,
+        final ResultHandler<? super BindResult> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -165,6 +129,18 @@
 
 
 
+    public FutureResult<BindResult> bind(final BindRequest request,
+        final ResultHandler<? super BindResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.bind(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
     public void close()
     {
       connection.close();
@@ -172,7 +148,7 @@
 
 
 
-    public void close(UnbindRequest request, String reason)
+    public void close(final UnbindRequest request, final String reason)
         throws NullPointerException
     {
       connection.close(request, reason);
@@ -180,8 +156,8 @@
 
 
 
-    public FutureResult<CompareResult> compare(CompareRequest request,
-        ResultHandler<? super CompareResult> handler)
+    public FutureResult<CompareResult> compare(final CompareRequest request,
+        final ResultHandler<? super CompareResult> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -190,8 +166,20 @@
 
 
 
-    public FutureResult<Result> delete(DeleteRequest request,
-        ResultHandler<Result> handler)
+    public FutureResult<CompareResult> compare(final CompareRequest request,
+        final ResultHandler<? super CompareResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.compare(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public FutureResult<Result> delete(final DeleteRequest request,
+        final ResultHandler<Result> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -200,8 +188,20 @@
 
 
 
-    public <R extends Result> FutureResult<R> extendedRequest(
-        ExtendedRequest<R> request, ResultHandler<? super R> handler)
+    public FutureResult<Result> delete(final DeleteRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.delete(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+        final ExtendedRequest<R> request, final ResultHandler<? super R> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -210,42 +210,15 @@
 
 
 
-    public FutureResult<Result> modify(ModifyRequest request,
-        ResultHandler<Result> handler)
+    public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+        final ExtendedRequest<R> request,
+        final ResultHandler<? super R> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
-      return connection.modify(request, handler);
-    }
-
-
-
-    public FutureResult<Result> modifyDN(ModifyDNRequest request,
-        ResultHandler<Result> handler)
-        throws UnsupportedOperationException, IllegalStateException,
-        NullPointerException
-    {
-      return connection.modifyDN(request, handler);
-    }
-
-
-
-    public void removeConnectionEventListener(
-        ConnectionEventListener listener) throws NullPointerException
-    {
-      connection.removeConnectionEventListener(listener);
-    }
-
-
-
-    public FutureResult<Result> search(SearchRequest request,
-        ResultHandler<Result> resultHandler,
-        SearchResultHandler searchResulthandler)
-        throws UnsupportedOperationException, IllegalStateException,
-        NullPointerException
-    {
-      return connection.search(request, resultHandler,
-          searchResulthandler);
+      return connection.extendedRequest(request, resultHandler,
+          intermediateResponseHandler);
     }
 
 
@@ -253,9 +226,9 @@
     /**
      * {@inheritDoc}
      */
-    public boolean isValid()
+    public Connection getSynchronousConnection()
     {
-      return connection.isValid();
+      return new SynchronousConnection(this);
     }
 
 
@@ -273,8 +246,76 @@
     /**
      * {@inheritDoc}
      */
+    public boolean isValid()
+    {
+      return connection.isValid();
+    }
+
+
+
+    public FutureResult<Result> modify(final ModifyRequest request,
+        final ResultHandler<Result> handler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.modify(request, handler);
+    }
+
+
+
+    public FutureResult<Result> modify(final ModifyRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.modify(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+        final ResultHandler<Result> handler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.modifyDN(request, handler);
+    }
+
+
+
+    public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.modifyDN(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<SearchResultEntry> readEntry(final DN name,
+        final Collection<String> attributeDescriptions,
+        final ResultHandler<? super SearchResultEntry> resultHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.readEntry(name, attributeDescriptions, resultHandler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
     public FutureResult<RootDSE> readRootDSE(
-        ResultHandler<RootDSE> handler)
+        final ResultHandler<RootDSE> handler)
         throws UnsupportedOperationException, IllegalStateException
     {
       return connection.readRootDSE(handler);
@@ -285,14 +326,55 @@
     /**
      * {@inheritDoc}
      */
-    public FutureResult<SearchResultEntry> readEntry(DN name,
-        Collection<String> attributeDescriptions,
-        ResultHandler<? super SearchResultEntry> resultHandler)
+    public FutureResult<Schema> readSchema(final DN name,
+        final ResultHandler<Schema> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      return connection.readSchema(name, handler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<Schema> readSchemaForEntry(final DN name,
+        final ResultHandler<Schema> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      return connection.readSchemaForEntry(name, handler);
+    }
+
+
+
+    public void removeConnectionEventListener(
+        final ConnectionEventListener listener) throws NullPointerException
+    {
+      connection.removeConnectionEventListener(listener);
+    }
+
+
+
+    public FutureResult<Result> search(final SearchRequest request,
+        final ResultHandler<Result> resultHandler,
+        final SearchResultHandler searchResulthandler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
-      return connection.readEntry(name, attributeDescriptions,
-          resultHandler);
+      return connection.search(request, resultHandler, searchResulthandler);
+    }
+
+
+
+    public FutureResult<Result> search(final SearchRequest request,
+        final ResultHandler<Result> resultHandler,
+        final SearchResultHandler searchResulthandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.search(request, resultHandler, searchResulthandler,
+          intermediateResponseHandler);
     }
 
 
@@ -301,38 +383,14 @@
      * {@inheritDoc}
      */
     public FutureResult<SearchResultEntry> searchSingleEntry(
-        SearchRequest request,
-        ResultHandler<? super SearchResultEntry> resultHandler)
+        final SearchRequest request,
+        final ResultHandler<? super SearchResultEntry> resultHandler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
       return connection.searchSingleEntry(request, resultHandler);
     }
 
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<Schema> readSchemaForEntry(DN name,
-        ResultHandler<Schema> handler)
-        throws UnsupportedOperationException, IllegalStateException
-    {
-      return connection.readSchemaForEntry(name, handler);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<Schema> readSchema(DN name,
-        ResultHandler<Schema> handler)
-        throws UnsupportedOperationException, IllegalStateException
-    {
-      return connection.readSchema(name, handler);
-    }
-
   }
 
 
@@ -349,16 +407,17 @@
 
 
 
-    private FutureResultImpl(BindRequest request,
-        ResultHandler<? super AsynchronousConnection> handler)
+    private FutureResultImpl(final BindRequest request,
+        final ResultHandler<? super AsynchronousConnection> handler)
     {
       this.bindRequest = request;
       this.futureBindResult = new FutureResultTransformer<BindResult, AsynchronousConnection>(
           handler)
       {
 
+        @Override
         protected ErrorResultException transformErrorResult(
-            ErrorResultException errorResult)
+            final ErrorResultException errorResult)
         {
           // Ensure that the connection is closed.
           try
@@ -366,7 +425,7 @@
             connection.close();
             connection = null;
           }
-          catch (Exception e)
+          catch (final Exception e)
           {
             // Ignore.
           }
@@ -375,8 +434,9 @@
 
 
 
-        protected AsynchronousConnection transformResult(
-            BindResult result) throws ErrorResultException
+        @Override
+        protected AsynchronousConnection transformResult(final BindResult result)
+            throws ErrorResultException
         {
           return new AuthenticatedAsynchronousConnection(connection);
         }
@@ -386,9 +446,10 @@
           futureBindResult)
       {
 
+        @Override
         protected FutureResult<? extends BindResult> chainResult(
-            AsynchronousConnection innerResult,
-            ResultHandler<? super BindResult> handler)
+            final AsynchronousConnection innerResult,
+            final ResultHandler<? super BindResult> handler)
             throws ErrorResultException
         {
           connection = innerResult;
@@ -400,4 +461,47 @@
 
   }
 
+
+
+  private final BindRequest request;
+
+  private final ConnectionFactory parentFactory;
+
+
+
+  /**
+   * Creates a new authenticated connection factory which will obtain
+   * connections using the provided connection factory and immediately perform
+   * the provided Bind request.
+   *
+   * @param factory
+   *          The connection factory to use for connecting to the Directory
+   *          Server.
+   * @param request
+   *          The Bind request to use for authentication.
+   */
+  AuthenticatedConnectionFactory(final ConnectionFactory factory,
+      final BindRequest request)
+  {
+    this.parentFactory = factory;
+
+    // FIXME: should do a defensive copy.
+    this.request = request;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      final ResultHandler<AsynchronousConnection> handler)
+  {
+    final FutureResultImpl future = new FutureResultImpl(request, handler);
+    future.futureConnectionResult.setFutureResult(parentFactory
+        .getAsynchronousConnection(future.futureConnectionResult));
+    return future.futureBindResult;
+  }
+
 }
diff --git a/sdk/src/org/opends/sdk/AuthenticationException.java b/sdk/src/org/opends/sdk/AuthenticationException.java
new file mode 100644
index 0000000..2e36959
--- /dev/null
+++ b/sdk/src/org/opends/sdk/AuthenticationException.java
@@ -0,0 +1,60 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import org.opends.sdk.responses.Result;
+
+
+
+/**
+ * Thrown when the result code returned in a Result indicates that the Bind
+ * Request failed due to an authentication failure. More specifically, this
+ * exception is used for the following error result codes:
+ * <ul>
+ * <li>{@link ResultCode#AUTH_METHOD_NOT_SUPPORTED AUTH_METHOD_NOT_SUPPORTED} -
+ * the Bind request failed because it referenced an invalid SASL mechanism.
+ * <li>{@link ResultCode#CLIENT_SIDE_AUTH_UNKNOWN CLIENT_SIDE_AUTH_UNKNOWN} -
+ * the Bind request failed because the user requested an authentication
+ * mechanism which is unknown or unsupported by the OpenDS SDK.
+ * <li>{@link ResultCode#INAPPROPRIATE_AUTHENTICATION
+ * INAPPROPRIATE_AUTHENTICATION} - the Bind request failed because the requested
+ * type of authentication was not appropriate for the targeted entry.
+ * <li>{@link ResultCode#INVALID_CREDENTIALS INVALID_CREDENTIALS} - the Bind
+ * request failed because the user did not provide a valid set of credentials.
+ * </ul>
+ */
+@SuppressWarnings("serial")
+public class AuthenticationException extends ErrorResultException
+{
+  AuthenticationException(final Result result)
+  {
+    super(result);
+  }
+}
diff --git a/sdk/src/org/opends/sdk/AuthorizationException.java b/sdk/src/org/opends/sdk/AuthorizationException.java
new file mode 100644
index 0000000..93c97da
--- /dev/null
+++ b/sdk/src/org/opends/sdk/AuthorizationException.java
@@ -0,0 +1,62 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import org.opends.sdk.responses.Result;
+
+
+
+/**
+ * Thrown when the result code returned in a Result indicates that the Request
+ * failed due to an authorization failure. More specifically, this exception is
+ * used for the following error result codes:
+ * <ul>
+ * <li>{@link ResultCode#AUTHORIZATION_DENIED AUTHORIZATION_DENIED} - the
+ * Request failed because the server has not allowed the client to use the
+ * requested authorization.
+ * <li>{@link ResultCode#CONFIDENTIALITY_REQUIRED CONFIDENTIALITY_REQUIRED} -
+ * the Request failed because it requires confidentiality for the communication
+ * between the client and the server.
+ * <li>{@link ResultCode#INSUFFICIENT_ACCESS_RIGHTS INSUFFICIENT_ACCESS_RIGHTS}
+ * - the Request failed because the client does not have sufficient permission
+ * to perform the requested operation.
+ * <li>{@link ResultCode#STRONG_AUTH_REQUIRED STRONG_AUTH_REQUIRED} - the
+ * Request failed because it requires that the client has completed a strong
+ * form of authentication.
+ * </ul>
+ */
+@SuppressWarnings("serial")
+public class AuthorizationException extends ErrorResultException
+{
+  AuthorizationException(final Result result)
+  {
+    super(result);
+  }
+}
diff --git a/sdk/src/org/opends/sdk/ByteSequence.java b/sdk/src/org/opends/sdk/ByteSequence.java
index 2ab17d9..88ce65e 100755
--- a/sdk/src/org/opends/sdk/ByteSequence.java
+++ b/sdk/src/org/opends/sdk/ByteSequence.java
@@ -33,24 +33,22 @@
 
 
 
-
 /**
- * A {@code ByteSequence} is a readable sequence of byte values. This
- * interface provides uniform, read-only access to many different kinds
- * of byte sequences.
+ * A {@code ByteSequence} is a readable sequence of byte values. This interface
+ * provides uniform, read-only access to many different kinds of byte sequences.
  */
 public interface ByteSequence extends Comparable<ByteSequence>
 {
 
   /**
-   * Returns a {@link ByteSequenceReader} which can be used to
-   * incrementally read and decode data from this byte sequence.
+   * Returns a {@link ByteSequenceReader} which can be used to incrementally
+   * read and decode data from this byte sequence.
    * <p>
-   * <b>NOTE:</b> any concurrent changes to the underlying byte sequence
-   * (if mutable) may cause subsequent reads to overrun and fail.
-   * 
-   * @return The {@link ByteSequenceReader} which can be used to
-   *         incrementally read and decode data from this byte sequence.
+   * <b>NOTE:</b> any concurrent changes to the underlying byte sequence (if
+   * mutable) may cause subsequent reads to overrun and fail.
+   *
+   * @return The {@link ByteSequenceReader} which can be used to incrementally
+   *         read and decode data from this byte sequence.
    */
   ByteSequenceReader asReader();
 
@@ -59,45 +57,40 @@
   /**
    * Returns the byte value at the specified index.
    * <p>
-   * An index ranges from zero to {@code length() - 1}. The first byte
-   * value of the sequence is at index zero, the next at index one, and
-   * so on, as for array indexing.
-   * 
+   * An index ranges from zero to {@code length() - 1}. The first byte value of
+   * the sequence is at index zero, the next at index one, and so on, as for
+   * array indexing.
+   *
    * @param index
    *          The index of the byte to be returned.
    * @return The byte value at the specified index.
    * @throws IndexOutOfBoundsException
-   *           If the index argument is negative or not less than
-   *           length().
+   *           If the index argument is negative or not less than length().
    */
   byte byteAt(int index) throws IndexOutOfBoundsException;
 
 
 
   /**
-   * Compares this byte sequence with the specified byte array
-   * sub-sequence for order. Returns a negative integer, zero, or a
-   * positive integer depending on whether this byte sequence is less
-   * than, equal to, or greater than the specified byte array
-   * sub-sequence.
-   * 
+   * Compares this byte sequence with the specified byte array sub-sequence for
+   * order. Returns a negative integer, zero, or a positive integer depending on
+   * whether this byte sequence is less than, equal to, or greater than the
+   * specified byte array sub-sequence.
+   *
    * @param b
    *          The byte array to compare.
    * @param offset
-   *          The offset of the sub-sequence in the byte array to be
-   *          compared; must be non-negative and no larger than {@code
-   *          b.length} .
+   *          The offset of the sub-sequence in the byte array to be compared;
+   *          must be non-negative and no larger than {@code b.length} .
    * @param length
-   *          The length of the sub-sequence in the byte array to be
-   *          compared; must be non-negative and no larger than {@code
-   *          b.length - offset}.
-   * @return A negative integer, zero, or a positive integer depending
-   *         on whether this byte sequence is less than, equal to, or
-   *         greater than the specified byte array sub-sequence.
+   *          The length of the sub-sequence in the byte array to be compared;
+   *          must be non-negative and no larger than {@code b.length - offset}.
+   * @return A negative integer, zero, or a positive integer depending on
+   *         whether this byte sequence is less than, equal to, or greater than
+   *         the specified byte array sub-sequence.
    * @throws IndexOutOfBoundsException
-   *           If {@code offset} is negative or if {@code length} is
-   *           negative or if {@code offset + length} is greater than
-   *           {@code b.length}.
+   *           If {@code offset} is negative or if {@code length} is negative or
+   *           if {@code offset + length} is greater than {@code b.length}.
    */
   int compareTo(byte[] b, int offset, int length)
       throws IndexOutOfBoundsException;
@@ -105,41 +98,39 @@
 
 
   /**
-   * Compares this byte sequence with the specified byte sequence for
-   * order. Returns a negative integer, zero, or a positive integer
-   * depending on whether this byte sequence is less than, equal to, or
-   * greater than the specified object.
-   * 
+   * Compares this byte sequence with the specified byte sequence for order.
+   * Returns a negative integer, zero, or a positive integer depending on
+   * whether this byte sequence is less than, equal to, or greater than the
+   * specified object.
+   *
    * @param o
    *          The byte sequence to be compared.
-   * @return A negative integer, zero, or a positive integer depending
-   *         on whether this byte sequence is less than, equal to, or
-   *         greater than the specified object.
+   * @return A negative integer, zero, or a positive integer depending on
+   *         whether this byte sequence is less than, equal to, or greater than
+   *         the specified object.
    */
   int compareTo(ByteSequence o);
 
 
 
   /**
-   * Copies the contents of this byte sequence to the provided byte
-   * array.
+   * Copies the contents of this byte sequence to the provided byte array.
    * <p>
-   * Copying will stop when either the entire content of this sequence
-   * has been copied or if the end of the provided byte array has been
-   * reached.
+   * Copying will stop when either the entire content of this sequence has been
+   * copied or if the end of the provided byte array has been reached.
    * <p>
    * An invocation of the form:
-   * 
+   *
    * <pre>
    * src.copyTo(b)
    * </pre>
-   * 
+   *
    * Behaves in exactly the same way as the invocation:
-   * 
+   *
    * <pre>
    * src.copyTo(b, 0);
    * </pre>
-   * 
+   *
    * @param b
    *          The byte array to which bytes are to be copied.
    * @return The byte array.
@@ -149,34 +140,33 @@
 
 
   /**
-   * Copies the contents of this byte sequence to the specified location
-   * in the provided byte array.
+   * Copies the contents of this byte sequence to the specified location in the
+   * provided byte array.
    * <p>
-   * Copying will stop when either the entire content of this sequence
-   * has been copied or if the end of the provided byte array has been
-   * reached.
+   * Copying will stop when either the entire content of this sequence has been
+   * copied or if the end of the provided byte array has been reached.
    * <p>
    * An invocation of the form:
-   * 
+   *
    * <pre>
    * src.copyTo(b, offset)
    * </pre>
-   * 
+   *
    * Behaves in exactly the same way as the invocation:
-   * 
+   *
    * <pre>
    * int len = Math.min(src.length(), b.length - offset);
    * for (int i = 0; i &lt; len; i++)
    *   b[offset + i] = src.get(i);
    * </pre>
-   * 
+   *
    * Except that it is potentially much more efficient.
-   * 
+   *
    * @param b
    *          The byte array to which bytes are to be copied.
    * @param offset
-   *          The offset within the array of the first byte to be
-   *          written; must be non-negative and no larger than b.length.
+   *          The offset within the array of the first byte to be written; must
+   *          be non-negative and no larger than b.length.
    * @return The byte array.
    * @throws IndexOutOfBoundsException
    *           If {@code offset} is negative.
@@ -188,7 +178,7 @@
   /**
    * Appends the entire contents of this byte sequence to the provided
    * {@link ByteStringBuilder}.
-   * 
+   *
    * @param builder
    *          The builder to copy to.
    * @return The builder.
@@ -198,43 +188,37 @@
 
 
   /**
-   * Copies the entire contents of this byte sequence to the provided
-   * {@code OutputStream}.
-   * 
+   * Copies the entire contents of this byte sequence to the provided {@code
+   * OutputStream}.
+   *
    * @param stream
    *          The {@code OutputStream} to copy to.
    * @return The {@code OutputStream}.
    * @throws IOException
-   *           If an error occurs while writing to the {@code
-   *           OutputStream}.
+   *           If an error occurs while writing to the {@code OutputStream}.
    */
   OutputStream copyTo(OutputStream stream) throws IOException;
 
 
 
   /**
-   * Indicates whether the provided byte array sub-sequence is equal to
-   * this byte sequence. In order for it to be considered equal, the
-   * provided byte array sub-sequence must contain the same bytes in the
-   * same order.
-   * 
+   * Indicates whether the provided byte array sub-sequence is equal to this
+   * byte sequence. In order for it to be considered equal, the provided byte
+   * array sub-sequence must contain the same bytes in the same order.
+   *
    * @param b
    *          The byte array for which to make the determination.
    * @param offset
-   *          The offset of the sub-sequence in the byte array to be
-   *          compared; must be non-negative and no larger than {@code
-   *          b.length} .
+   *          The offset of the sub-sequence in the byte array to be compared;
+   *          must be non-negative and no larger than {@code b.length} .
    * @param length
-   *          The length of the sub-sequence in the byte array to be
-   *          compared; must be non-negative and no larger than {@code
-   *          b.length - offset}.
-   * @return {@code true} if the content of the provided byte array
-   *         sub-sequence is equal to that of this byte sequence, or
-   *         {@code false} if not.
+   *          The length of the sub-sequence in the byte array to be compared;
+   *          must be non-negative and no larger than {@code b.length - offset}.
+   * @return {@code true} if the content of the provided byte array sub-sequence
+   *         is equal to that of this byte sequence, or {@code false} if not.
    * @throws IndexOutOfBoundsException
-   *           If {@code offset} is negative or if {@code length} is
-   *           negative or if {@code offset + length} is greater than
-   *           {@code b.length}.
+   *           If {@code offset} is negative or if {@code length} is negative or
+   *           if {@code offset + length} is greater than {@code b.length}.
    */
   boolean equals(byte[] b, int offset, int length)
       throws IndexOutOfBoundsException;
@@ -242,25 +226,24 @@
 
 
   /**
-   * Indicates whether the provided object is equal to this byte
-   * sequence. In order for it to be considered equal, the provided
-   * object must be a byte sequence containing the same bytes in the
-   * same order.
-   * 
+   * Indicates whether the provided object is equal to this byte sequence. In
+   * order for it to be considered equal, the provided object must be a byte
+   * sequence containing the same bytes in the same order.
+   *
    * @param o
    *          The object for which to make the determination.
-   * @return {@code true} if the provided object is a byte sequence
-   *         whose content is equal to that of this byte sequence, or
-   *         {@code false} if not.
+   * @return {@code true} if the provided object is a byte sequence whose
+   *         content is equal to that of this byte sequence, or {@code false} if
+   *         not.
    */
   boolean equals(Object o);
 
 
 
   /**
-   * Returns a hash code for this byte sequence. It will be the sum of
-   * all of the bytes contained in the byte sequence.
-   * 
+   * Returns a hash code for this byte sequence. It will be the sum of all of
+   * the bytes contained in the byte sequence.
+   *
    * @return A hash code for this byte sequence.
    */
   int hashCode();
@@ -269,7 +252,7 @@
 
   /**
    * Returns the length of this byte sequence.
-   * 
+   *
    * @return The length of this byte sequence.
    */
   int length();
@@ -277,50 +260,47 @@
 
 
   /**
-   * Returns a new byte sequence that is a subsequence of this byte
-   * sequence.
+   * Returns a new byte sequence that is a subsequence of this byte sequence.
    * <p>
-   * The subsequence starts with the byte value at the specified {@code
-   * start} index and ends with the byte value at index {@code end - 1}.
-   * The length (in bytes) of the returned sequence is {@code end -
-   * start}, so if {@code start == end} then an empty sequence is
-   * returned.
+   * The subsequence starts with the byte value at the specified {@code start}
+   * index and ends with the byte value at index {@code end - 1}. The length (in
+   * bytes) of the returned sequence is {@code end - start}, so if {@code start
+   * == end} then an empty sequence is returned.
    * <p>
-   * <b>NOTE:</b> changes to the underlying byte sequence (if mutable)
-   * may render the returned sub-sequence invalid.
-   * 
+   * <b>NOTE:</b> changes to the underlying byte sequence (if mutable) may
+   * render the returned sub-sequence invalid.
+   *
    * @param start
    *          The start index, inclusive.
    * @param end
    *          The end index, exclusive.
    * @return The newly created byte subsequence.
    * @throws IndexOutOfBoundsException
-   *           If {@code start} or {@code end} are negative, if {@code
-   *           end} is greater than {@code length()}, or if {@code
-   *           start} is greater than {@code end}.
+   *           If {@code start} or {@code end} are negative, if {@code end} is
+   *           greater than {@code length()}, or if {@code start} is greater
+   *           than {@code end}.
    */
-  ByteSequence subSequence(int start, int end)
-      throws IndexOutOfBoundsException;
+  ByteSequence subSequence(int start, int end) throws IndexOutOfBoundsException;
 
 
 
   /**
-   * Returns a byte array containing the bytes in this sequence in the
-   * same order as this sequence. The length of the byte array will be
-   * the length of this sequence.
+   * Returns a byte array containing the bytes in this sequence in the same
+   * order as this sequence. The length of the byte array will be the length of
+   * this sequence.
    * <p>
    * An invocation of the form:
-   * 
+   *
    * <pre>
    * src.toByteArray()
    * </pre>
-   * 
+   *
    * Behaves in exactly the same way as the invocation:
-   * 
+   *
    * <pre>
    * src.copyTo(new byte[src.length()]);
    * </pre>
-   * 
+   *
    * @return A byte array consisting of exactly this sequence of bytes.
    */
   byte[] toByteArray();
@@ -328,21 +308,18 @@
 
 
   /**
-   * Returns the {@link ByteString} representation of this byte
-   * sequence.
-   * 
-   * @return The {@link ByteString} representation of this byte
-   *         sequence.
+   * Returns the {@link ByteString} representation of this byte sequence.
+   *
+   * @return The {@link ByteString} representation of this byte sequence.
    */
   ByteString toByteString();
 
 
 
   /**
-   * Returns the UTF-8 decoded string representation of this byte
-   * sequence. If UTF-8 decoding fails, the platform's default encoding
-   * will be used.
-   * 
+   * Returns the UTF-8 decoded string representation of this byte sequence. If
+   * UTF-8 decoding fails, the platform's default encoding will be used.
+   *
    * @return The string representation of this byte sequence.
    */
   String toString();
diff --git a/sdk/src/org/opends/sdk/ByteSequenceReader.java b/sdk/src/org/opends/sdk/ByteSequenceReader.java
index 1fa9fd2..a6f7865 100755
--- a/sdk/src/org/opends/sdk/ByteSequenceReader.java
+++ b/sdk/src/org/opends/sdk/ByteSequenceReader.java
@@ -28,11 +28,10 @@
 
 
 
-
 /**
- * An interface for iteratively reading date from a {@link ByteSequence}
- * . {@code ByteSequenceReader} must be created using the associated
- * {@code ByteSequence}'s {@code asReader()} method.
+ * An interface for iteratively reading date from a {@link ByteSequence} .
+ * {@code ByteSequenceReader} must be created using the associated {@code
+ * ByteSequence}'s {@code asReader()} method.
  */
 public final class ByteSequenceReader
 {
@@ -46,19 +45,19 @@
 
 
   /**
-   * Creates a new byte sequence reader whose source is the provided
-   * byte sequence.
+   * Creates a new byte sequence reader whose source is the provided byte
+   * sequence.
    * <p>
-   * <b>NOTE:</b> any concurrent changes to the underlying byte sequence
-   * (if mutable) may cause subsequent reads to overrun and fail.
+   * <b>NOTE:</b> any concurrent changes to the underlying byte sequence (if
+   * mutable) may cause subsequent reads to overrun and fail.
    * <p>
-   * This constructor is package private: construction must be performed
-   * using {@link ByteSequence#asReader()}.
-   * 
+   * This constructor is package private: construction must be performed using
+   * {@link ByteSequence#asReader()}.
+   *
    * @param sequence
    *          The byte sequence to be read.
    */
-  ByteSequenceReader(ByteSequence sequence)
+  ByteSequenceReader(final ByteSequence sequence)
   {
     this.sequence = sequence;
   }
@@ -67,12 +66,12 @@
 
   /**
    * Relative get method. Reads the byte at the current position.
-   * 
+   *
    * @return The byte at this reader's current position.
    * @throws IndexOutOfBoundsException
-   *           If there are fewer bytes remaining in this reader than
-   *           are required to satisfy the request, that is, if {@code
-   *           remaining() < 1}.
+   *           If there are fewer bytes remaining in this reader than are
+   *           required to satisfy the request, that is, if {@code remaining()
+   *           &lt; 1}.
    */
   public byte get() throws IndexOutOfBoundsException
   {
@@ -84,28 +83,27 @@
 
 
   /**
-   * Relative bulk get method. This method transfers bytes from this
-   * reader into the given destination array. An invocation of this
-   * method of the form:
-   * 
+   * Relative bulk get method. This method transfers bytes from this reader into
+   * the given destination array. An invocation of this method of the form:
+   *
    * <pre>
    * src.get(b);
    * </pre>
-   * 
+   *
    * Behaves in exactly the same way as the invocation:
-   * 
+   *
    * <pre>
    * src.get(b, 0, b.length);
    * </pre>
-   * 
+   *
    * @param b
    *          The byte array into which bytes are to be written.
    * @throws IndexOutOfBoundsException
-   *           If there are fewer bytes remaining in this reader than
-   *           are required to satisfy the request, that is, if {@code
-   *           remaining() < b.length}.
+   *           If there are fewer bytes remaining in this reader than are
+   *           required to satisfy the request, that is, if {@code remaining()
+   *           &lt; b.length}.
    */
-  public void get(byte[] b) throws IndexOutOfBoundsException
+  public void get(final byte[] b) throws IndexOutOfBoundsException
   {
     get(b, 0, b.length);
   }
@@ -113,41 +111,40 @@
 
 
   /**
-   * Relative bulk get method. Copies {@code length} bytes from this
-   * reader into the given array, starting at the current position of
-   * this reader and at the given {@code offset} in the array. The
-   * position of this reader is then incremented by {@code length}. In
-   * other words, an invocation of this method of the form:
-   * 
+   * Relative bulk get method. Copies {@code length} bytes from this reader into
+   * the given array, starting at the current position of this reader and at the
+   * given {@code offset} in the array. The position of this reader is then
+   * incremented by {@code length}. In other words, an invocation of this method
+   * of the form:
+   *
    * <pre>
    * src.get(b, offset, length);
    * </pre>
-   * 
+   *
    * Has exactly the same effect as the loop:
-   * 
+   *
    * <pre>
    * for (int i = offset; i &lt; offset + length; i++)
    *   b[i] = src.get();
    * </pre>
-   * 
-   * Except that it first checks that there are sufficient bytes in this
-   * buffer and it is potentially much more efficient.
-   * 
+   *
+   * Except that it first checks that there are sufficient bytes in this buffer
+   * and it is potentially much more efficient.
+   *
    * @param b
    *          The byte array into which bytes are to be written.
    * @param offset
-   *          The offset within the array of the first byte to be
-   *          written; must be non-negative and no larger than {@code
-   *          b.length}.
+   *          The offset within the array of the first byte to be written; must
+   *          be non-negative and no larger than {@code b.length}.
    * @param length
-   *          The number of bytes to be written to the given array; must
-   *          be non-negative and no larger than {@code b.length} .
+   *          The number of bytes to be written to the given array; must be
+   *          non-negative and no larger than {@code b.length} .
    * @throws IndexOutOfBoundsException
-   *           If there are fewer bytes remaining in this reader than
-   *           are required to satisfy the request, that is, if {@code
-   *           remaining() < length}.
+   *           If there are fewer bytes remaining in this reader than are
+   *           required to satisfy the request, that is, if {@code remaining()
+   *           &lt; length}.
    */
-  public void get(byte[] b, int offset, int length)
+  public void get(final byte[] b, final int offset, final int length)
       throws IndexOutOfBoundsException
   {
     if (offset < 0 || length < 0 || offset + length > b.length
@@ -163,16 +160,15 @@
 
 
   /**
-   * Relative get method for reading a multi-byte BER length. Reads the
-   * next one to five bytes at this reader's current position, composing
-   * them into a integer value and then increments the position by the
-   * number of bytes read.
-   * 
-   * @return The integer value representing the length at this reader's
-   *         current position.
+   * Relative get method for reading a multi-byte BER length. Reads the next one
+   * to five bytes at this reader's current position, composing them into a
+   * integer value and then increments the position by the number of bytes read.
+   *
+   * @return The integer value representing the length at this reader's current
+   *         position.
    * @throws IndexOutOfBoundsException
-   *           If there are fewer bytes remaining in this reader than
-   *           are required to satisfy the request.
+   *           If there are fewer bytes remaining in this reader than are
+   *           required to satisfy the request.
    */
   public int getBERLength() throws IndexOutOfBoundsException
   {
@@ -210,25 +206,25 @@
 
 
   /**
-   * Relative bulk get method. Returns a {@link ByteSequence} whose
-   * content is the next {@code length} bytes from this reader, starting
-   * at the current position of this reader. The position of this reader
-   * is then incremented by {@code length}.
+   * Relative bulk get method. Returns a {@link ByteSequence} whose content is
+   * the next {@code length} bytes from this reader, starting at the current
+   * position of this reader. The position of this reader is then incremented by
+   * {@code length}.
    * <p>
-   * <b>NOTE:</b> The value returned from this method should NEVER be
-   * cached as it prevents the contents of the underlying byte stream
-   * from being garbage collected.
-   * 
+   * <b>NOTE:</b> The value returned from this method should NEVER be cached as
+   * it prevents the contents of the underlying byte stream from being garbage
+   * collected.
+   *
    * @param length
    *          The length of the byte sequence to be returned.
-   * @return The byte sequence whose content is the next {@code length}
-   *         bytes from this reader.
+   * @return The byte sequence whose content is the next {@code length} bytes
+   *         from this reader.
    * @throws IndexOutOfBoundsException
-   *           If there are fewer bytes remaining in this reader than
-   *           are required to satisfy the request, that is, if {@code
-   *           remaining() < length}.
+   *           If there are fewer bytes remaining in this reader than are
+   *           required to satisfy the request, that is, if {@code remaining()
+   *           &lt; length}.
    */
-  public ByteSequence getByteSequence(int length)
+  public ByteSequence getByteSequence(final int length)
       throws IndexOutOfBoundsException
   {
     final int newPos = pos + length;
@@ -240,37 +236,37 @@
 
 
   /**
-   * Relative bulk get method. Returns a {@link ByteString} whose
-   * content is the next {@code length} bytes from this reader, starting
-   * at the current position of this reader. The position of this reader
-   * is then incremented by {@code length}.
+   * Relative bulk get method. Returns a {@link ByteString} whose content is the
+   * next {@code length} bytes from this reader, starting at the current
+   * position of this reader. The position of this reader is then incremented by
+   * {@code length}.
    * <p>
    * An invocation of this method of the form:
-   * 
+   *
    * <pre>
    * src.getByteString(length);
    * </pre>
-   * 
+   *
    * Has exactly the same effect as:
-   * 
+   *
    * <pre>
    * src.getByteSequence(length).toByteString();
    * </pre>
-   * 
-   * <b>NOTE:</b> The value returned from this method should NEVER be
-   * cached as it prevents the contents of the underlying byte stream
-   * from being garbage collected.
-   * 
+   *
+   * <b>NOTE:</b> The value returned from this method should NEVER be cached as
+   * it prevents the contents of the underlying byte stream from being garbage
+   * collected.
+   *
    * @param length
    *          The length of the byte string to be returned.
-   * @return The byte string whose content is the next {@code length}
-   *         bytes from this reader.
+   * @return The byte string whose content is the next {@code length} bytes from
+   *         this reader.
    * @throws IndexOutOfBoundsException
-   *           If there are fewer bytes remaining in this reader than
-   *           are required to satisfy the request, that is, if {@code
-   *           remaining() < length}.
+   *           If there are fewer bytes remaining in this reader than are
+   *           required to satisfy the request, that is, if {@code remaining()
+   *           &lt; length}.
    */
-  public ByteString getByteString(int length)
+  public ByteString getByteString(final int length)
       throws IndexOutOfBoundsException
   {
     return getByteSequence(length).toByteString();
@@ -279,16 +275,16 @@
 
 
   /**
-   * Relative get method for reading an integer value. Reads the next
-   * four bytes at this reader's current position, composing them into
-   * an integer value according to big-endian byte order, and then
-   * increments the position by four.
-   * 
+   * Relative get method for reading an integer value. Reads the next four bytes
+   * at this reader's current position, composing them into an integer value
+   * according to big-endian byte order, and then increments the position by
+   * four.
+   *
    * @return The integer value at this reader's current position.
    * @throws IndexOutOfBoundsException
-   *           If there are fewer bytes remaining in this reader than
-   *           are required to satisfy the request, that is, if {@code
-   *           remaining() < 4}.
+   *           If there are fewer bytes remaining in this reader than are
+   *           required to satisfy the request, that is, if {@code remaining()
+   *           &lt; 4}.
    */
   public int getInt() throws IndexOutOfBoundsException
   {
@@ -310,16 +306,15 @@
 
 
   /**
-   * Relative get method for reading a long value. Reads the next eight
-   * bytes at this reader's current position, composing them into a long
-   * value according to big-endian byte order, and then increments the
-   * position by eight.
-   * 
+   * Relative get method for reading a long value. Reads the next eight bytes at
+   * this reader's current position, composing them into a long value according
+   * to big-endian byte order, and then increments the position by eight.
+   *
    * @return The long value at this reader's current position.
    * @throws IndexOutOfBoundsException
-   *           If there are fewer bytes remaining in this reader than
-   *           are required to satisfy the request, that is, if {@code
-   *           remaining() < 8}.
+   *           If there are fewer bytes remaining in this reader than are
+   *           required to satisfy the request, that is, if {@code remaining()
+   *           &lt; 8}.
    */
   public long getLong() throws IndexOutOfBoundsException
   {
@@ -341,16 +336,16 @@
 
 
   /**
-   * Relative get method for reading an short value. Reads the next 2
-   * bytes at this reader's current position, composing them into an
-   * short value according to big-endian byte order, and then increments
-   * the position by two.
-   * 
+   * Relative get method for reading an short value. Reads the next 2 bytes at
+   * this reader's current position, composing them into an short value
+   * according to big-endian byte order, and then increments the position by
+   * two.
+   *
    * @return The integer value at this reader's current position.
    * @throws IndexOutOfBoundsException
-   *           If there are fewer bytes remaining in this reader than
-   *           are required to satisfy the request, that is, if {@code
-   *           remaining() < 2}.
+   *           If there are fewer bytes remaining in this reader than are
+   *           required to satisfy the request, that is, if {@code remaining()
+   *           &lt; 2}.
    */
   public short getShort() throws IndexOutOfBoundsException
   {
@@ -372,21 +367,21 @@
 
 
   /**
-   * Relative get method for reading a UTF-8 encoded string. Reads the
-   * next number of specified bytes at this reader's current position,
-   * decoding them into a string using UTF-8 and then increments the
-   * position by the number of bytes read. If UTF-8 decoding fails, the
-   * platform's default encoding will be used.
-   * 
+   * Relative get method for reading a UTF-8 encoded string. Reads the next
+   * number of specified bytes at this reader's current position, decoding them
+   * into a string using UTF-8 and then increments the position by the number of
+   * bytes read. If UTF-8 decoding fails, the platform's default encoding will
+   * be used.
+   *
    * @param length
    *          The number of bytes to read and decode.
    * @return The string value at the reader's current position.
    * @throws IndexOutOfBoundsException
-   *           If there are fewer bytes remaining in this reader than
-   *           are required to satisfy the request, that is, if {@code
-   *           remaining() < length}.
+   *           If there are fewer bytes remaining in this reader than are
+   *           required to satisfy the request, that is, if {@code remaining()
+   *           &lt; length}.
    */
-  public String getString(int length) throws IndexOutOfBoundsException
+  public String getString(final int length) throws IndexOutOfBoundsException
   {
     if (remaining() < length)
     {
@@ -394,8 +389,7 @@
     }
 
     final int newPos = pos + length;
-    final String str =
-        sequence.subSequence(pos, pos + length).toString();
+    final String str = sequence.subSequence(pos, pos + length).toString();
     pos = newPos;
     return str;
   }
@@ -404,7 +398,7 @@
 
   /**
    * Returns this reader's position.
-   * 
+   *
    * @return The position of this reader.
    */
   public int position()
@@ -416,15 +410,15 @@
 
   /**
    * Sets this reader's position.
-   * 
+   *
    * @param pos
-   *          The new position value; must be non-negative and no larger
-   *          than the length of the underlying byte sequence.
+   *          The new position value; must be non-negative and no larger than
+   *          the length of the underlying byte sequence.
    * @throws IndexOutOfBoundsException
-   *           If the position is negative or larger than the length of
-   *           the underlying byte sequence.
+   *           If the position is negative or larger than the length of the
+   *           underlying byte sequence.
    */
-  public void position(int pos) throws IndexOutOfBoundsException
+  public void position(final int pos) throws IndexOutOfBoundsException
   {
     if (pos > sequence.length() || pos < 0)
     {
@@ -437,11 +431,11 @@
 
 
   /**
-   * Returns the number of bytes between the current position and the
-   * end of the underlying byte sequence.
-   * 
-   * @return The number of bytes between the current position and the
-   *         end of the underlying byte sequence.
+   * Returns the number of bytes between the current position and the end of the
+   * underlying byte sequence.
+   *
+   * @return The number of bytes between the current position and the end of the
+   *         underlying byte sequence.
    */
   public int remaining()
   {
@@ -454,13 +448,13 @@
    * Rewinds this reader's position to zero.
    * <p>
    * An invocation of this method of the form:
-   * 
+   *
    * <pre>
    * src.rewind();
    * </pre>
-   * 
+   *
    * Has exactly the same effect as:
-   * 
+   *
    * <pre>
    * src.position(0);
    * </pre>
@@ -476,24 +470,24 @@
    * Skips the given number of bytes. Negative values are allowed.
    * <p>
    * An invocation of this method of the form:
-   * 
+   *
    * <pre>
    * src.skip(length);
    * </pre>
-   * 
+   *
    * Has exactly the same effect as:
-   * 
+   *
    * <pre>
    * src.position(position() + length);
    * </pre>
-   * 
+   *
    * @param length
    *          The number of bytes to skip.
    * @throws IndexOutOfBoundsException
-   *           If the new position is less than 0 or greater than the
-   *           length of the underlying byte sequence.
+   *           If the new position is less than 0 or greater than the length of
+   *           the underlying byte sequence.
    */
-  public void skip(int length) throws IndexOutOfBoundsException
+  public void skip(final int length) throws IndexOutOfBoundsException
   {
     position(pos + length);
   }
diff --git a/sdk/src/org/opends/sdk/ByteString.java b/sdk/src/org/opends/sdk/ByteString.java
index 65c71e1..f3f2432 100755
--- a/sdk/src/org/opends/sdk/ByteString.java
+++ b/sdk/src/org/opends/sdk/ByteString.java
@@ -49,7 +49,7 @@
 
   /**
    * Returns an empty byte string.
-   * 
+   *
    * @return An empty byte string.
    */
   public static ByteString empty()
@@ -60,13 +60,13 @@
 
 
   /**
-   * Returns a byte string containing the big-endian encoded bytes of
-   * the provided integer.
-   * 
+   * Returns a byte string containing the big-endian encoded bytes of the
+   * provided integer.
+   *
    * @param i
    *          The integer to encode.
-   * @return The byte string containing the big-endian encoded bytes of
-   *         the provided integer.
+   * @return The byte string containing the big-endian encoded bytes of the
+   *         provided integer.
    */
   public static ByteString valueOf(int i)
   {
@@ -82,13 +82,13 @@
 
 
   /**
-   * Returns a byte string containing the big-endian encoded bytes of
-   * the provided long.
-   * 
+   * Returns a byte string containing the big-endian encoded bytes of the
+   * provided long.
+   *
    * @param l
    *          The long to encode.
-   * @return The byte string containing the big-endian encoded bytes of
-   *         the provided long.
+   * @return The byte string containing the big-endian encoded bytes of the
+   *         provided long.
    */
   public static ByteString valueOf(long l)
   {
@@ -104,17 +104,17 @@
 
 
   /**
-   * Returns a byte string containing the provided object. If the object
-   * is an instance of {@code ByteSequence} then it is converted to a
-   * byte string using the {@code toByteString()} method. Otherwise a
-   * new byte string is created containing the UTF-8 encoded bytes of
-   * the string representation of the provided object.
-   * 
+   * Returns a byte string containing the provided object. If the object is an
+   * instance of {@code ByteSequence} then it is converted to a byte string
+   * using the {@code toByteString()} method. Otherwise a new byte string is
+   * created containing the UTF-8 encoded bytes of the string representation of
+   * the provided object.
+   *
    * @param o
    *          The object to use.
    * @return The byte string containing the provided object.
    */
-  public static ByteString valueOf(Object o)
+  public static ByteString valueOf(final Object o)
   {
     if (o instanceof ByteSequence)
     {
@@ -129,15 +129,14 @@
 
 
   /**
-   * Returns a byte string containing the UTF-8 encoded bytes of the
-   * provided string.
-   * 
+   * Returns a byte string containing the UTF-8 encoded bytes of the provided
+   * string.
+   *
    * @param s
    *          The string to use.
-   * @return The byte string with the encoded bytes of the provided
-   *         string.
+   * @return The byte string with the encoded bytes of the provided string.
    */
-  public static ByteString valueOf(String s)
+  public static ByteString valueOf(final String s)
   {
     return wrap(StaticUtils.getBytes(s));
   }
@@ -147,15 +146,15 @@
   /**
    * Returns a byte string that wraps the provided byte array.
    * <p>
-   * <b>NOTE:</b> this method takes ownership of the provided byte array
-   * and, therefore, the byte array MUST NOT be altered directly after
-   * this method returns.
-   * 
+   * <b>NOTE:</b> this method takes ownership of the provided byte array and,
+   * therefore, the byte array MUST NOT be altered directly after this method
+   * returns.
+   *
    * @param b
    *          The byte array to wrap.
    * @return The byte string that wraps the given byte array.
    */
-  public static ByteString wrap(byte[] b)
+  public static ByteString wrap(final byte[] b)
   {
     return new ByteString(b, 0, b.length);
   }
@@ -163,29 +162,27 @@
 
 
   /**
-   * Returns a byte string that wraps a subsequence of the provided byte
-   * array.
+   * Returns a byte string that wraps a subsequence of the provided byte array.
    * <p>
-   * <b>NOTE:</b> this method takes ownership of the provided byte array
-   * and, therefore, the byte array MUST NOT be altered directly after
-   * this method returns.
-   * 
+   * <b>NOTE:</b> this method takes ownership of the provided byte array and,
+   * therefore, the byte array MUST NOT be altered directly after this method
+   * returns.
+   *
    * @param b
    *          The byte array to wrap.
    * @param offset
-   *          The offset of the byte array to be used; must be
-   *          non-negative and no larger than {@code b.length} .
+   *          The offset of the byte array to be used; must be non-negative and
+   *          no larger than {@code b.length} .
    * @param length
-   *          The length of the byte array to be used; must be
-   *          non-negative and no larger than {@code b.length - offset}.
+   *          The length of the byte array to be used; must be non-negative and
+   *          no larger than {@code b.length - offset}.
    * @return The byte string that wraps the given byte array.
    * @throws IndexOutOfBoundsException
-   *           If {@code offset} is negative or if {@code length} is
-   *           negative or if {@code offset + length} is greater than
-   *           {@code b.length}.
+   *           If {@code offset} is negative or if {@code length} is negative or
+   *           if {@code offset + length} is greater than {@code b.length}.
    */
-  public static ByteString wrap(byte[] b, int offset, int length)
-      throws IndexOutOfBoundsException
+  public static ByteString wrap(final byte[] b, final int offset,
+      final int length) throws IndexOutOfBoundsException
   {
     checkArrayBounds(b, offset, length);
     return new ByteString(b, offset, length);
@@ -194,24 +191,23 @@
 
 
   /**
-   * Checks the array bounds of the provided byte array sub-sequence,
-   * throwing an {@code IndexOutOfBoundsException} if they are illegal.
-   * 
+   * Checks the array bounds of the provided byte array sub-sequence, throwing
+   * an {@code IndexOutOfBoundsException} if they are illegal.
+   *
    * @param b
    *          The byte array.
    * @param offset
-   *          The offset of the byte array to be checked; must be
-   *          non-negative and no larger than {@code b.length}.
+   *          The offset of the byte array to be checked; must be non-negative
+   *          and no larger than {@code b.length}.
    * @param length
-   *          The length of the byte array to be checked; must be
-   *          non-negative and no larger than {@code b.length - offset}.
+   *          The length of the byte array to be checked; must be non-negative
+   *          and no larger than {@code b.length - offset}.
    * @throws IndexOutOfBoundsException
-   *           If {@code offset} is negative or if {@code length} is
-   *           negative or if {@code offset + length} is greater than
-   *           {@code b.length}.
+   *           If {@code offset} is negative or if {@code length} is negative or
+   *           if {@code offset + length} is greater than {@code b.length}.
    */
-  static void checkArrayBounds(byte[] b, int offset, int length)
-      throws IndexOutOfBoundsException
+  static void checkArrayBounds(final byte[] b, final int offset,
+      final int length) throws IndexOutOfBoundsException
   {
     if (offset < 0 || offset > b.length || length < 0
         || offset + length > b.length || offset + length < 0)
@@ -223,9 +219,9 @@
 
 
   /**
-   * Compares two byte array sub-sequences and returns a value that
-   * indicates their relative order.
-   * 
+   * Compares two byte array sub-sequences and returns a value that indicates
+   * their relative order.
+   *
    * @param b1
    *          The byte array containing the first sub-sequence.
    * @param offset1
@@ -238,16 +234,15 @@
    *          The offset of the second byte array sub-sequence.
    * @param length2
    *          The length of the second byte array sub-sequence.
-   * @return A negative integer if first byte array sub-sequence should
-   *         come before the second byte array sub-sequence in ascending
-   *         order, a positive integer if the first byte array
-   *         sub-sequence should come after the byte array sub-sequence
-   *         in ascending order, or zero if there is no difference
-   *         between the two byte array sub-sequences with regard to
-   *         ordering.
+   * @return A negative integer if first byte array sub-sequence should come
+   *         before the second byte array sub-sequence in ascending order, a
+   *         positive integer if the first byte array sub-sequence should come
+   *         after the byte array sub-sequence in ascending order, or zero if
+   *         there is no difference between the two byte array sub-sequences
+   *         with regard to ordering.
    */
-  static int compareTo(byte[] b1, int offset1, int length1, byte[] b2,
-      int offset2, int length2)
+  static int compareTo(final byte[] b1, final int offset1, final int length1,
+      final byte[] b2, final int offset2, final int length2)
   {
     int count = Math.min(length1, length2);
     int i = offset1;
@@ -267,10 +262,9 @@
 
 
   /**
-   * Indicates whether two byte array sub-sequences are equal. In order
-   * for them to be considered equal, they must contain the same bytes
-   * in the same order.
-   * 
+   * Indicates whether two byte array sub-sequences are equal. In order for them
+   * to be considered equal, they must contain the same bytes in the same order.
+   *
    * @param b1
    *          The byte array containing the first sub-sequence.
    * @param offset1
@@ -283,11 +277,11 @@
    *          The offset of the second byte array sub-sequence.
    * @param length2
    *          The length of the second byte array sub-sequence.
-   * @return {@code true} if the two byte array sub-sequences have the
-   *         same content, or {@code false} if not.
+   * @return {@code true} if the two byte array sub-sequences have the same
+   *         content, or {@code false} if not.
    */
-  static boolean equals(byte[] b1, int offset1, int length1, byte[] b2,
-      int offset2, int length2)
+  static boolean equals(final byte[] b1, final int offset1, final int length1,
+      final byte[] b2, final int offset2, final int length2)
   {
     if (length1 != length2)
     {
@@ -312,7 +306,7 @@
 
   /**
    * Returns a hash code for the provided byte array sub-sequence.
-   * 
+   *
    * @param b
    *          The byte array.
    * @param offset
@@ -321,7 +315,7 @@
    *          The length of the byte array sub-sequence.
    * @return A hash code for the provided byte array sub-sequence.
    */
-  static int hashCode(byte[] b, int offset, int length)
+  static int hashCode(final byte[] b, final int offset, final int length)
   {
     int hashCode = 1;
     int i = offset;
@@ -336,10 +330,10 @@
 
 
   /**
-   * Returns the UTF-8 decoded string representation of the provided
-   * byte array sub-sequence. If UTF-8 decoding fails, the platform's
-   * default encoding will be used.
-   * 
+   * Returns the UTF-8 decoded string representation of the provided byte array
+   * sub-sequence. If UTF-8 decoding fails, the platform's default encoding will
+   * be used.
+   *
    * @param b
    *          The byte array.
    * @param offset
@@ -348,7 +342,7 @@
    *          The length of the byte array sub-sequence.
    * @return The string representation of the byte array sub-sequence.
    */
-  static String toString(byte[] b, int offset, int length)
+  static String toString(final byte[] b, final int offset, final int length)
   {
     String stringValue;
     try
@@ -369,6 +363,8 @@
     return stringValue;
   }
 
+
+
   // These are package private so that compression and crypto
   // functionality may directly access the fields.
 
@@ -385,23 +381,23 @@
 
 
   /**
-   * Creates a new byte string that wraps a subsequence of the provided
-   * byte array.
+   * Creates a new byte string that wraps a subsequence of the provided byte
+   * array.
    * <p>
-   * <b>NOTE:</b> this method takes ownership of the provided byte array
-   * and, therefore, the byte array MUST NOT be altered directly after
-   * this method returns.
-   * 
+   * <b>NOTE:</b> this method takes ownership of the provided byte array and,
+   * therefore, the byte array MUST NOT be altered directly after this method
+   * returns.
+   *
    * @param b
    *          The byte array to wrap.
    * @param offset
-   *          The offset of the byte array to be used; must be
-   *          non-negative and no larger than {@code b.length} .
+   *          The offset of the byte array to be used; must be non-negative and
+   *          no larger than {@code b.length} .
    * @param length
-   *          The length of the byte array to be used; must be
-   *          non-negative and no larger than {@code b.length - offset}.
+   *          The length of the byte array to be used; must be non-negative and
+   *          no larger than {@code b.length - offset}.
    */
-  private ByteString(byte[] b, int offset, int length)
+  private ByteString(final byte[] b, final int offset, final int length)
   {
     this.buffer = b;
     this.offset = offset;
@@ -411,11 +407,11 @@
 
 
   /**
-   * Returns a {@link ByteSequenceReader} which can be used to
-   * incrementally read and decode data from this byte string.
-   * 
-   * @return The {@link ByteSequenceReader} which can be used to
-   *         incrementally read and decode data from this byte string.
+   * Returns a {@link ByteSequenceReader} which can be used to incrementally
+   * read and decode data from this byte string.
+   *
+   * @return The {@link ByteSequenceReader} which can be used to incrementally
+   *         read and decode data from this byte string.
    */
   public ByteSequenceReader asReader()
   {
@@ -427,7 +423,7 @@
   /**
    * {@inheritDoc}
    */
-  public byte byteAt(int index) throws IndexOutOfBoundsException
+  public byte byteAt(final int index) throws IndexOutOfBoundsException
   {
     if (index >= length || index < 0)
     {
@@ -441,12 +437,11 @@
   /**
    * {@inheritDoc}
    */
-  public int compareTo(byte[] b, int offset, int length)
+  public int compareTo(final byte[] b, final int offset, final int length)
       throws IndexOutOfBoundsException
   {
     checkArrayBounds(b, offset, length);
-    return compareTo(this.buffer, this.offset, this.length, b, offset,
-        length);
+    return compareTo(this.buffer, this.offset, this.length, b, offset, length);
   }
 
 
@@ -454,7 +449,7 @@
   /**
    * {@inheritDoc}
    */
-  public int compareTo(ByteSequence o)
+  public int compareTo(final ByteSequence o)
   {
     if (this == o)
     {
@@ -468,7 +463,7 @@
   /**
    * {@inheritDoc}
    */
-  public byte[] copyTo(byte[] b)
+  public byte[] copyTo(final byte[] b)
   {
     copyTo(b, 0);
     return b;
@@ -479,15 +474,15 @@
   /**
    * {@inheritDoc}
    */
-  public byte[] copyTo(byte[] b, int offset)
+  public byte[] copyTo(final byte[] b, final int offset)
       throws IndexOutOfBoundsException
   {
     if (offset < 0)
     {
       throw new IndexOutOfBoundsException();
     }
-    System.arraycopy(buffer, this.offset, b, offset, Math.min(length,
-        b.length - offset));
+    System.arraycopy(buffer, this.offset, b, offset, Math.min(length, b.length
+        - offset));
     return b;
   }
 
@@ -496,7 +491,7 @@
   /**
    * {@inheritDoc}
    */
-  public ByteStringBuilder copyTo(ByteStringBuilder builder)
+  public ByteStringBuilder copyTo(final ByteStringBuilder builder)
   {
     builder.append(buffer, offset, length);
     return builder;
@@ -507,7 +502,7 @@
   /**
    * {@inheritDoc}
    */
-  public OutputStream copyTo(OutputStream stream) throws IOException
+  public OutputStream copyTo(final OutputStream stream) throws IOException
   {
     stream.write(buffer, offset, length);
     return stream;
@@ -518,29 +513,28 @@
   /**
    * {@inheritDoc}
    */
-  public boolean equals(byte[] b, int offset, int length)
+  public boolean equals(final byte[] b, final int offset, final int length)
       throws IndexOutOfBoundsException
   {
     checkArrayBounds(b, offset, length);
-    return equals(this.buffer, this.offset, this.length, b, offset,
-        length);
+    return equals(this.buffer, this.offset, this.length, b, offset, length);
   }
 
 
 
   /**
-   * Indicates whether the provided object is equal to this byte string.
-   * In order for it to be considered equal, the provided object must be
-   * a byte sequence containing the same bytes in the same order.
-   * 
+   * Indicates whether the provided object is equal to this byte string. In
+   * order for it to be considered equal, the provided object must be a byte
+   * sequence containing the same bytes in the same order.
+   *
    * @param o
    *          The object for which to make the determination.
-   * @return {@code true} if the provided object is a byte sequence
-   *         whose content is equal to that of this byte string, or
-   *         {@code false} if not.
+   * @return {@code true} if the provided object is a byte sequence whose
+   *         content is equal to that of this byte string, or {@code false} if
+   *         not.
    */
   @Override
-  public boolean equals(Object o)
+  public boolean equals(final Object o)
   {
     if (this == o)
     {
@@ -560,9 +554,9 @@
 
 
   /**
-   * Returns a hash code for this byte string. It will be the sum of all
-   * of the bytes contained in the byte string.
-   * 
+   * Returns a hash code for this byte string. It will be the sum of all of the
+   * bytes contained in the byte string.
+   *
    * @return A hash code for this byte string.
    */
   @Override
@@ -586,7 +580,7 @@
   /**
    * {@inheritDoc}
    */
-  public ByteString subSequence(int start, int end)
+  public ByteString subSequence(final int start, final int end)
       throws IndexOutOfBoundsException
   {
     if (start < 0 || start > end || end > length)
@@ -619,11 +613,11 @@
 
 
   /**
-   * Returns the integer value represented by the first four bytes of
-   * this byte string in big-endian order.
-   * 
-   * @return The integer value represented by the first four bytes of
-   *         this byte string in big-endian order.
+   * Returns the integer value represented by the first four bytes of this byte
+   * string in big-endian order.
+   *
+   * @return The integer value represented by the first four bytes of this byte
+   *         string in big-endian order.
    * @throws IndexOutOfBoundsException
    *           If this byte string has less than four bytes.
    */
@@ -646,11 +640,11 @@
 
 
   /**
-   * Returns the long value represented by the first eight bytes of this
-   * byte string in big-endian order.
-   * 
-   * @return The long value represented by the first eight bytes of this
-   *         byte string in big-endian order.
+   * Returns the long value represented by the first eight bytes of this byte
+   * string in big-endian order.
+   *
+   * @return The long value represented by the first eight bytes of this byte
+   *         string in big-endian order.
    * @throws IndexOutOfBoundsException
    *           If this byte string has less than eight bytes.
    */
diff --git a/sdk/src/org/opends/sdk/ByteStringBuilder.java b/sdk/src/org/opends/sdk/ByteStringBuilder.java
index 92821ed..a66597a 100755
--- a/sdk/src/org/opends/sdk/ByteStringBuilder.java
+++ b/sdk/src/org/opends/sdk/ByteStringBuilder.java
@@ -45,9 +45,9 @@
 {
 
   /**
-   * A sub-sequence of the parent byte string builder. The sub-sequence
-   * will be robust against all updates to the byte string builder
-   * except for invocations of the method {@code clear()}.
+   * A sub-sequence of the parent byte string builder. The sub-sequence will be
+   * robust against all updates to the byte string builder except for
+   * invocations of the method {@code clear()}.
    */
   private final class SubSequence implements ByteSequence
   {
@@ -62,13 +62,13 @@
 
     /**
      * Creates a new sub-sequence.
-     * 
+     *
      * @param offset
      *          The offset of the sub-sequence.
      * @param length
      *          The length of the sub-sequence.
      */
-    private SubSequence(int offset, int length)
+    private SubSequence(final int offset, final int length)
     {
       this.subOffset = offset;
       this.subLength = length;
@@ -89,7 +89,7 @@
     /**
      * {@inheritDoc}
      */
-    public byte byteAt(int index) throws IndexOutOfBoundsException
+    public byte byteAt(final int index) throws IndexOutOfBoundsException
     {
       if (index >= subLength || index < 0)
       {
@@ -105,14 +105,14 @@
     /**
      * {@inheritDoc}
      */
-    public int compareTo(byte[] b, int offset, int length)
+    public int compareTo(final byte[] b, final int offset, final int length)
         throws IndexOutOfBoundsException
     {
       ByteString.checkArrayBounds(b, offset, length);
 
       // Protect against reallocation: use builder's buffer.
-      return ByteString.compareTo(buffer, subOffset, subLength, b,
-          offset, length);
+      return ByteString.compareTo(buffer, subOffset, subLength, b, offset,
+          length);
     }
 
 
@@ -120,7 +120,7 @@
     /**
      * {@inheritDoc}
      */
-    public int compareTo(ByteSequence o)
+    public int compareTo(final ByteSequence o)
     {
       if (this == o)
       {
@@ -136,7 +136,7 @@
     /**
      * {@inheritDoc}
      */
-    public byte[] copyTo(byte[] b)
+    public byte[] copyTo(final byte[] b)
     {
       copyTo(b, 0);
       return b;
@@ -147,7 +147,7 @@
     /**
      * {@inheritDoc}
      */
-    public byte[] copyTo(byte[] b, int offset)
+    public byte[] copyTo(final byte[] b, final int offset)
         throws IndexOutOfBoundsException
     {
       if (offset < 0)
@@ -156,8 +156,8 @@
       }
 
       // Protect against reallocation: use builder's buffer.
-      System.arraycopy(buffer, subOffset, b, offset, Math.min(
-          subLength, b.length - offset));
+      System.arraycopy(buffer, subOffset, b, offset, Math.min(subLength,
+          b.length - offset));
       return b;
     }
 
@@ -166,7 +166,7 @@
     /**
      * {@inheritDoc}
      */
-    public ByteStringBuilder copyTo(ByteStringBuilder builder)
+    public ByteStringBuilder copyTo(final ByteStringBuilder builder)
     {
       // Protect against reallocation: use builder's buffer.
       return builder.append(buffer, subOffset, subLength);
@@ -177,7 +177,7 @@
     /**
      * {@inheritDoc}
      */
-    public OutputStream copyTo(OutputStream stream) throws IOException
+    public OutputStream copyTo(final OutputStream stream) throws IOException
     {
       // Protect against reallocation: use builder's buffer.
       stream.write(buffer, subOffset, subLength);
@@ -189,14 +189,13 @@
     /**
      * {@inheritDoc}
      */
-    public boolean equals(byte[] b, int offset, int length)
+    public boolean equals(final byte[] b, final int offset, final int length)
         throws IndexOutOfBoundsException
     {
       ByteString.checkArrayBounds(b, offset, length);
 
       // Protect against reallocation: use builder's buffer.
-      return ByteString.equals(buffer, subOffset, subLength, b, offset,
-          length);
+      return ByteString.equals(buffer, subOffset, subLength, b, offset, length);
     }
 
 
@@ -205,7 +204,7 @@
      * {@inheritDoc}
      */
     @Override
-    public boolean equals(Object o)
+    public boolean equals(final Object o)
     {
       if (this == o)
       {
@@ -251,7 +250,7 @@
     /**
      * {@inheritDoc}
      */
-    public ByteSequence subSequence(int start, int end)
+    public ByteSequence subSequence(final int start, final int end)
         throws IndexOutOfBoundsException
     {
       if (start < 0 || start > end || end > subLength)
@@ -298,6 +297,8 @@
     }
   }
 
+
+
   // These are package private so that compression and crypto
   // functionality may directly access the fields.
 
@@ -310,8 +311,7 @@
 
 
   /**
-   * Creates a new byte string builder with an initial capacity of 32
-   * bytes.
+   * Creates a new byte string builder with an initial capacity of 32 bytes.
    */
   public ByteStringBuilder()
   {
@@ -322,16 +322,14 @@
 
 
   /**
-   * Creates a new byte string builder with the specified initial
-   * capacity.
-   * 
+   * Creates a new byte string builder with the specified initial capacity.
+   *
    * @param capacity
    *          The initial capacity.
    * @throws IllegalArgumentException
    *           If the {@code capacity} is negative.
    */
-  public ByteStringBuilder(int capacity)
-      throws IllegalArgumentException
+  public ByteStringBuilder(final int capacity) throws IllegalArgumentException
   {
     if (capacity < 0)
     {
@@ -346,12 +344,12 @@
 
   /**
    * Appends the provided byte to this byte string builder.
-   * 
+   *
    * @param b
    *          The byte to be appended to this byte string builder.
    * @return This byte string builder.
    */
-  public ByteStringBuilder append(byte b)
+  public ByteStringBuilder append(final byte b)
   {
     ensureAdditionalCapacity(1);
     buffer[length++] = b;
@@ -364,22 +362,22 @@
    * Appends the provided byte array to this byte string builder.
    * <p>
    * An invocation of the form:
-   * 
+   *
    * <pre>
    * src.append(b)
    * </pre>
-   * 
+   *
    * Behaves in exactly the same way as the invocation:
-   * 
+   *
    * <pre>
    * src.append(b, 0, b.length);
    * </pre>
-   * 
+   *
    * @param b
    *          The byte array to be appended to this byte string builder.
    * @return This byte string builder.
    */
-  public ByteStringBuilder append(byte[] b)
+  public ByteStringBuilder append(final byte[] b)
   {
     return append(b, 0, b.length);
   }
@@ -388,23 +386,22 @@
 
   /**
    * Appends the provided byte array to this byte string builder.
-   * 
+   *
    * @param b
    *          The byte array to be appended to this byte string builder.
    * @param offset
-   *          The offset of the byte array to be used; must be
-   *          non-negative and no larger than {@code b.length} .
+   *          The offset of the byte array to be used; must be non-negative and
+   *          no larger than {@code b.length} .
    * @param length
-   *          The length of the byte array to be used; must be
-   *          non-negative and no larger than {@code b.length - offset}.
+   *          The length of the byte array to be used; must be non-negative and
+   *          no larger than {@code b.length - offset}.
    * @return This byte string builder.
    * @throws IndexOutOfBoundsException
-   *           If {@code offset} is negative or if {@code length} is
-   *           negative or if {@code offset + length} is greater than
-   *           {@code b.length}.
+   *           If {@code offset} is negative or if {@code length} is negative or
+   *           if {@code offset + length} is greater than {@code b.length}.
    */
-  public ByteStringBuilder append(byte[] b, int offset, int length)
-      throws IndexOutOfBoundsException
+  public ByteStringBuilder append(final byte[] b, final int offset,
+      final int length) throws IndexOutOfBoundsException
   {
     ByteString.checkArrayBounds(b, offset, length);
 
@@ -421,20 +418,18 @@
 
 
   /**
-   * Appends the provided {@code ByteBuffer} to this byte string
-   * builder.
-   * 
+   * Appends the provided {@code ByteBuffer} to this byte string builder.
+   *
    * @param buffer
-   *          The byte buffer to be appended to this byte string
-   *          builder.
+   *          The byte buffer to be appended to this byte string builder.
    * @param length
    *          The number of bytes to be appended from {@code buffer}.
    * @return This byte string builder.
    * @throws IndexOutOfBoundsException
-   *           If {@code length} is less than zero or greater than
-   *           {@code buffer.remaining()}.
+   *           If {@code length} is less than zero or greater than {@code
+   *           buffer.remaining()}.
    */
-  public ByteStringBuilder append(ByteBuffer buffer, int length)
+  public ByteStringBuilder append(final ByteBuffer buffer, final int length)
       throws IndexOutOfBoundsException
   {
     if (length < 0 || length > buffer.remaining())
@@ -455,15 +450,13 @@
 
 
   /**
-   * Appends the provided {@link ByteSequence} to this byte string
-   * builder.
-   * 
+   * Appends the provided {@link ByteSequence} to this byte string builder.
+   *
    * @param bytes
-   *          The byte sequence to be appended to this byte string
-   *          builder.
+   *          The byte sequence to be appended to this byte string builder.
    * @return This byte string builder.
    */
-  public ByteStringBuilder append(ByteSequence bytes)
+  public ByteStringBuilder append(final ByteSequence bytes)
   {
     return bytes.copyTo(this);
   }
@@ -473,19 +466,19 @@
   /**
    * Appends the provided {@link ByteSequenceReader} to this byte string
    * builder.
-   * 
+   *
    * @param reader
-   *          The byte sequence reader to be appended to this byte
-   *          string builder.
+   *          The byte sequence reader to be appended to this byte string
+   *          builder.
    * @param length
    *          The number of bytes to be appended from {@code reader}.
    * @return This byte string builder.
    * @throws IndexOutOfBoundsException
-   *           If {@code length} is less than zero or greater than
-   *           {@code reader.remaining()}.
+   *           If {@code length} is less than zero or greater than {@code
+   *           reader.remaining()}.
    */
-  public ByteStringBuilder append(ByteSequenceReader reader, int length)
-      throws IndexOutOfBoundsException
+  public ByteStringBuilder append(final ByteSequenceReader reader,
+      final int length) throws IndexOutOfBoundsException
   {
     if (length < 0 || length > reader.remaining())
     {
@@ -505,23 +498,20 @@
 
 
   /**
-   * Appends the provided {@code InputStream} to this byte string
-   * builder.
-   * 
+   * Appends the provided {@code InputStream} to this byte string builder.
+   *
    * @param stream
-   *          The input stream to be appended to this byte string
-   *          builder.
+   *          The input stream to be appended to this byte string builder.
    * @param length
-   *          The maximum number of bytes to be appended from {@code
-   *          buffer}.
-   * @return The number of bytes read from the input stream, or {@code
-   *         -1} if the end of the input stream has been reached.
+   *          The maximum number of bytes to be appended from {@code buffer}.
+   * @return The number of bytes read from the input stream, or {@code -1} if
+   *         the end of the input stream has been reached.
    * @throws IndexOutOfBoundsException
    *           If {@code length} is less than zero.
    * @throws IOException
    *           If an I/O error occurs.
    */
-  public int append(InputStream stream, int length)
+  public int append(final InputStream stream, final int length)
       throws IndexOutOfBoundsException, IOException
   {
     if (length < 0)
@@ -542,12 +532,12 @@
 
 
   /**
-   * Appends the big-endian encoded bytes of the provided integer to
-   * this byte string builder.
-   * 
+   * Appends the big-endian encoded bytes of the provided integer to this byte
+   * string builder.
+   *
    * @param i
-   *          The integer whose big-endian encoding is to be appended to
-   *          this byte string builder.
+   *          The integer whose big-endian encoding is to be appended to this
+   *          byte string builder.
    * @return This byte string builder.
    */
   public ByteStringBuilder append(int i)
@@ -565,12 +555,12 @@
 
 
   /**
-   * Appends the big-endian encoded bytes of the provided long to this
-   * byte string builder.
-   * 
+   * Appends the big-endian encoded bytes of the provided long to this byte
+   * string builder.
+   *
    * @param l
-   *          The long whose big-endian encoding is to be appended to
-   *          this byte string builder.
+   *          The long whose big-endian encoding is to be appended to this byte
+   *          string builder.
    * @return This byte string builder.
    */
   public ByteStringBuilder append(long l)
@@ -588,12 +578,41 @@
 
 
   /**
-   * Appends the big-endian encoded bytes of the provided short to this
-   * byte string builder.
-   * 
+   * Appends the provided object to this byte string builder. If the object is
+   * an instance of {@code ByteSequence} then its contents will be appended
+   * directly to this byte string builder using the {@code append(ByteSequence)}
+   * method. Otherwise the string representation of the object will be appended
+   * using the {@code append(String)} method.
+   *
+   * @param o
+   *          The object to be appended to this byte string builder.
+   * @return This byte string builder.
+   */
+  public ByteStringBuilder append(final Object o)
+  {
+    if (o == null)
+    {
+      return this;
+    }
+    else if (o instanceof ByteSequence)
+    {
+      return append((ByteSequence) o);
+    }
+    else
+    {
+      return append(o.toString());
+    }
+  }
+
+
+
+  /**
+   * Appends the big-endian encoded bytes of the provided short to this byte
+   * string builder.
+   *
    * @param i
-   *          The short whose big-endian encoding is to be appended to
-   *          this byte string builder.
+   *          The short whose big-endian encoding is to be appended to this byte
+   *          string builder.
    * @return This byte string builder.
    */
   public ByteStringBuilder append(short i)
@@ -611,15 +630,15 @@
 
 
   /**
-   * Appends the UTF-8 encoded bytes of the provided string to this byte
-   * string builder.
-   * 
+   * Appends the UTF-8 encoded bytes of the provided string to this byte string
+   * builder.
+   *
    * @param s
-   *          The string whose UTF-8 encoding is to be appended to this
-   *          byte string builder.
+   *          The string whose UTF-8 encoding is to be appended to this byte
+   *          string builder.
    * @return This byte string builder.
    */
-  public ByteStringBuilder append(String s)
+  public ByteStringBuilder append(final String s)
   {
     if (s == null)
     {
@@ -667,14 +686,14 @@
 
 
   /**
-   * Appends the ASN.1 BER length encoding representation of the
-   * provided integer to this byte string builder.
-   * 
+   * Appends the ASN.1 BER length encoding representation of the provided
+   * integer to this byte string builder.
+   *
    * @param length
    *          The value to encode using the BER length encoding rules.
    * @return This byte string builder.
    */
-  public ByteStringBuilder appendBERLength(int length)
+  public ByteStringBuilder appendBERLength(final int length)
   {
     if ((length & 0x0000007F) == length)
     {
@@ -722,17 +741,16 @@
 
 
   /**
-   * Returns a {@link ByteSequenceReader} which can be used to
-   * incrementally read and decode data from this byte string builder.
+   * Returns a {@link ByteSequenceReader} which can be used to incrementally
+   * read and decode data from this byte string builder.
    * <p>
    * <b>NOTE:</b> all concurrent updates to this byte string builder are
-   * supported with the exception of {@link #clear()}. Any invocations
-   * of {@link #clear()} must be accompanied by a subsequent call to
-   * {@code ByteSequenceReader.rewind()}.
-   * 
-   * @return The {@link ByteSequenceReader} which can be used to
-   *         incrementally read and decode data from this byte string
-   *         builder.
+   * supported with the exception of {@link #clear()}. Any invocations of
+   * {@link #clear()} must be accompanied by a subsequent call to {@code
+   * ByteSequenceReader.rewind()}.
+   *
+   * @return The {@link ByteSequenceReader} which can be used to incrementally
+   *         read and decode data from this byte string builder.
    * @see #clear()
    */
   public ByteSequenceReader asReader()
@@ -745,7 +763,7 @@
   /**
    * {@inheritDoc}
    */
-  public byte byteAt(int index) throws IndexOutOfBoundsException
+  public byte byteAt(final int index) throws IndexOutOfBoundsException
   {
     if (index >= length || index < 0)
     {
@@ -760,9 +778,9 @@
    * Sets the length of this byte string builder to zero.
    * <p>
    * <b>NOTE:</b> if this method is called, then {@code
-   * ByteSequenceReader.rewind()} must also be called on any associated
-   * byte sequence readers in order for them to remain valid.
-   * 
+   * ByteSequenceReader.rewind()} must also be called on any associated byte
+   * sequence readers in order for them to remain valid.
+   *
    * @return This byte string builder.
    * @see #asReader()
    */
@@ -777,12 +795,11 @@
   /**
    * {@inheritDoc}
    */
-  public int compareTo(byte[] b, int offset, int length)
+  public int compareTo(final byte[] b, final int offset, final int length)
       throws IndexOutOfBoundsException
   {
     ByteString.checkArrayBounds(b, offset, length);
-    return ByteString.compareTo(this.buffer, 0, this.length, b, offset,
-        length);
+    return ByteString.compareTo(this.buffer, 0, this.length, b, offset, length);
   }
 
 
@@ -790,7 +807,7 @@
   /**
    * {@inheritDoc}
    */
-  public int compareTo(ByteSequence o)
+  public int compareTo(final ByteSequence o)
   {
     if (this == o)
     {
@@ -804,7 +821,7 @@
   /**
    * {@inheritDoc}
    */
-  public byte[] copyTo(byte[] b)
+  public byte[] copyTo(final byte[] b)
   {
     copyTo(b, 0);
     return b;
@@ -815,15 +832,14 @@
   /**
    * {@inheritDoc}
    */
-  public byte[] copyTo(byte[] b, int offset)
+  public byte[] copyTo(final byte[] b, final int offset)
       throws IndexOutOfBoundsException
   {
     if (offset < 0)
     {
       throw new IndexOutOfBoundsException();
     }
-    System.arraycopy(buffer, 0, b, offset, Math.min(length, b.length
-        - offset));
+    System.arraycopy(buffer, 0, b, offset, Math.min(length, b.length - offset));
     return b;
   }
 
@@ -832,7 +848,7 @@
   /**
    * {@inheritDoc}
    */
-  public ByteStringBuilder copyTo(ByteStringBuilder builder)
+  public ByteStringBuilder copyTo(final ByteStringBuilder builder)
   {
     builder.append(buffer, 0, length);
     return builder;
@@ -843,7 +859,7 @@
   /**
    * {@inheritDoc}
    */
-  public OutputStream copyTo(OutputStream stream) throws IOException
+  public OutputStream copyTo(final OutputStream stream) throws IOException
   {
     stream.write(buffer, 0, length);
     return stream;
@@ -852,20 +868,19 @@
 
 
   /**
-   * Ensures that the specified number of additional bytes will fit in
-   * this byte string builder and resizes it if necessary.
-   * 
+   * Ensures that the specified number of additional bytes will fit in this byte
+   * string builder and resizes it if necessary.
+   *
    * @param size
    *          The number of additional bytes.
    * @return This byte string builder.
    */
-  public ByteStringBuilder ensureAdditionalCapacity(int size)
+  public ByteStringBuilder ensureAdditionalCapacity(final int size)
   {
     final int newCount = this.length + size;
     if (newCount > buffer.length)
     {
-      final byte[] newbuffer =
-          new byte[Math.max(buffer.length << 1, newCount)];
+      final byte[] newbuffer = new byte[Math.max(buffer.length << 1, newCount)];
       System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
       buffer = newbuffer;
     }
@@ -877,30 +892,28 @@
   /**
    * {@inheritDoc}
    */
-  public boolean equals(byte[] b, int offset, int length)
+  public boolean equals(final byte[] b, final int offset, final int length)
       throws IndexOutOfBoundsException
   {
     ByteString.checkArrayBounds(b, offset, length);
-    return ByteString.equals(this.buffer, 0, this.length, b, offset,
-        length);
+    return ByteString.equals(this.buffer, 0, this.length, b, offset, length);
   }
 
 
 
   /**
-   * Indicates whether the provided object is equal to this byte string
-   * builder. In order for it to be considered equal, the provided
-   * object must be a byte sequence containing the same bytes in the
-   * same order.
-   * 
+   * Indicates whether the provided object is equal to this byte string builder.
+   * In order for it to be considered equal, the provided object must be a byte
+   * sequence containing the same bytes in the same order.
+   *
    * @param o
    *          The object for which to make the determination.
-   * @return {@code true} if the provided object is a byte sequence
-   *         whose content is equal to that of this byte string builder,
-   *         or {@code false} if not.
+   * @return {@code true} if the provided object is a byte sequence whose
+   *         content is equal to that of this byte string builder, or {@code
+   *         false} if not.
    */
   @Override
-  public boolean equals(Object o)
+  public boolean equals(final Object o)
   {
     if (this == o)
     {
@@ -920,18 +933,18 @@
 
 
   /**
-   * Returns the byte array that backs this byte string builder.
-   * Modifications to this byte string builder's content may cause the
-   * returned array's content to be modified, and vice versa.
+   * Returns the byte array that backs this byte string builder. Modifications
+   * to this byte string builder's content may cause the returned array's
+   * content to be modified, and vice versa.
    * <p>
-   * Note that the length of the returned array is only guaranteed to be
-   * the same as the length of this byte string builder immediately
-   * after a call to {@link #trimToSize()}.
+   * Note that the length of the returned array is only guaranteed to be the
+   * same as the length of this byte string builder immediately after a call to
+   * {@link #trimToSize()}.
    * <p>
-   * In addition, subsequent modifications to this byte string builder
-   * may cause the backing byte array to be reallocated thus decoupling
-   * the returned byte array from this byte string builder.
-   * 
+   * In addition, subsequent modifications to this byte string builder may cause
+   * the backing byte array to be reallocated thus decoupling the returned byte
+   * array from this byte string builder.
+   *
    * @return The byte array that backs this byte string builder.
    */
   public byte[] getBackingArray()
@@ -942,12 +955,12 @@
 
 
   /**
-   * Returns a hash code for this byte string builder. It will be the
-   * sum of all of the bytes contained in the byte string builder.
+   * Returns a hash code for this byte string builder. It will be the sum of all
+   * of the bytes contained in the byte string builder.
    * <p>
-   * <b>NOTE:</b> subsequent changes to this byte string builder will
-   * invalidate the returned hash code.
-   * 
+   * <b>NOTE:</b> subsequent changes to this byte string builder will invalidate
+   * the returned hash code.
+   *
    * @return A hash code for this byte string builder.
    */
   @Override
@@ -971,29 +984,28 @@
   /**
    * Sets the length of this byte string builder.
    * <p>
-   * If the <code>newLength</code> argument is less than the current
-   * length, the length is changed to the specified length.
+   * If the <code>newLength</code> argument is less than the current length, the
+   * length is changed to the specified length.
    * <p>
-   * If the <code>newLength</code> argument is greater than or equal to
-   * the current length, then the capacity is increased and sufficient
-   * null bytes are appended so that length becomes the
-   * <code>newLength</code> argument.
+   * If the <code>newLength</code> argument is greater than or equal to the
+   * current length, then the capacity is increased and sufficient null bytes
+   * are appended so that length becomes the <code>newLength</code> argument.
    * <p>
-   * The <code>newLength</code> argument must be greater than or equal
-   * to <code>0</code>.
-   * 
+   * The <code>newLength</code> argument must be greater than or equal to
+   * <code>0</code>.
+   *
    * @param newLength
    *          The new length.
    * @return This byte string builder.
    * @throws IndexOutOfBoundsException
    *           If the <code>newLength</code> argument is negative.
    */
-  public ByteStringBuilder setLength(int newLength)
+  public ByteStringBuilder setLength(final int newLength)
+      throws IndexOutOfBoundsException
   {
     if (newLength < 0)
     {
-      throw new IndexOutOfBoundsException("Negative newLength: "
-          + newLength);
+      throw new IndexOutOfBoundsException("Negative newLength: " + newLength);
     }
 
     if (newLength > length)
@@ -1014,32 +1026,29 @@
 
 
   /**
-   * Returns a new byte sequence that is a subsequence of this byte
-   * sequence.
+   * Returns a new byte sequence that is a subsequence of this byte sequence.
    * <p>
-   * The subsequence starts with the byte value at the specified {@code
-   * start} index and ends with the byte value at index {@code end - 1}.
-   * The length (in bytes) of the returned sequence is {@code end -
-   * start}, so if {@code start == end} then an empty sequence is
-   * returned.
+   * The subsequence starts with the byte value at the specified {@code start}
+   * index and ends with the byte value at index {@code end - 1}. The length (in
+   * bytes) of the returned sequence is {@code end - start}, so if {@code start
+   * == end} then an empty sequence is returned.
    * <p>
-   * <b>NOTE:</b> the returned sub-sequence will be robust against all
-   * updates to the byte string builder except for invocations of the
-   * method {@link #clear()}. If a permanent immutable byte sequence is
-   * required then callers should invoke {@code toByteString()} on the
-   * returned byte sequence.
-   * 
+   * <b>NOTE:</b> the returned sub-sequence will be robust against all updates
+   * to the byte string builder except for invocations of the method
+   * {@link #clear()}. If a permanent immutable byte sequence is required then
+   * callers should invoke {@code toByteString()} on the returned byte sequence.
+   *
    * @param start
    *          The start index, inclusive.
    * @param end
    *          The end index, exclusive.
    * @return The newly created byte subsequence.
    * @throws IndexOutOfBoundsException
-   *           If {@code start} or {@code end} are negative, if {@code
-   *           end} is greater than {@code length()}, or if {@code
-   *           start} is greater than {@code end}.
+   *           If {@code start} or {@code end} are negative, if {@code end} is
+   *           greater than {@code length()}, or if {@code start} is greater
+   *           than {@code end}.
    */
-  public ByteSequence subSequence(int start, int end)
+  public ByteSequence subSequence(final int start, final int end)
       throws IndexOutOfBoundsException
   {
     if (start < 0 || start > end || end > length)
@@ -1063,12 +1072,11 @@
 
 
   /**
-   * Returns the {@link ByteString} representation of this byte string
-   * builder. Subsequent changes to this byte string builder will not
-   * modify the returned {@link ByteString}.
-   * 
-   * @return The {@link ByteString} representation of this byte
-   *         sequence.
+   * Returns the {@link ByteString} representation of this byte string builder.
+   * Subsequent changes to this byte string builder will not modify the returned
+   * {@link ByteString}.
+   *
+   * @return The {@link ByteString} representation of this byte sequence.
    */
   public ByteString toByteString()
   {
@@ -1091,10 +1099,10 @@
 
 
   /**
-   * Attempts to reduce storage used for this byte string builder. If
-   * the buffer is larger than necessary to hold its current sequence of
-   * bytes, then it may be resized to become more space efficient.
-   * 
+   * Attempts to reduce storage used for this byte string builder. If the buffer
+   * is larger than necessary to hold its current sequence of bytes, then it may
+   * be resized to become more space efficient.
+   *
    * @return This byte string builder.
    */
   public ByteStringBuilder trimToSize()
diff --git a/sdk/src/org/opends/sdk/CancelledResultException.java b/sdk/src/org/opends/sdk/CancelledResultException.java
index 5c4f80c..8abe3d5 100644
--- a/sdk/src/org/opends/sdk/CancelledResultException.java
+++ b/sdk/src/org/opends/sdk/CancelledResultException.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
@@ -34,20 +34,20 @@
 
 
 /**
- * Thrown when the result code returned in a Result indicates that the
- * Request was cancelled. More specifically, this exception is used for
- * the following error result codes:
+ * Thrown when the result code returned in a Result indicates that the Request
+ * was cancelled. More specifically, this exception is used for the following
+ * error result codes:
  * <ul>
- * <li>{@link ResultCode#CANCELLED} - the requested operation was
+ * <li>{@link ResultCode#CANCELLED CANCELLED} - the requested operation was
  * cancelled.
- * <li>{@link ResultCode#CLIENT_SIDE_USER_CANCELLED} - the requested
- * operation was cancelled by the user.
+ * <li>{@link ResultCode#CLIENT_SIDE_USER_CANCELLED CLIENT_SIDE_USER_CANCELLED}
+ * - the requested operation was cancelled by the user.
  * </ul>
  */
 @SuppressWarnings("serial")
 public class CancelledResultException extends ErrorResultException
 {
-  CancelledResultException(Result result)
+  CancelledResultException(final Result result)
   {
     super(result);
   }
diff --git a/sdk/src/org/opends/sdk/ConditionResult.java b/sdk/src/org/opends/sdk/ConditionResult.java
index f6a7ddd..1a67178 100644
--- a/sdk/src/org/opends/sdk/ConditionResult.java
+++ b/sdk/src/org/opends/sdk/ConditionResult.java
@@ -30,12 +30,11 @@
 
 
 /**
- * The result of a tri-state logical expression. Condition results are
- * used to represent the result of a conditional evaluation that can
- * yield three possible values: {@code FALSE} (i.e. "no"), {@code TRUE}
- * (i.e. "yes"), or {@code UNDEFINED} (i.e. "maybe"). A result of
- * {@code UNDEFINED} indicates that further investigation may be
- * required.
+ * The result of a tri-state logical expression. Condition results are used to
+ * represent the result of a conditional evaluation that can yield three
+ * possible values: {@code FALSE} (i.e. "no"), {@code TRUE} (i.e. "yes"), or
+ * {@code UNDEFINED} (i.e. "maybe"). A result of {@code UNDEFINED} indicates
+ * that further investigation may be required.
  */
 public enum ConditionResult
 {
@@ -45,8 +44,8 @@
   FALSE("false"),
 
   /**
-   * Indicates that the condition could not be evaluated and its result
-   * is undefined.
+   * Indicates that the condition could not be evaluated and its result is
+   * undefined.
    */
   UNDEFINED("undefined"),
 
@@ -56,30 +55,29 @@
   TRUE("true");
 
   // Boolean -> ConditionResult map.
-  private static final boolean[] booleanMap = { false, false, true };
+  private static final boolean[] BOOLEAN_MAP = { false, false, true };
 
   // AND truth table.
-  private static final ConditionResult[][] logicalAND =
-      { { FALSE, FALSE, FALSE }, { FALSE, UNDEFINED, UNDEFINED },
-          { FALSE, UNDEFINED, TRUE }, };
+  private static final ConditionResult[][] LOGICAL_AND = {
+      { FALSE, FALSE, FALSE }, { FALSE, UNDEFINED, UNDEFINED },
+      { FALSE, UNDEFINED, TRUE }, };
 
   // NOT truth table.
-  private static final ConditionResult[] logicalNOT =
-      { TRUE, UNDEFINED, FALSE };
+  private static final ConditionResult[] LOGICAL_NOT = { TRUE, UNDEFINED, FALSE };
 
   // OR truth table.
-  private static final ConditionResult[][] logicalOR =
-      { { FALSE, UNDEFINED, TRUE }, { UNDEFINED, UNDEFINED, TRUE },
-          { TRUE, TRUE, TRUE }, };
+  private static final ConditionResult[][] LOGICAL_OR = {
+      { FALSE, UNDEFINED, TRUE }, { UNDEFINED, UNDEFINED, TRUE },
+      { TRUE, TRUE, TRUE }, };
 
 
 
   /**
-   * Returns the logical AND of zero condition results, which is always
-   * {@code TRUE}.
+   * Returns the logical AND of zero condition results, which is always {@code
+   * TRUE}.
    *
-   * @return The logical OR of zero condition results, which is always
-   *         {@code TRUE}.
+   * @return The logical OR of zero condition results, which is always {@code
+   *         TRUE}.
    */
   public static ConditionResult and()
   {
@@ -89,15 +87,15 @@
 
 
   /**
-   * Returns the logical AND of the provided condition result, which is
-   * always {@code r}.
+   * Returns the logical AND of the provided condition result, which is always
+   * {@code r}.
    *
    * @param r
    *          The condition result.
-   * @return The logical AND of the provided condition result, which is
-   *         always {@code r}.
+   * @return The logical AND of the provided condition result, which is always
+   *         {@code r}.
    */
-  public static ConditionResult and(ConditionResult r)
+  public static ConditionResult and(final ConditionResult r)
   {
     return r;
   }
@@ -105,24 +103,26 @@
 
 
   /**
-   * Returns the logical AND of the provided condition results, which is
-   * {@code TRUE} if all of the provided condition results are {@code
-   * TRUE}, {@code FALSE} if at least one of them is {@code FALSE}, and
-   * {@code UNDEFINED} otherwise. Note that {@code TRUE} is returned if
-   * the provided list of results is empty.
+   * Returns the logical AND of the provided condition results, which is {@code
+   * TRUE} if all of the provided condition results are {@code TRUE}, {@code
+   * FALSE} if at least one of them is {@code FALSE}, and {@code UNDEFINED}
+   * otherwise. Note that {@code TRUE} is returned if the provided list of
+   * results is empty.
    *
    * @param results
    *          The condition results to be compared.
    * @return The logical AND of the provided condition results.
    */
-  public static ConditionResult and(ConditionResult... results)
+  public static ConditionResult and(final ConditionResult... results)
   {
     ConditionResult finalResult = TRUE;
-    for (ConditionResult result : results)
+    for (final ConditionResult result : results)
     {
       finalResult = and(finalResult, result);
       if (finalResult == FALSE)
+      {
         break;
+      }
     }
     return finalResult;
   }
@@ -130,10 +130,10 @@
 
 
   /**
-   * Returns the logical AND of the provided condition results, which is
-   * {@code TRUE} if both of the provided condition results are {@code
-   * TRUE}, {@code FALSE} if at least one of them is {@code FALSE} , and
-   * {@code UNDEFINED} otherwise.
+   * Returns the logical AND of the provided condition results, which is {@code
+   * TRUE} if both of the provided condition results are {@code TRUE}, {@code
+   * FALSE} if at least one of them is {@code FALSE} , and {@code UNDEFINED}
+   * otherwise.
    *
    * @param r1
    *          The first condition result to be compared.
@@ -141,37 +141,36 @@
    *          The second condition result to be compared.
    * @return The logical AND of the provided condition results.
    */
-  public static ConditionResult and(ConditionResult r1,
-      ConditionResult r2)
+  public static ConditionResult and(final ConditionResult r1,
+      final ConditionResult r2)
   {
-    return logicalAND[r1.ordinal()][r2.ordinal()];
+    return LOGICAL_AND[r1.ordinal()][r2.ordinal()];
   }
 
 
 
   /**
-   * Returns the logical NOT of the provided condition result, which is
-   * {@code TRUE} if the provided condition result is {@code FALSE},
-   * {@code TRUE} if it is {@code FALSE}, and {@code UNDEFINED}
-   * otherwise.
+   * Returns the logical NOT of the provided condition result, which is {@code
+   * TRUE} if the provided condition result is {@code FALSE}, {@code TRUE} if it
+   * is {@code FALSE}, and {@code UNDEFINED} otherwise.
    *
    * @param r
    *          The condition result to invert.
    * @return The logical NOT of the provided condition result.
    */
-  public static ConditionResult not(ConditionResult r)
+  public static ConditionResult not(final ConditionResult r)
   {
-    return logicalNOT[r.ordinal()];
+    return LOGICAL_NOT[r.ordinal()];
   }
 
 
 
   /**
-   * Returns the logical OR of zero condition results, which is always
-   * {@code FALSE}.
+   * Returns the logical OR of zero condition results, which is always {@code
+   * FALSE}.
    *
-   * @return The logical OR of zero condition results, which is always
-   *         {@code FALSE}.
+   * @return The logical OR of zero condition results, which is always {@code
+   *         FALSE}.
    */
   public static ConditionResult or()
   {
@@ -181,15 +180,15 @@
 
 
   /**
-   * Returns the logical OR of the provided condition result, which is
-   * always {@code r}.
+   * Returns the logical OR of the provided condition result, which is always
+   * {@code r}.
    *
    * @param r
    *          The condition result.
-   * @return The logical OR of the provided condition result, which is
-   *         always {@code r}.
+   * @return The logical OR of the provided condition result, which is always
+   *         {@code r}.
    */
-  public static ConditionResult or(ConditionResult r)
+  public static ConditionResult or(final ConditionResult r)
   {
     return r;
   }
@@ -197,24 +196,26 @@
 
 
   /**
-   * Returns the logical OR of the provided condition results, which is
-   * {@code FALSE} if all of the provided condition results are {@code
-   * FALSE}, {@code TRUE} if at least one of them is {@code TRUE}, and
-   * {@code UNDEFINED} otherwise. Note that {@code FALSE} is returned if
-   * the provided list of results is empty.
+   * Returns the logical OR of the provided condition results, which is {@code
+   * FALSE} if all of the provided condition results are {@code FALSE}, {@code
+   * TRUE} if at least one of them is {@code TRUE}, and {@code UNDEFINED}
+   * otherwise. Note that {@code FALSE} is returned if the provided list of
+   * results is empty.
    *
    * @param results
    *          The condition results to be compared.
    * @return The logical OR of the provided condition results.
    */
-  public static ConditionResult or(ConditionResult... results)
+  public static ConditionResult or(final ConditionResult... results)
   {
     ConditionResult finalResult = FALSE;
-    for (ConditionResult result : results)
+    for (final ConditionResult result : results)
     {
       finalResult = and(finalResult, result);
       if (finalResult == TRUE)
+      {
         break;
+      }
     }
     return finalResult;
   }
@@ -222,10 +223,10 @@
 
 
   /**
-   * Returns the logical OR of the provided condition results, which is
-   * {@code FALSE} if both of the provided condition results are {@code
-   * FALSE}, {@code TRUE} if at least one of them is {@code TRUE} , and
-   * {@code UNDEFINED} otherwise.
+   * Returns the logical OR of the provided condition results, which is {@code
+   * FALSE} if both of the provided condition results are {@code FALSE}, {@code
+   * TRUE} if at least one of them is {@code TRUE} , and {@code UNDEFINED}
+   * otherwise.
    *
    * @param r1
    *          The first condition result to be compared.
@@ -233,35 +234,37 @@
    *          The second condition result to be compared.
    * @return The logical OR of the provided condition results.
    */
-  public static ConditionResult or(ConditionResult r1,
-      ConditionResult r2)
+  public static ConditionResult or(final ConditionResult r1,
+      final ConditionResult r2)
   {
-    return logicalOR[r1.ordinal()][r2.ordinal()];
+    return LOGICAL_OR[r1.ordinal()][r2.ordinal()];
   }
 
 
 
   /**
-   * Returns the condition result which is equivalent to the provided
-   * boolean value.
+   * Returns the condition result which is equivalent to the provided boolean
+   * value.
    *
    * @param b
    *          The boolean value.
-   * @return {@code TRUE} if {@code b} was {@code true}, otherwise
-   *         {@code FALSE}.
+   * @return {@code TRUE} if {@code b} was {@code true}, otherwise {@code FALSE}
+   *         .
    */
-  public static ConditionResult valueOf(boolean b)
+  public static ConditionResult valueOf(final boolean b)
   {
     return b ? TRUE : FALSE;
   }
 
+
+
   // The human-readable name for this result.
   private final String resultName;
 
 
 
   // Prevent instantiation.
-  private ConditionResult(String resultName)
+  private ConditionResult(final String resultName)
   {
     this.resultName = resultName;
   }
@@ -269,15 +272,15 @@
 
 
   /**
-   * Converts this condition result to a boolean value. {@code FALSE}
-   * and {@code UNDEFINED} are both converted to {@code false}, and
-   * {@code TRUE} is converted to {@code true}.
+   * Converts this condition result to a boolean value. {@code FALSE} and
+   * {@code UNDEFINED} are both converted to {@code false}, and {@code TRUE} is
+   * converted to {@code true}.
    *
    * @return The boolean equivalent of this condition result.
    */
   public boolean toBoolean()
   {
-    return booleanMap[ordinal()];
+    return BOOLEAN_MAP[ordinal()];
   }
 
 
diff --git a/sdk/src/org/opends/sdk/Connection.java b/sdk/src/org/opends/sdk/Connection.java
index 74ee0fd..96828e1 100644
--- a/sdk/src/org/opends/sdk/Connection.java
+++ b/sdk/src/org/opends/sdk/Connection.java
@@ -40,80 +40,59 @@
 
 
 /**
- * A synchronous connection with a Directory Server over which read and
- * update operations may be performed. See RFC 4511 for the LDAPv3
- * protocol specification and more information about the types of
- * operations defined in LDAP.
+ * A synchronous connection with a Directory Server over which read and update
+ * operations may be performed. See RFC 4511 for the LDAPv3 protocol
+ * specification and more information about the types of operations defined in
+ * LDAP.
  * <p>
  * <h3>Operation processing</h3>
  * <p>
  * All operations are performed synchronously and return an appropriate
- * {@link Result} representing the final status of the operation.
- * Operation failures, for whatever reason, are signalled using an
+ * {@link Result} representing the final status of the operation. Operation
+ * failures, for whatever reason, are signalled using an
  * {@link ErrorResultException}.
  * <p>
  * <h3>Closing connections</h3>
  * <p>
  * Applications must ensure that a connection is closed by calling
- * {@link #close()} even if a fatal error occurs on the connection. Once
- * a connection has been closed by the client application, any attempts
- * to continue to use the connection will result in an
- * {@link IllegalStateException} being thrown. Note that, if a fatal
- * error is encountered on the connection, then the application can
- * continue to use the connection. In this case all requests subsequent
- * to the failure will fail with an appropriate
- * {@link ErrorResultException} when their result is retrieved.
+ * {@link #close()} even if a fatal error occurs on the connection. Once a
+ * connection has been closed by the client application, any attempts to
+ * continue to use the connection will result in an
+ * {@link IllegalStateException} being thrown. Note that, if a fatal error is
+ * encountered on the connection, then the application can continue to use the
+ * connection. In this case all requests subsequent to the failure will fail
+ * with an appropriate {@link ErrorResultException} when their result is
+ * retrieved.
  * <p>
  * <h3>Event notification</h3>
  * <p>
- * Applications can choose to be notified when a connection is closed by
- * the application, receives an unsolicited notification, or experiences
- * a fatal error by registering a {@link ConnectionEventListener} with
- * the connection using the {@link #addConnectionEventListener} method.
- * <p>
- * <h3>TO DO</h3>
- * <p>
- * <ul>
- * <li>do we need isClosed() and isValid()?
- * <li>do we need connection event notification of client close? JDBC
- * and JCA have this functionality in their pooled (managed) connection
- * APIs. We need some form of event notification at the app level for
- * unsolicited notifications.
- * <li>method for performing update operation (e.g. LDIF change
- * records).
- * <li>should unsupported methods throw UnsupportedOperationException or
- * throw an ErrorResultException using an UnwillingToPerform result code
- * (or something similar)?
- * <li>Handler version of search.
- * <li>Finish off Search APIs to support blocking queues and
- * collections.
- * <li>searchSingleEntry Javadoc needs finishing. Code sample is
- * incorrect. How about references? What exceptions are thrown?
- * </ul>
+ * Applications can choose to be notified when a connection is closed by the
+ * application, receives an unsolicited notification, or experiences a fatal
+ * error by registering a {@link ConnectionEventListener} with the connection
+ * using the {@link #addConnectionEventListener} method.
  *
- * @see <a href="http://tools.ietf.org/html/rfc4511">RFC 4511 -
- *      Lightweight Directory Access Protocol (LDAP): The Protocol </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4511">RFC 4511 - Lightweight
+ *      Directory Access Protocol (LDAP): The Protocol </a>
  */
 public interface Connection extends Closeable
 {
 
   /**
-   * Adds an entry to the Directory Server using the provided add
-   * request.
+   * Adds an entry to the Directory Server using the provided add request.
    *
    * @param request
    *          The add request.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support add operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
@@ -137,27 +116,26 @@
    *          The entry to be added.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support add operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code entry} was {@code null} .
    */
-  Result add(Entry entry) throws ErrorResultException,
-      InterruptedException, UnsupportedOperationException,
-      IllegalStateException, NullPointerException;
+  Result add(Entry entry) throws ErrorResultException, InterruptedException,
+      UnsupportedOperationException, IllegalStateException,
+      NullPointerException;
 
 
 
   /**
-   * Adds an entry to the Directory Server using the provided lines of
-   * LDIF.
+   * Adds an entry to the Directory Server using the provided lines of LDIF.
    * <p>
    * This method is equivalent to the following code:
    *
@@ -167,22 +145,22 @@
    * </pre>
    *
    * @param ldifLines
-   *          Lines of LDIF containing the an LDIF add change record or
-   *          an LDIF entry record.
+   *          Lines of LDIF containing the an LDIF add change record or an LDIF
+   *          entry record.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support add operations.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code ldifLines} was empty, or contained invalid
-   *           LDIF, or could not be decoded using the default schema.
+   *           If {@code ldifLines} was empty, or contained invalid LDIF, or
+   *           could not be decoded using the default schema.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null} .
    */
@@ -195,15 +173,15 @@
 
   /**
    * Registers the provided connection event listener so that it will be
-   * notified when this connection is closed by the application,
-   * receives an unsolicited notification, or experiences a fatal error.
+   * notified when this connection is closed by the application, receives an
+   * unsolicited notification, or experiences a fatal error.
    *
    * @param listener
-   *          The listener which wants to be notified when events occur
-   *          on this connection.
+   *          The listener which wants to be notified when events occur on this
+   *          connection.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If the {@code listener} was {@code null}.
    */
@@ -213,22 +191,21 @@
 
 
   /**
-   * Authenticates to the Directory Server using the provided bind
-   * request.
+   * Authenticates to the Directory Server using the provided bind request.
    *
    * @param request
    *          The bind request.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support bind operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
@@ -239,8 +216,8 @@
 
 
   /**
-   * Authenticates to the Directory Server using simple authentication
-   * and the provided user name and password.
+   * Authenticates to the Directory Server using simple authentication and the
+   * provided user name and password.
    * <p>
    * This method is equivalent to the following code:
    *
@@ -250,44 +227,43 @@
    * </pre>
    *
    * @param name
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as, which may be empty.
-   * @param password
-   *          The password of the Directory object that the client
+   *          The distinguished name of the Directory object that the client
    *          wishes to bind as, which may be empty.
+   * @param password
+   *          The password of the Directory object that the client wishes to
+   *          bind as, which may be empty.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
+   *           If {@code name} could not be decoded using the default schema.
    * @throws UnsupportedOperationException
    *           If this connection does not support bind operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code name} or {@code password} was {@code null}.
    */
-  BindResult bind(String name, String password)
-      throws ErrorResultException, InterruptedException,
-      LocalizedIllegalArgumentException, UnsupportedOperationException,
-      IllegalStateException, NullPointerException;
+  BindResult bind(String name, String password) throws ErrorResultException,
+      InterruptedException, LocalizedIllegalArgumentException,
+      UnsupportedOperationException, IllegalStateException,
+      NullPointerException;
 
 
 
   /**
-   * Releases any resources associated with this connection. For
-   * physical connections to a Directory Server this will mean that an
-   * unbind request is sent and the underlying socket is closed.
+   * Releases any resources associated with this connection. For physical
+   * connections to a Directory Server this will mean that an unbind request is
+   * sent and the underlying socket is closed.
    * <p>
-   * Other connection implementations may behave differently, and may
-   * choose not to send an unbind request if its use is inappropriate
-   * (for example a pooled connection will be released and returned to
-   * its connection pool without ever issuing an unbind request).
+   * Other connection implementations may behave differently, and may choose not
+   * to send an unbind request if its use is inappropriate (for example a pooled
+   * connection will be released and returned to its connection pool without
+   * ever issuing an unbind request).
    * <p>
    * This method is equivalent to the following code:
    *
@@ -296,71 +272,65 @@
    * connection.close(request);
    * </pre>
    *
-   * Calling {@code close} on a connection that is already closed has no
-   * effect.
+   * Calling {@code close} on a connection that is already closed has no effect.
    */
   void close();
 
 
 
   /**
-   * Releases any resources associated with this connection. For
-   * physical connections to a Directory Server this will mean that the
-   * provided unbind request is sent and the underlying socket is
-   * closed.
+   * Releases any resources associated with this connection. For physical
+   * connections to a Directory Server this will mean that the provided unbind
+   * request is sent and the underlying socket is closed.
    * <p>
-   * Other connection implementations may behave differently, and may
-   * choose to ignore the provided unbind request if its use is
-   * inappropriate (for example a pooled connection will be released and
-   * returned to its connection pool without ever issuing an unbind
-   * request).
+   * Other connection implementations may behave differently, and may choose to
+   * ignore the provided unbind request if its use is inappropriate (for example
+   * a pooled connection will be released and returned to its connection pool
+   * without ever issuing an unbind request).
    * <p>
-   * Calling {@code close} on a connection that is already closed has no
-   * effect.
+   * Calling {@code close} on a connection that is already closed has no effect.
    *
    * @param request
-   *          The unbind request to use in the case where a physical
-   *          connection is closed.
+   *          The unbind request to use in the case where a physical connection
+   *          is closed.
    * @param reason
    *          A reason describing why the connection was closed.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
-  void close(UnbindRequest request, String reason)
-      throws NullPointerException;
+  void close(UnbindRequest request, String reason) throws NullPointerException;
 
 
 
   /**
-   * Compares an entry in the Directory Server using the provided
-   * compare request.
+   * Compares an entry in the Directory Server using the provided compare
+   * request.
    *
    * @param request
    *          The compare request.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support compare operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
-  CompareResult compare(CompareRequest request)
-      throws ErrorResultException, InterruptedException,
-      UnsupportedOperationException, IllegalStateException,
-      NullPointerException;
+  CompareResult compare(CompareRequest request) throws ErrorResultException,
+      InterruptedException, UnsupportedOperationException,
+      IllegalStateException, NullPointerException;
 
 
 
   /**
-   * Compares the named entry in the Directory Server against the
-   * provided attribute value assertion.
+   * Compares the named entry in the Directory Server against the provided
+   * attribute value assertion.
    * <p>
    * This method is equivalent to the following code:
    *
@@ -378,47 +348,46 @@
    *          The assertion value to be compared.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} or {@code AttributeDescription} could not
-   *           be decoded using the default schema.
+   *           If {@code name} or {@code AttributeDescription} could not be
+   *           decoded using the default schema.
    * @throws UnsupportedOperationException
    *           If this connection does not support compare operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code name}, {@code attributeDescription}, or {@code
    *           assertionValue} was {@code null}.
    */
   CompareResult compare(String name, String attributeDescription,
-      String assertionValue) throws ErrorResultException,
-      InterruptedException, LocalizedIllegalArgumentException,
-      UnsupportedOperationException, IllegalStateException,
-      NullPointerException;
+      String assertionValue) throws ErrorResultException, InterruptedException,
+      LocalizedIllegalArgumentException, UnsupportedOperationException,
+      IllegalStateException, NullPointerException;
 
 
 
   /**
-   * Deletes an entry from the Directory Server using the provided
-   * delete request.
+   * Deletes an entry from the Directory Server using the provided delete
+   * request.
    *
    * @param request
    *          The delete request.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support delete operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
@@ -442,31 +411,28 @@
    *          The distinguished name of the entry to be deleted.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
+   *           If {@code name} could not be decoded using the default schema.
    * @throws UnsupportedOperationException
    *           If this connection does not support delete operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  Result delete(String name) throws ErrorResultException,
-      InterruptedException, LocalizedIllegalArgumentException,
-      UnsupportedOperationException, IllegalStateException,
-      NullPointerException;
+  Result delete(String name) throws ErrorResultException, InterruptedException,
+      LocalizedIllegalArgumentException, UnsupportedOperationException,
+      IllegalStateException, NullPointerException;
 
 
 
   /**
-   * Requests that the Directory Server performs the provided extended
-   * request.
+   * Requests that the Directory Server performs the provided extended request.
    *
    * @param <R>
    *          The type of result returned by the extended request.
@@ -474,19 +440,19 @@
    *          The extended request.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support extended operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
-  <R extends Result> R extendedRequest(ExtendedRequest<R> request)
+  <R extends ExtendedResult> R extendedRequest(ExtendedRequest<R> request)
       throws ErrorResultException, InterruptedException,
       UnsupportedOperationException, IllegalStateException,
       NullPointerException;
@@ -494,35 +460,65 @@
 
 
   /**
-   * Requests that the Directory Server performs the provided extended
-   * request.
-   * <p>
-   * This method is equivalent to the following code:
+   * Requests that the Directory Server performs the provided extended request,
+   * optionally listening for any intermediate responses.
    *
-   * <pre>
-   * GenericExtendedRequest request = new GenericExtendedRequest(
-   *     requestName, requestValue);
-   * connection.extendedRequest(request);
-   * </pre>
-   *
-   * @param requestName
-   *          The dotted-decimal representation of the unique OID
-   *          corresponding to the extended request.
-   * @param requestValue
-   *          The content of the extended request in a form defined by
-   *          the extended operation, or {@code null} if there is no
-   *          content.
+   * @param <R>
+   *          The type of result returned by the extended request.
+   * @param request
+   *          The extended request.
+   * @param handler
+   *          An intermediate response handler which can be used to process any
+   *          intermediate responses as they are received, may be {@code null}.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support extended operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
+   * @throws NullPointerException
+   *           If {@code request} was {@code null}.
+   */
+  <R extends ExtendedResult> R extendedRequest(ExtendedRequest<R> request,
+      IntermediateResponseHandler handler) throws ErrorResultException,
+      InterruptedException, UnsupportedOperationException,
+      IllegalStateException, NullPointerException;
+
+
+
+  /**
+   * Requests that the Directory Server performs the provided extended request.
+   * <p>
+   * This method is equivalent to the following code:
+   *
+   * <pre>
+   * GenericExtendedRequest request = new GenericExtendedRequest(requestName,
+   *     requestValue);
+   * connection.extendedRequest(request);
+   * </pre>
+   *
+   * @param requestName
+   *          The dotted-decimal representation of the unique OID corresponding
+   *          to the extended request.
+   * @param requestValue
+   *          The content of the extended request in a form defined by the
+   *          extended operation, or {@code null} if there is no content.
+   * @return The result of the operation.
+   * @throws ErrorResultException
+   *           If the result code indicates that the request failed for some
+   *           reason.
+   * @throws InterruptedException
+   *           If the current thread was interrupted while waiting.
+   * @throws UnsupportedOperationException
+   *           If this connection does not support extended operations.
+   * @throws IllegalStateException
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code requestName} was {@code null}.
    */
@@ -533,74 +529,42 @@
 
 
 
-  //
-  //
-  //
-  // /**
-  // * Indicates whether or not this connection is valid. A connection
-  // is
-  // * not valid if the method {@code close} has been called on it or if
-  // * certain fatal errors have occurred. This method is guaranteed to
-  // * return {@code false} only when it is called after the method
-  // * {@code close} has been called.
-  // * <p>
-  // * Implementations may choose to send a no-op request to the
-  // * underlying Directory Server in order to determine if the
-  // underlying
-  // * connection is still valid.
-  // *
-  // * @return {@code true} if this connection is valid, or {@code
-  // false}
-  // * otherwise.
-  // * @throws InterruptedException
-  // * If the current thread was interrupted while waiting.
-  // */
-  // boolean isValid() throws InterruptedException;
-  //
-  //
-  //
-  // /**
-  // * Indicates whether or not this connection is valid. A connection
-  // is
-  // * not valid if the method {@code close} has been called on it or if
-  // * certain fatal errors have occurred. This method is guaranteed to
-  // * return {@code false} only when it is called after the method
-  // * {@code close} has been called.
-  // * <p>
-  // * Implementations may choose to send a no-op request to the
-  // * underlying Directory Server in order to determine if the
-  // underlying
-  // * connection is still valid.
-  // *
-  // * @param timeout
-  // * The maximum time to wait.
-  // * @param unit
-  // * The time unit of the timeout argument.
-  // * @return {@code true} if this connection is valid, or {@code
-  // false}
-  // * otherwise.
-  // * @throws InterruptedException
-  // * If the current thread was interrupted while waiting.
-  // * @throws TimeoutException
-  // * If the wait timed out.
-  // */
-  // boolean isValid(long timeout, TimeUnit unit)
-  // throws InterruptedException, TimeoutException;
+  /**
+   * Returns an asynchronous connection sharing the same underlying network
+   * connection as this synchronous connection.
+   *
+   * @return An asynchronous connection sharing the same underlying network
+   *         connection as this synchronous connection.
+   */
+  AsynchronousConnection getAsynchronousConnection();
+
+
 
   /**
-   * Indicates whether or not this connection has been explicitly closed
-   * by calling {@code close}. This method will not return {@code true}
-   * if a fatal error has occurred on the connection unless {@code
-   * close} has been called.
+   * Indicates whether or not this connection has been explicitly closed by
+   * calling {@code close}. This method will not return {@code true} if a fatal
+   * error has occurred on the connection unless {@code close} has been called.
    *
-   * @return {@code true} if this connection has been explicitly closed
-   *         by calling {@code close}, or {@code false} otherwise.
+   * @return {@code true} if this connection has been explicitly closed by
+   *         calling {@code close}, or {@code false} otherwise.
    */
   boolean isClosed();
 
 
 
   /**
+   * Returns {@code true} if this connection has not been closed and no fatal
+   * errors have been detected. This method is guaranteed to return {@code
+   * false} only when it is called after the method {@code close} has been
+   * called.
+   *
+   * @return {@code true} if this connection is valid, {@code false} otherwise.
+   */
+  boolean isValid();
+
+
+
+  /**
    * Modifies an entry in the Directory Server using the provided modify
    * request.
    *
@@ -608,15 +572,15 @@
    *          The modify request.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support modify operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
@@ -627,8 +591,7 @@
 
 
   /**
-   * Modifies an entry in the Directory Server using the provided lines
-   * of LDIF.
+   * Modifies an entry in the Directory Server using the provided lines of LDIF.
    * <p>
    * This method is equivalent to the following code:
    *
@@ -638,22 +601,21 @@
    * </pre>
    *
    * @param ldifLines
-   *          Lines of LDIF containing the a single LDIF modify change
-   *          record.
+   *          Lines of LDIF containing the a single LDIF modify change record.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support modify operations.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code ldifLines} was empty, or contained invalid
-   *           LDIF, or could not be decoded using the default schema.
+   *           If {@code ldifLines} was empty, or contained invalid LDIF, or
+   *           could not be decoded using the default schema.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null} .
    */
@@ -665,22 +627,22 @@
 
 
   /**
-   * Renames an entry in the Directory Server using the provided modify
-   * DN request.
+   * Renames an entry in the Directory Server using the provided modify DN
+   * request.
    *
    * @param request
    *          The modify DN request.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support modify DN operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
@@ -691,8 +653,7 @@
 
 
   /**
-   * Renames the named entry in the Directory Server using the provided
-   * new RDN.
+   * Renames the named entry in the Directory Server using the provided new RDN.
    * <p>
    * This method is equivalent to the following code:
    *
@@ -707,60 +668,60 @@
    *          The new RDN of the entry.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} or {@code newRDN} could not be decoded
-   *           using the default schema.
+   *           If {@code name} or {@code newRDN} could not be decoded using the
+   *           default schema.
    * @throws UnsupportedOperationException
    *           If this connection does not support modify DN operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code name} or {@code newRDN} was {@code null}.
    */
-  Result modifyDN(String name, String newRDN)
-      throws ErrorResultException, LocalizedIllegalArgumentException,
-      InterruptedException, UnsupportedOperationException,
-      IllegalStateException, NullPointerException;
+  Result modifyDN(String name, String newRDN) throws ErrorResultException,
+      LocalizedIllegalArgumentException, InterruptedException,
+      UnsupportedOperationException, IllegalStateException,
+      NullPointerException;
 
 
 
   /**
    * Reads the named entry from the Directory Server.
    * <p>
-   * If the requested entry is not returned by the Directory Server then
-   * the request will fail with an {@link EntryNotFoundException}. More
+   * If the requested entry is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
    * specifically, this method will never return {@code null}.
    * <p>
    * This method is equivalent to the following code:
    *
    * <pre>
-   * SearchRequest request = new SearchRequest(name,
-   *     SearchScope.BASE_OBJECT, &quot;(objectClass=*)&quot;, attributeDescriptions);
+   * SearchRequest request = new SearchRequest(name, SearchScope.BASE_OBJECT,
+   *     &quot;(objectClass=*)&quot;, attributeDescriptions);
    * connection.searchSingleEntry(request);
    * </pre>
    *
    * @param name
    *          The distinguished name of the entry to be read.
    * @param attributeDescriptions
-   *          The names of the attributes to be included with the entry,
-   *          which may be {@code null} or empty indicating that all
-   *          user attributes should be returned.
+   *          The names of the attributes to be included with the entry, which
+   *          may be {@code null} or empty indicating that all user attributes
+   *          should be returned.
    * @return The single search result entry returned from the search.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If the {@code name} was {@code null}.
    */
@@ -774,15 +735,15 @@
   /**
    * Reads the named entry from the Directory Server.
    * <p>
-   * If the requested entry is not returned by the Directory Server then
-   * the request will fail with an {@link EntryNotFoundException}. More
+   * If the requested entry is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
    * specifically, this method will never return {@code null}.
    * <p>
    * This method is equivalent to the following code:
    *
    * <pre>
-   * SearchRequest request = new SearchRequest(name,
-   *     SearchScope.BASE_OBJECT, &quot;(objectClass=*)&quot;, attributeDescriptions);
+   * SearchRequest request = new SearchRequest(name, SearchScope.BASE_OBJECT,
+   *     &quot;(objectClass=*)&quot;, attributeDescriptions);
    * connection.searchSingleEntry(request);
    * </pre>
    *
@@ -792,112 +753,106 @@
    *          The names of the attributes to be included with the entry.
    * @return The single search result entry returned from the search.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code baseObject} could not be decoded using the
-   *           default schema.
+   *           If {@code baseObject} could not be decoded using the default
+   *           schema.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If the {@code name} was {@code null}.
    */
-  SearchResultEntry readEntry(String name,
-      String... attributeDescriptions) throws ErrorResultException,
-      InterruptedException, LocalizedIllegalArgumentException,
-      UnsupportedOperationException, IllegalStateException,
-      NullPointerException;
+  SearchResultEntry readEntry(String name, String... attributeDescriptions)
+      throws ErrorResultException, InterruptedException,
+      LocalizedIllegalArgumentException, UnsupportedOperationException,
+      IllegalStateException, NullPointerException;
 
 
 
   /**
    * Reads the Root DSE from the Directory Server.
    * <p>
-   * If the Root DSE is not returned by the Directory Server then the
-   * request will fail with an {@link EntryNotFoundException}. More
-   * specifically, this method will never return {@code null}.
+   * If the Root DSE is not returned by the Directory Server then the request
+   * will fail with an {@link EntryNotFoundException}. More specifically, this
+   * method will never return {@code null}.
    *
    * @return The Directory Server's Root DSE.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    */
-  RootDSE readRootDSE() throws ErrorResultException,
-      InterruptedException, UnsupportedOperationException,
-      IllegalStateException;
+  RootDSE readRootDSE() throws ErrorResultException, InterruptedException,
+      UnsupportedOperationException, IllegalStateException;
 
 
 
   /**
-   * Reads the schema from the Directory Server contained in the named
-   * subschema sub-entry.
+   * Reads the schema from the Directory Server contained in the named subschema
+   * sub-entry.
    * <p>
-   * If the requested schema is not returned by the Directory Server
-   * then the request will fail with an {@link EntryNotFoundException}.
-   * More specifically, this method will never return {@code null}.
+   * If the requested schema is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
+   * specifically, this method will never return {@code null}.
    * <p>
-   * Implementations may choose to perform optimizations such as
-   * caching.
+   * Implementations may choose to perform optimizations such as caching.
    *
    * @param name
    *          The distinguished name of the subschema sub-entry.
    * @return The schema from the Directory Server.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    */
-  Schema readSchema(DN name) throws ErrorResultException,
-      InterruptedException, UnsupportedOperationException,
-      IllegalStateException;
+  Schema readSchema(DN name) throws ErrorResultException, InterruptedException,
+      UnsupportedOperationException, IllegalStateException;
 
 
 
   /**
-   * Reads the schema from the Directory Server contained in the named
-   * subschema sub-entry.
+   * Reads the schema from the Directory Server contained in the named subschema
+   * sub-entry.
    * <p>
-   * If the requested schema is not returned by the Directory Server
-   * then the request will fail with an {@link EntryNotFoundException}.
-   * More specifically, this method will never return {@code null}.
+   * If the requested schema is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
+   * specifically, this method will never return {@code null}.
    * <p>
-   * Implementations may choose to perform optimizations such as
-   * caching.
+   * Implementations may choose to perform optimizations such as caching.
    *
    * @param name
    *          The distinguished name of the subschema sub-entry.
    * @return The schema from the Directory Server.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
+   *           If {@code name} could not be decoded using the default schema.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    */
   Schema readSchema(String name) throws ErrorResultException,
       InterruptedException, LocalizedIllegalArgumentException,
@@ -906,34 +861,32 @@
 
 
   /**
-   * Reads the schema from the Directory Server which applies to the
-   * named entry.
+   * Reads the schema from the Directory Server which applies to the named
+   * entry.
    * <p>
-   * If the requested entry or its associated schema are not returned by
-   * the Directory Server then the request will fail with an
-   * {@link EntryNotFoundException}. More specifically, this method will
-   * never return {@code null}.
+   * If the requested entry or its associated schema are not returned by the
+   * Directory Server then the request will fail with an
+   * {@link EntryNotFoundException}. More specifically, this method will never
+   * return {@code null}.
    * <p>
-   * A typical implementation will first read the {@code
-   * subschemaSubentry} attribute of the entry in order to locate the
-   * schema. However, implementations may choose to perform other
-   * optimizations, such as caching.
+   * A typical implementation will first read the {@code subschemaSubentry}
+   * attribute of the entry in order to locate the schema. However,
+   * implementations may choose to perform other optimizations, such as caching.
    *
    * @param name
-   *          The distinguished name of the entry whose schema is to be
-   *          located.
-   * @return The schema from the Directory Server which applies to the
-   *         named entry.
+   *          The distinguished name of the entry whose schema is to be located.
+   * @return The schema from the Directory Server which applies to the named
+   *         entry.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    */
   Schema readSchemaForEntry(DN name) throws ErrorResultException,
       InterruptedException, UnsupportedOperationException,
@@ -942,37 +895,34 @@
 
 
   /**
-   * Reads the schema from the Directory Server which applies to the
-   * named entry.
+   * Reads the schema from the Directory Server which applies to the named
+   * entry.
    * <p>
-   * If the requested entry or its associated schema are not returned by
-   * the Directory Server then the request will fail with an
-   * {@link EntryNotFoundException}. More specifically, this method will
-   * never return {@code null}.
+   * If the requested entry or its associated schema are not returned by the
+   * Directory Server then the request will fail with an
+   * {@link EntryNotFoundException}. More specifically, this method will never
+   * return {@code null}.
    * <p>
-   * A typical implementation will first read the {@code
-   * subschemaSubentry} attribute of the entry in order to locate the
-   * schema. However, implementations may choose to perform other
-   * optimizations, such as caching.
+   * A typical implementation will first read the {@code subschemaSubentry}
+   * attribute of the entry in order to locate the schema. However,
+   * implementations may choose to perform other optimizations, such as caching.
    *
    * @param name
-   *          The distinguished name of the entry whose schema is to be
-   *          located.
-   * @return The schema from the Directory Server which applies to the
-   *         named entry.
+   *          The distinguished name of the entry whose schema is to be located.
+   * @return The schema from the Directory Server which applies to the named
+   *         entry.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
+   *           If {@code name} could not be decoded using the default schema.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    */
   Schema readSchemaForEntry(String name) throws ErrorResultException,
       InterruptedException, LocalizedIllegalArgumentException,
@@ -981,17 +931,15 @@
 
 
   /**
-   * Reads the schema from the Directory Server which applies to the
-   * Root DSE.
+   * Reads the schema from the Directory Server which applies to the Root DSE.
    * <p>
-   * If the requested schema is not returned by the Directory Server
-   * then the request will fail with an {@link EntryNotFoundException}.
-   * More specifically, this method will never return {@code null}.
+   * If the requested schema is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
+   * specifically, this method will never return {@code null}.
    * <p>
-   * A typical implementation will first read the {@code
-   * subschemaSubentry} attribute of the Root DSE in order to locate the
-   * schema. However, implementations may choose to perform other
-   * optimizations, such as caching.
+   * A typical implementation will first read the {@code subschemaSubentry}
+   * attribute of the Root DSE in order to locate the schema. However,
+   * implementations may choose to perform other optimizations, such as caching.
    * <p>
    * This method is equivalent to the following code:
    *
@@ -999,18 +947,18 @@
    * connection.readSchemaForEntry(DN.rootDN());
    * </pre>
    *
-   * @return The schema from the Directory Server which applies to the
-   *         named entry.
+   * @return The schema from the Directory Server which applies to the named
+   *         entry.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    */
   Schema readSchemaForRootDSE() throws ErrorResultException,
       InterruptedException, UnsupportedOperationException,
@@ -1019,14 +967,14 @@
 
 
   /**
-   * Removes the provided connection event listener from this connection
-   * so that it will no longer be notified when this connection is
-   * closed by the application, receives an unsolicited notification, or
-   * experiences a fatal error.
+   * Removes the provided connection event listener from this connection so that
+   * it will no longer be notified when this connection is closed by the
+   * application, receives an unsolicited notification, or experiences a fatal
+   * error.
    *
    * @param listener
-   *          The listener which no longer wants to be notified when
-   *          events occur on this connection.
+   *          The listener which no longer wants to be notified when events
+   *          occur on this connection.
    * @throws NullPointerException
    *           If the {@code listener} was {@code null}.
    */
@@ -1036,15 +984,15 @@
 
 
   /**
-   * Searches the Directory Server using the provided search request.
-   * Any matching entries returned by the search will be added to
-   * {@code entries}, even if the final search result indicates that the
-   * search failed. Search result references will be discarded.
+   * Searches the Directory Server using the provided search request. Any
+   * matching entries returned by the search will be added to {@code entries},
+   * even if the final search result indicates that the search failed. Search
+   * result references will be discarded.
    * <p>
-   * <b>Warning:</b> Usage of this method is discouraged if the search
-   * request is expected to yield a large number of search results since
-   * the entire set of results will be stored in memory, potentially
-   * causing an {@code OutOfMemoryError}.
+   * <b>Warning:</b> Usage of this method is discouraged if the search request
+   * is expected to yield a large number of search results since the entire set
+   * of results will be stored in memory, potentially causing an {@code
+   * OutOfMemoryError}.
    * <p>
    * This method is equivalent to the following code:
    *
@@ -1058,15 +1006,15 @@
    *          The collection to which matching entries should be added.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} or {@code entries} was {@code null}.
    */
@@ -1079,35 +1027,35 @@
 
 
   /**
-   * Searches the Directory Server using the provided search request.
-   * Any matching entries returned by the search will be added to
-   * {@code entries}, even if the final search result indicates that the
-   * search failed. Similarly, search result references returned by the
-   * search will be added to {@code references}.
+   * Searches the Directory Server using the provided search request. Any
+   * matching entries returned by the search will be added to {@code entries},
+   * even if the final search result indicates that the search failed.
+   * Similarly, search result references returned by the search will be added to
+   * {@code references}.
    * <p>
-   * <b>Warning:</b> Usage of this method is discouraged if the search
-   * request is expected to yield a large number of search results since
-   * the entire set of results will be stored in memory, potentially
-   * causing an {@code OutOfMemoryError}.
+   * <b>Warning:</b> Usage of this method is discouraged if the search request
+   * is expected to yield a large number of search results since the entire set
+   * of results will be stored in memory, potentially causing an {@code
+   * OutOfMemoryError}.
    *
    * @param request
    *          The search request.
    * @param entries
    *          The collection to which matching entries should be added.
    * @param references
-   *          The collection to which search result references should be
-   *          added, or {@code null} if references are to be discarded.
+   *          The collection to which search result references should be added,
+   *          or {@code null} if references are to be discarded.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} or {@code entries} was {@code null}.
    */
@@ -1121,28 +1069,27 @@
 
 
   /**
-   * Searches the Directory Server using the provided search request.
-   * Any matching entries returned by the search as well as any search
-   * result references will be passed to the provided search result
-   * handler.
+   * Searches the Directory Server using the provided search request. Any
+   * matching entries returned by the search as well as any search result
+   * references will be passed to the provided search result handler.
    *
    * @param request
    *          The search request.
    * @param handler
-   *          A search result handler which can be used to process the
-   *          search result entries and references as they are received,
-   *          may be {@code null}.
+   *          A search result handler which can be used to process the search
+   *          result entries and references as they are received, may be {@code
+   *          null}.
    * @return The result of the operation.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If {@code request} was {@code null}.
    */
@@ -1154,15 +1101,15 @@
 
 
   /**
-   * Searches the Directory Server using the provided search parameters.
-   * Any matching entries returned by the search will be added to a
-   * {@code List} which is returned if the search succeeds. Search
-   * result references will be discarded.
+   * Searches the Directory Server using the provided search parameters. Any
+   * matching entries returned by the search will be added to a {@code List}
+   * which is returned if the search succeeds. Search result references will be
+   * discarded.
    * <p>
-   * <b>Warning:</b> Usage of this method is discouraged if the search
-   * request is expected to yield a large number of search results since
-   * the entire set of results will be stored in memory, potentially
-   * causing an {@code OutOfMemoryError}.
+   * <b>Warning:</b> Usage of this method is discouraged if the search request
+   * is expected to yield a large number of search results since the entire set
+   * of results will be stored in memory, potentially causing an {@code
+   * OutOfMemoryError}.
    * <p>
    * This method is equivalent to the following code:
    *
@@ -1173,35 +1120,33 @@
    * </pre>
    *
    * @param baseObject
-   *          The distinguished name of the base entry relative to which
-   *          the search is to be performed.
+   *          The distinguished name of the base entry relative to which the
+   *          search is to be performed.
    * @param scope
    *          The scope of the search.
    * @param filter
-   *          The filter that defines the conditions that must be
-   *          fulfilled in order for an entry to be returned.
+   *          The filter that defines the conditions that must be fulfilled in
+   *          order for an entry to be returned.
    * @param attributeDescriptions
-   *          The names of the attributes to be included with each
-   *          entry.
-   * @return A list containing any matching entries returned by the
-   *         search.
+   *          The names of the attributes to be included with each entry.
+   * @return A list containing any matching entries returned by the search.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code baseObject} could not be decoded using the
-   *           default schema or if {@code filter} is not a valid LDAP
-   *           string representation of a filter.
+   *           If {@code baseObject} could not be decoded using the default
+   *           schema or if {@code filter} is not a valid LDAP string
+   *           representation of a filter.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
-   *           If the {@code baseObject}, {@code scope}, or {@code
-   *           filter} were {@code null}.
+   *           If the {@code baseObject}, {@code scope}, or {@code filter} were
+   *           {@code null}.
    */
   List<SearchResultEntry> search(String baseObject, SearchScope scope,
       String filter, String... attributeDescriptions)
@@ -1212,28 +1157,28 @@
 
 
   /**
-   * Searches the Directory Server for a single entry using the provided
-   * search request.
+   * Searches the Directory Server for a single entry using the provided search
+   * request.
    * <p>
-   * If the requested entry is not returned by the Directory Server then
-   * the request will fail with an {@link EntryNotFoundException}. More
-   * specifically, this method will never return {@code null}. If
-   * multiple matching entries are returned by the Directory Server then
-   * the request will fail with an {@link MultipleEntriesFoundException}.
+   * If the requested entry is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
+   * specifically, this method will never return {@code null}. If multiple
+   * matching entries are returned by the Directory Server then the request will
+   * fail with an {@link MultipleEntriesFoundException}.
    *
    * @param request
    *          The search request.
    * @return The single search result entry returned from the search.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If the {@code request} was {@code null}.
    */
@@ -1245,14 +1190,14 @@
 
 
   /**
-   * Searches the Directory Server for a single entry using the provided
-   * search parameters.
+   * Searches the Directory Server for a single entry using the provided search
+   * parameters.
    * <p>
-   * If the requested entry is not returned by the Directory Server then
-   * the request will fail with an {@link EntryNotFoundException}. More
-   * specifically, this method will never return {@code null}. If
-   * multiple matching entries are returned by the Directory Server then
-   * the request will fail with an {@link MultipleEntriesFoundException}.
+   * If the requested entry is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
+   * specifically, this method will never return {@code null}. If multiple
+   * matching entries are returned by the Directory Server then the request will
+   * fail with an {@link MultipleEntriesFoundException}.
    * <p>
    * This method is equivalent to the following code:
    *
@@ -1263,37 +1208,36 @@
    * </pre>
    *
    * @param baseObject
-   *          The distinguished name of the base entry relative to which
-   *          the search is to be performed.
+   *          The distinguished name of the base entry relative to which the
+   *          search is to be performed.
    * @param scope
    *          The scope of the search.
    * @param filter
-   *          The filter that defines the conditions that must be
-   *          fulfilled in order for an entry to be returned.
+   *          The filter that defines the conditions that must be fulfilled in
+   *          order for an entry to be returned.
    * @param attributeDescriptions
-   *          The names of the attributes to be included with each
-   *          entry.
+   *          The names of the attributes to be included with each entry.
    * @return The single search result entry returned from the search.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code baseObject} could not be decoded using the
-   *           default schema or if {@code filter} is not a valid LDAP
-   *           string representation of a filter.
+   *           If {@code baseObject} could not be decoded using the default
+   *           schema or if {@code filter} is not a valid LDAP string
+   *           representation of a filter.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
-   *           If the {@code baseObject}, {@code scope}, or {@code
-   *           filter} were {@code null}.
+   *           If the {@code baseObject}, {@code scope}, or {@code filter} were
+   *           {@code null}.
    */
-  SearchResultEntry searchSingleEntry(String baseObject,
-      SearchScope scope, String filter, String... attributeDescriptions)
+  SearchResultEntry searchSingleEntry(String baseObject, SearchScope scope,
+      String filter, String... attributeDescriptions)
       throws ErrorResultException, InterruptedException,
       LocalizedIllegalArgumentException, UnsupportedOperationException,
       IllegalStateException, NullPointerException;
diff --git a/sdk/src/org/opends/sdk/ConnectionEventListener.java b/sdk/src/org/opends/sdk/ConnectionEventListener.java
index d17475e..6225618 100644
--- a/sdk/src/org/opends/sdk/ConnectionEventListener.java
+++ b/sdk/src/org/opends/sdk/ConnectionEventListener.java
@@ -31,79 +31,69 @@
 
 import java.util.EventListener;
 
-import org.opends.sdk.responses.GenericExtendedResult;
+import org.opends.sdk.responses.ExtendedResult;
 
 
 
 /**
- * An object that registers to be notified when a connection is closed
- * by the application, receives an unsolicited notification, or
- * experiences a fatal error.
+ * An object that registers to be notified when a connection is closed by the
+ * application, receives an unsolicited notification, or experiences a fatal
+ * error.
  * <p>
- * TODO: isolate fatal connection errors as a sub-type of
- * ErrorResultException.
+ * TODO: isolate fatal connection errors as a sub-type of ErrorResultException.
  * <p>
- * TODO: do we need client initiated close notification as in JCA /
- * JDBC? A simpler approach would be for the connection pool to wrap the
- * underlying physical connection with its own. It can then intercept
- * the close request from the client. This has the disadvantage in that
- * we lose any specialized methods exposed by the underlying physical
- * connection (i.e. if the physical connection extends Connection and
- * provides additional methods) since the connection pool effectively
- * hides them via its wrapper.
+ * TODO: do we need client initiated close notification as in JCA / JDBC? A
+ * simpler approach would be for the connection pool to wrap the underlying
+ * physical connection with its own. It can then intercept the close request
+ * from the client. This has the disadvantage in that we lose any specialized
+ * methods exposed by the underlying physical connection (i.e. if the physical
+ * connection extends Connection and provides additional methods) since the
+ * connection pool effectively hides them via its wrapper.
  */
 public interface ConnectionEventListener extends EventListener
 {
-  // /**
-  // * Notifies this connection event listener that the application has
-  // * called {@link Connection#close} on the connection. The connection
-  // * event listener will be notified immediately after the application
-  // * calls the {@link Connection#close} method on the associated
-  // * connection.
-  // *
-  // * @param connection
-  // * The connection that has just been closed by the
-  // * application.
-  // */
-  // void connectionClosed(Connection connection);
-
   /**
-   * Notifies this connection event listener that the connection has
-   * just received the provided unsolicited notification from the
-   * server.
-   * <p>
-   * <b>Note:</b> disconnect notifications are treated as fatal
-   * connection errors and are handled by the
-   * {@link #connectionErrorOccurred} method.
-   *
-   * @param notification
-   *          The unsolicited notification
+   * Notifies this connection event listener that the application has called
+   * {@code close} on the connection. The connection event listener will be
+   * notified immediately after the application calls the {@code close} method
+   * on the associated connection.
    */
-  void connectionReceivedUnsolicitedNotification(
-      GenericExtendedResult notification);
+  void connectionClosed();
 
 
 
   /**
-   * Notifies this connection event listener that a fatal error has
-   * occurred and the connection can no longer be used - the server has
-   * crashed, for example. The connection implementation makes this
-   * notification just before it throws the provided
-   * {@link ErrorResultException} to the application.
+   * Notifies this connection event listener that a fatal error has occurred and
+   * the connection can no longer be used - the server has crashed, for example.
+   * The connection implementation makes this notification just before it throws
+   * the provided {@link ErrorResultException} to the application.
    * <p>
-   * <b>Note:</b> disconnect notifications are treated as fatal
-   * connection errors and are handled by this method. In this case
-   * {@code isDisconnectNotification} will be {@code true} and {@code
-   * error} will contain the result code and any diagnostic information
-   * contained in the notification message.
+   * <b>Note:</b> disconnect notifications are treated as fatal connection
+   * errors and are handled by this method. In this case {@code
+   * isDisconnectNotification} will be {@code true} and {@code error} will
+   * contain the result code and any diagnostic information contained in the
+   * notification message.
    *
    * @param isDisconnectNotification
    *          {@code true} if the error was triggered by a disconnect
    *          notification sent by the server, otherwise {@code false}.
    * @param error
-   *          The exception that is about to be thrown to the
-   *          application.
+   *          The exception that is about to be thrown to the application.
    */
   void connectionErrorOccurred(boolean isDisconnectNotification,
       ErrorResultException error);
+
+
+
+  /**
+   * Notifies this connection event listener that the connection has just
+   * received the provided unsolicited notification from the server.
+   * <p>
+   * <b>Note:</b> disconnect notifications are treated as fatal connection
+   * errors and are handled by the {@link #connectionErrorOccurred} method.
+   *
+   * @param notification
+   *          The unsolicited notification
+   */
+  void connectionReceivedUnsolicitedNotification(ExtendedResult notification);
 }
diff --git a/sdk/src/org/opends/sdk/ConnectionException.java b/sdk/src/org/opends/sdk/ConnectionException.java
index 8f7e5d9..839f2fc 100644
--- a/sdk/src/org/opends/sdk/ConnectionException.java
+++ b/sdk/src/org/opends/sdk/ConnectionException.java
@@ -34,13 +34,13 @@
 
 
 /**
- * Thrown when the result code returned in a Result indicates that the
- * Request was unsuccessful because of a connection failure.
+ * Thrown when the result code returned in a Result indicates that the Request
+ * was unsuccessful because of a connection failure.
  */
 @SuppressWarnings("serial")
 public class ConnectionException extends ErrorResultException
 {
-  ConnectionException(Result result)
+  ConnectionException(final Result result)
   {
     super(result);
   }
diff --git a/sdk/src/org/opends/sdk/ConnectionFactory.java b/sdk/src/org/opends/sdk/ConnectionFactory.java
index 82f70cc..1737262 100644
--- a/sdk/src/org/opends/sdk/ConnectionFactory.java
+++ b/sdk/src/org/opends/sdk/ConnectionFactory.java
@@ -27,11 +27,13 @@
 
 package org.opends.sdk;
 
+
+
 /**
- * A connection factory provides an interface for obtaining a connection
- * to a Directory Server. Connection factories can be used to wrap other
- * connection factories in order to provide enhanced capabilities in a
- * manner which is transparent to the application. For example:
+ * A connection factory provides an interface for obtaining a connection to a
+ * Directory Server. Connection factories can be used to wrap other connection
+ * factories in order to provide enhanced capabilities in a manner which is
+ * transparent to the application. For example:
  * <ul>
  * <li>Connection pooling
  * <li>Load balancing
@@ -44,42 +46,41 @@
  * <li>Pre-authenticated connections
  * <li>Recording connections, with primitive roll-back functionality
  * </ul>
- * An application typically obtains a connection from a connection
- * factory, performs one or more operations, and then closes the
- * connection. Applications should aim to close connections as soon as
- * possible in order to avoid resource contention.
- *
+ * An application typically obtains a connection from a connection factory,
+ * performs one or more operations, and then closes the connection. Applications
+ * should aim to close connections as soon as possible in order to avoid
+ * resource contention.
  */
 public interface ConnectionFactory
 {
   /**
+   * Initiates an asynchronous connection request to the Directory Server
+   * associated with this connection factory. The returned {@code FutureResult}
+   * can be used to retrieve the completed asynchronous connection.
+   * Alternatively, if a {@code ResultHandler} is provided, the handler will be
+   * notified when the connection is available and ready for use.
+   *
+   * @param handler
+   *          The completion handler, or {@code null} if no handler is to be
+   *          used.
+   * @return A future which can be used to retrieve the asynchronous connection.
+   */
+  FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      ResultHandler<AsynchronousConnection> handler);
+
+
+
+  /**
    * Returns a connection to the Directory Server associated with this
-   * connection factory. The connection returned by this method can be
-   * used immediately.
+   * connection factory. The connection returned by this method can be used
+   * immediately.
    *
    * @return A connection to the Directory Server associated with this
    *         connection factory.
    * @throws ErrorResultException
    *           If the connection request failed for some reason.
+   * @throws InterruptedException
+   *           If the current thread was interrupted while waiting.
    */
-  Connection getConnection() throws ErrorResultException;
-
-
-
-  /**
-   * Initiates an asynchronous connection request to the Directory
-   * Server associated with this connection factory. The returned
-   * {@code FutureResult} can be used to retrieve the completed
-   * asynchronous connection. Alternatively, if a {@code ResultHandler}
-   * is provided, the handler will be notified when the connection is
-   * available and ready for use.
-   *
-   * @param handler
-   *          The completion handler, or {@code null} if no handler is
-   *          to be used.
-   * @return A future which can be used to retrieve the asynchronous
-   *         connection.
-   */
-  FutureResult<AsynchronousConnection> getAsynchronousConnection(
-      ResultHandler<AsynchronousConnection> handler);
+  Connection getConnection() throws ErrorResultException, InterruptedException;
 }
diff --git a/sdk/src/org/opends/sdk/ConnectionPool.java b/sdk/src/org/opends/sdk/ConnectionPool.java
index d0b8780..de641ce 100644
--- a/sdk/src/org/opends/sdk/ConnectionPool.java
+++ b/sdk/src/org/opends/sdk/ConnectionPool.java
@@ -49,21 +49,32 @@
  */
 final class ConnectionPool extends AbstractConnectionFactory
 {
-  private final ConnectionFactory connectionFactory;
-
-  private volatile int numConnections;
-
-  private final int poolSize;
-
-  // FIXME: should use a better collection than this - CLQ?
-  private final Queue<AsynchronousConnection> pool;
-
-  private final ConcurrentLinkedQueue<FuturePooledConnection> pendingFutures;
+  // Future used for waiting for pooled connections to become available.
+  private static final class FuturePooledConnection extends
+      AbstractFutureResult<AsynchronousConnection>
+  {
+    private FuturePooledConnection(
+        final ResultHandler<? super AsynchronousConnection> handler)
+    {
+      super(handler);
+    }
 
 
 
-  private final class PooledConnectionWapper implements
-      AsynchronousConnection, ConnectionEventListener
+    /**
+     * {@inheritDoc}
+     */
+    public int getRequestID()
+    {
+      return -1;
+    }
+
+  }
+
+
+
+  private final class PooledConnectionWapper implements AsynchronousConnection,
+      ConnectionEventListener
   {
     private final AsynchronousConnection connection;
 
@@ -71,7 +82,7 @@
 
 
 
-    private PooledConnectionWapper(AsynchronousConnection connection)
+    private PooledConnectionWapper(final AsynchronousConnection connection)
     {
       this.connection = connection;
       this.connection.addConnectionEventListener(this);
@@ -79,7 +90,7 @@
 
 
 
-    public void abandon(AbandonRequest request)
+    public FutureResult<Void> abandon(final AbandonRequest request)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -87,13 +98,13 @@
       {
         throw new IllegalStateException();
       }
-      connection.abandon(request);
+      return connection.abandon(request);
     }
 
 
 
-    public FutureResult<Result> add(AddRequest request,
-        ResultHandler<Result> handler)
+    public FutureResult<Result> add(final AddRequest request,
+        final ResultHandler<Result> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -106,8 +117,36 @@
 
 
 
-    public FutureResult<BindResult> bind(BindRequest request,
-        ResultHandler<? super BindResult> handler)
+    public FutureResult<Result> add(final AddRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection
+          .add(request, resultHandler, intermediateResponseHandler);
+    }
+
+
+
+    public void addConnectionEventListener(
+        final ConnectionEventListener listener) throws IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+    }
+
+
+
+    public FutureResult<BindResult> bind(final BindRequest request,
+        final ResultHandler<? super BindResult> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -120,6 +159,22 @@
 
 
 
+    public FutureResult<BindResult> bind(final BindRequest request,
+        final ResultHandler<? super BindResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.bind(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
     public void close()
     {
       synchronized (pool)
@@ -145,26 +200,23 @@
       {
         StaticUtils.DEBUG_LOG.warning(String.format(
             "Dead connection released and closed. "
-                + "numConnections: %d, poolSize: %d, "
-                + "pendingFutures: %d", numConnections, pool.size(),
-            pendingFutures.size()));
+                + "numConnections: %d, poolSize: %d, " + "pendingFutures: %d",
+            numConnections, pool.size(), pendingFutures.size()));
       }
 
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
       {
         StaticUtils.DEBUG_LOG.warning(String.format(
             "Reconnect attempt starting. "
-                + "numConnections: %d, poolSize: %d, "
-                + "pendingFutures: %d", numConnections, pool.size(),
-            pendingFutures.size()));
+                + "numConnections: %d, poolSize: %d, " + "pendingFutures: %d",
+            numConnections, pool.size(), pendingFutures.size()));
       }
-      connectionFactory
-          .getAsynchronousConnection(new ReconnectHandler());
+      connectionFactory.getAsynchronousConnection(new ReconnectHandler());
     }
 
 
 
-    public void close(UnbindRequest request, String reason)
+    public void close(final UnbindRequest request, final String reason)
         throws NullPointerException
     {
       close();
@@ -172,8 +224,8 @@
 
 
 
-    public FutureResult<CompareResult> compare(CompareRequest request,
-        ResultHandler<? super CompareResult> handler)
+    public FutureResult<CompareResult> compare(final CompareRequest request,
+        final ResultHandler<? super CompareResult> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -186,8 +238,67 @@
 
 
 
-    public FutureResult<Result> delete(DeleteRequest request,
-        ResultHandler<Result> handler)
+    public FutureResult<CompareResult> compare(final CompareRequest request,
+        final ResultHandler<? super CompareResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.compare(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public void connectionClosed()
+    {
+      // Ignore - we intercept close via the close method.
+    }
+
+
+
+    public void connectionErrorOccurred(final boolean isDisconnectNotification,
+        final ErrorResultException error)
+    {
+      // Remove this connection from the pool if its in there. If not,
+      // just ignore and wait for the user to close and we can deal with it
+      // there.
+      if (pool.remove(this))
+      {
+        numConnections--;
+        connection.removeConnectionEventListener(this);
+
+        // FIXME: should still close the connection, but we need to be
+        // careful that users of the pooled connection get a sensible
+        // error if they continue to use it (i.e. not an NPE or ISE).
+
+        if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
+        {
+          StaticUtils.DEBUG_LOG.warning(String.format(
+              "Connection error occured and removed from pool: "
+                  + error.getMessage()
+                  + " numConnections: %d, poolSize: %d, pendingFutures: %d",
+              numConnections, pool.size(), pendingFutures.size()));
+        }
+      }
+    }
+
+
+
+    public void connectionReceivedUnsolicitedNotification(
+        final ExtendedResult notification)
+    {
+      // Ignore
+    }
+
+
+
+    public FutureResult<Result> delete(final DeleteRequest request,
+        final ResultHandler<Result> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -200,8 +311,24 @@
 
 
 
-    public <R extends Result> FutureResult<R> extendedRequest(
-        ExtendedRequest<R> request, ResultHandler<? super R> handler)
+    public FutureResult<Result> delete(final DeleteRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.delete(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+        final ExtendedRequest<R> request, final ResultHandler<? super R> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -214,8 +341,10 @@
 
 
 
-    public FutureResult<Result> modify(ModifyRequest request,
-        ResultHandler<Result> handler)
+    public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+        final ExtendedRequest<R> request,
+        final ResultHandler<? super R> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -223,37 +352,8 @@
       {
         throw new IllegalStateException();
       }
-      return connection.modify(request, handler);
-    }
-
-
-
-    public FutureResult<Result> modifyDN(ModifyDNRequest request,
-        ResultHandler<Result> handler)
-        throws UnsupportedOperationException, IllegalStateException,
-        NullPointerException
-    {
-      if (isClosed())
-      {
-        throw new IllegalStateException();
-      }
-      return connection.modifyDN(request, handler);
-    }
-
-
-
-    public FutureResult<Result> search(SearchRequest request,
-        ResultHandler<Result> resultHandler,
-        SearchResultHandler searchResulthandler)
-        throws UnsupportedOperationException, IllegalStateException,
-        NullPointerException
-    {
-      if (isClosed())
-      {
-        throw new IllegalStateException();
-      }
-      return connection.search(request, resultHandler,
-          searchResulthandler);
+      return connection.extendedRequest(request, resultHandler,
+          intermediateResponseHandler);
     }
 
 
@@ -261,107 +361,9 @@
     /**
      * {@inheritDoc}
      */
-    public FutureResult<SearchResultEntry> readEntry(DN name,
-        Collection<String> attributeDescriptions,
-        ResultHandler<? super SearchResultEntry> resultHandler)
-        throws UnsupportedOperationException, IllegalStateException,
-        NullPointerException
+    public Connection getSynchronousConnection()
     {
-      if (isClosed())
-      {
-        throw new IllegalStateException();
-      }
-      return connection.readEntry(name, attributeDescriptions,
-          resultHandler);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<SearchResultEntry> searchSingleEntry(
-        SearchRequest request,
-        ResultHandler<? super SearchResultEntry> resultHandler)
-        throws UnsupportedOperationException, IllegalStateException,
-        NullPointerException
-    {
-      if (isClosed())
-      {
-        throw new IllegalStateException();
-      }
-      return connection.searchSingleEntry(request, resultHandler);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<RootDSE> readRootDSE(
-        ResultHandler<RootDSE> handler)
-        throws UnsupportedOperationException, IllegalStateException
-    {
-      if (isClosed())
-      {
-        throw new IllegalStateException();
-      }
-      return connection.readRootDSE(handler);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<Schema> readSchemaForEntry(DN name,
-        ResultHandler<Schema> handler)
-        throws UnsupportedOperationException, IllegalStateException
-    {
-      if (isClosed())
-      {
-        throw new IllegalStateException();
-      }
-      return connection.readSchemaForEntry(name, handler);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<Schema> readSchema(DN name,
-        ResultHandler<Schema> handler)
-        throws UnsupportedOperationException, IllegalStateException
-    {
-      if (isClosed())
-      {
-        throw new IllegalStateException();
-      }
-      return connection.readSchema(name, handler);
-    }
-
-
-
-    public void addConnectionEventListener(
-        ConnectionEventListener listener) throws IllegalStateException,
-        NullPointerException
-    {
-      if (isClosed())
-      {
-        throw new IllegalStateException();
-      }
-    }
-
-
-
-    public void removeConnectionEventListener(
-        ConnectionEventListener listener) throws NullPointerException
-    {
-      if (isClosed())
-      {
-        throw new IllegalStateException();
-      }
+      return new SynchronousConnection(this);
     }
 
 
@@ -383,42 +385,189 @@
 
 
 
-    public void connectionReceivedUnsolicitedNotification(
-        GenericExtendedResult notification)
+    public FutureResult<Result> modify(final ModifyRequest request,
+        final ResultHandler<Result> handler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
     {
-      // Ignore
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.modify(request, handler);
     }
 
 
 
-    public void connectionErrorOccurred(
-        boolean isDisconnectNotification, ErrorResultException error)
+    public FutureResult<Result> modify(final ModifyRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
     {
-      // Remove this connection from the pool if its in there. If not,
-      // just
-      // ignore and wait for the user to close and we can deal with it
-      // there.
-      if (pool.remove(this))
+      if (isClosed())
       {
-        numConnections--;
-        connection.removeConnectionEventListener(this);
-
-        // FIXME: should still close the connection, but we need to be
-        // careful that users of the pooled connection get a sensible
-        // error if they continue to use it (i.e. not an NPE or ISE).
-
-        if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
-        {
-          StaticUtils.DEBUG_LOG
-              .warning(String
-                  .format(
-                      "Connection error occured and removed from pool: "
-                          + error.getMessage()
-                          + " numConnections: %d, poolSize: %d, pendingFutures: %d",
-                      numConnections, pool.size(), pendingFutures
-                          .size()));
-        }
+        throw new IllegalStateException();
       }
+      return connection.modify(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+        final ResultHandler<Result> handler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.modifyDN(request, handler);
+    }
+
+
+
+    public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.modifyDN(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<SearchResultEntry> readEntry(final DN name,
+        final Collection<String> attributeDescriptions,
+        final ResultHandler<? super SearchResultEntry> resultHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.readEntry(name, attributeDescriptions, resultHandler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<RootDSE> readRootDSE(
+        final ResultHandler<RootDSE> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.readRootDSE(handler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<Schema> readSchema(final DN name,
+        final ResultHandler<Schema> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.readSchema(name, handler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<Schema> readSchemaForEntry(final DN name,
+        final ResultHandler<Schema> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.readSchemaForEntry(name, handler);
+    }
+
+
+
+    public void removeConnectionEventListener(
+        final ConnectionEventListener listener) throws NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+    }
+
+
+
+    public FutureResult<Result> search(final SearchRequest request,
+        final ResultHandler<Result> resultHandler,
+        final SearchResultHandler searchResulthandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.search(request, resultHandler, searchResulthandler);
+    }
+
+
+
+    public FutureResult<Result> search(final SearchRequest request,
+        final ResultHandler<Result> resultHandler,
+        final SearchResultHandler searchResulthandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.search(request, resultHandler, searchResulthandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<SearchResultEntry> searchSingleEntry(
+        final SearchRequest request,
+        final ResultHandler<? super SearchResultEntry> resultHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      if (isClosed())
+      {
+        throw new IllegalStateException();
+      }
+      return connection.searchSingleEntry(request, resultHandler);
     }
   }
 
@@ -427,7 +576,7 @@
   private class ReconnectHandler implements
       ResultHandler<AsynchronousConnection>
   {
-    public void handleErrorResult(ErrorResultException error)
+    public void handleErrorResult(final ErrorResultException error)
     {
       // The reconnect failed. Fail the connect attempt.
       numConnections--;
@@ -443,29 +592,24 @@
       }
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
       {
-        StaticUtils.DEBUG_LOG
-            .warning(String
-                .format(
-                    "Reconnect failed. Failed all pending futures: "
-                        + error.getMessage()
-                        + " numConnections: %d, poolSize: %d, pendingFutures: %d",
-                    numConnections, pool.size(), pendingFutures.size()));
+        StaticUtils.DEBUG_LOG.warning(String.format(
+            "Reconnect failed. Failed all pending futures: "
+                + error.getMessage()
+                + " numConnections: %d, poolSize: %d, pendingFutures: %d",
+            numConnections, pool.size(), pendingFutures.size()));
       }
 
     }
 
 
 
-    public void handleResult(AsynchronousConnection connection)
+    public void handleResult(final AsynchronousConnection connection)
     {
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
       {
-        StaticUtils.DEBUG_LOG
-            .finest(String
-                .format(
-                    "Reconnect succeded. "
-                        + " numConnections: %d, poolSize: %d, pendingFutures: %d",
-                    numConnections, pool.size(), pendingFutures.size()));
+        StaticUtils.DEBUG_LOG.finest(String.format("Reconnect succeeded. "
+            + " numConnections: %d, poolSize: %d, pendingFutures: %d",
+            numConnections, pool.size(), pendingFutures.size()));
       }
       synchronized (pool)
       {
@@ -476,75 +620,16 @@
 
 
 
-  // Future used for waiting for pooled connections to become available.
-  private static final class FuturePooledConnection extends
-      AbstractFutureResult<AsynchronousConnection>
-  {
-    private FuturePooledConnection(
-        ResultHandler<? super AsynchronousConnection> handler)
-    {
-      super(handler);
-    }
+  private final ConnectionFactory connectionFactory;
 
+  private volatile int numConnections;
 
+  private final int poolSize;
 
-    /**
-     * {@inheritDoc}
-     */
-    public int getRequestID()
-    {
-      return -1;
-    }
+  // FIXME: should use a better collection than this - CLQ?
+  private final Queue<AsynchronousConnection> pool;
 
-  }
-
-
-
-  private void releaseConnection(AsynchronousConnection connection)
-  {
-    // See if there waiters pending.
-    for (;;)
-    {
-      PooledConnectionWapper pooledConnection = new PooledConnectionWapper(
-          connection);
-      FuturePooledConnection future = pendingFutures.poll();
-
-      if (future == null)
-      {
-        // No waiters - so drop out and add connection to pool.
-        break;
-      }
-
-      future.handleResult(pooledConnection);
-
-      if (!future.isCancelled())
-      {
-        // The future was not cancelled and the connection was
-        // accepted.
-        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
-        {
-          StaticUtils.DEBUG_LOG
-              .finest(String
-                  .format(
-                      "Connection released and directly "
-                          + "given to waiter. numConnections: %d, poolSize: %d, "
-                          + "pendingFutures: %d", numConnections, pool
-                          .size(), pendingFutures.size()));
-        }
-        return;
-      }
-    }
-
-    // No waiters. Put back in pool.
-    pool.offer(connection);
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
-    {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "Connection released to pool. numConnections: %d, "
-              + "poolSize: %d, pendingFutures: %d", numConnections,
-          pool.size(), pendingFutures.size()));
-    }
-  }
+  private final ConcurrentLinkedQueue<FuturePooledConnection> pendingFutures;
 
 
 
@@ -553,12 +638,11 @@
    * connections created using the provided connection factory.
    *
    * @param connectionFactory
-   *          The connection factory to use for creating new
-   *          connections.
+   *          The connection factory to use for creating new connections.
    * @param poolSize
    *          The maximum size of the connection pool.
    */
-  ConnectionPool(ConnectionFactory connectionFactory, int poolSize)
+  ConnectionPool(final ConnectionFactory connectionFactory, final int poolSize)
   {
     this.connectionFactory = connectionFactory;
     this.poolSize = poolSize;
@@ -568,12 +652,12 @@
 
 
 
+  @Override
   public synchronized FutureResult<AsynchronousConnection> getAsynchronousConnection(
-      ResultHandler<AsynchronousConnection> handler)
+      final ResultHandler<AsynchronousConnection> handler)
   {
     // This entire method is synchronized to ensure new connects are
-    // done
-    // synchronously to avoid the "pending connect" case.
+    // done synchronously to avoid the "pending connect" case.
     AsynchronousConnection conn;
     synchronized (pool)
     {
@@ -587,19 +671,16 @@
         {
           // We reached max # of conns so wait for a connection to
           // become available.
-          FuturePooledConnection future = new FuturePooledConnection(
+          final FuturePooledConnection future = new FuturePooledConnection(
               handler);
           pendingFutures.add(future);
 
           if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
           {
-            StaticUtils.DEBUG_LOG
-                .finest(String
-                    .format(
-                        "No connections available. Wait-listed"
-                            + "numConnections: %d, poolSize: %d, pendingFutures: %d",
-                        numConnections, pool.size(), pendingFutures
-                            .size()));
+            StaticUtils.DEBUG_LOG.finest(String.format(
+                "No connections available. Wait-listed"
+                    + "numConnections: %d, poolSize: %d, pendingFutures: %d",
+                numConnections, pool.size(), pendingFutures.size()));
           }
 
           return future;
@@ -616,16 +697,13 @@
         numConnections++;
         if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
         {
-          StaticUtils.DEBUG_LOG
-              .finest(String
-                  .format(
-                      "New connection established and aquired. "
-                          + "numConnections: %d, poolSize: %d, pendingFutures: %d",
-                      numConnections, pool.size(), pendingFutures
-                          .size()));
+          StaticUtils.DEBUG_LOG.finest(String.format(
+              "New connection established and aquired. "
+                  + "numConnections: %d, poolSize: %d, pendingFutures: %d",
+              numConnections, pool.size(), pendingFutures.size()));
         }
       }
-      catch (ErrorResultException e)
+      catch (final ErrorResultException e)
       {
         if (handler != null)
         {
@@ -633,9 +711,9 @@
         }
         return new CompletedFutureResult<AsynchronousConnection>(e);
       }
-      catch (InterruptedException e)
+      catch (final InterruptedException e)
       {
-        ErrorResultException error = new ErrorResultException(Responses
+        final ErrorResultException error = new ErrorResultException(Responses
             .newResult(ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
         if (handler != null)
         {
@@ -648,23 +726,66 @@
     {
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
       {
-        StaticUtils.DEBUG_LOG
-            .finest(String
-                .format(
-                    "Connection aquired from pool. "
-                        + "numConnections: %d, poolSize: %d, pendingFutures: %d",
-                    numConnections, pool.size(), pendingFutures.size()));
+        StaticUtils.DEBUG_LOG.finest(String.format(
+            "Connection aquired from pool. "
+                + "numConnections: %d, poolSize: %d, pendingFutures: %d",
+            numConnections, pool.size(), pendingFutures.size()));
       }
     }
 
-    PooledConnectionWapper pooledConnection = new PooledConnectionWapper(
+    final PooledConnectionWapper pooledConnection = new PooledConnectionWapper(
         conn);
     if (handler != null)
     {
       handler.handleResult(pooledConnection);
     }
-    return new CompletedFutureResult<AsynchronousConnection>(
-        pooledConnection);
+    return new CompletedFutureResult<AsynchronousConnection>(pooledConnection);
 
   }
+
+
+
+  private void releaseConnection(final AsynchronousConnection connection)
+  {
+    // See if there waiters pending.
+    for (;;)
+    {
+      final PooledConnectionWapper pooledConnection = new PooledConnectionWapper(
+          connection);
+      final FuturePooledConnection future = pendingFutures.poll();
+
+      if (future == null)
+      {
+        // No waiters - so drop out and add connection to pool.
+        break;
+      }
+
+      future.handleResult(pooledConnection);
+
+      if (!future.isCancelled())
+      {
+        // The future was not cancelled and the connection was
+        // accepted.
+        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
+        {
+          StaticUtils.DEBUG_LOG.finest(String.format(
+              "Connection released and directly "
+                  + "given to waiter. numConnections: %d, poolSize: %d, "
+                  + "pendingFutures: %d", numConnections, pool.size(),
+              pendingFutures.size()));
+        }
+        return;
+      }
+    }
+
+    // No waiters. Put back in pool.
+    pool.offer(connection);
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
+    {
+      StaticUtils.DEBUG_LOG.finest(String.format(
+          "Connection released to pool. numConnections: %d, "
+              + "poolSize: %d, pendingFutures: %d", numConnections,
+          pool.size(), pendingFutures.size()));
+    }
+  }
 }
diff --git a/sdk/src/org/opends/sdk/ConnectionSecurityLayer.java b/sdk/src/org/opends/sdk/ConnectionSecurityLayer.java
new file mode 100644
index 0000000..2066c06
--- /dev/null
+++ b/sdk/src/org/opends/sdk/ConnectionSecurityLayer.java
@@ -0,0 +1,83 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+/**
+ * An interface for providing additional connection security to a connection.
+ */
+public interface ConnectionSecurityLayer
+{
+
+  /**
+   * Disposes of any system resources or security-sensitive information that
+   * this connection security layer might be using. Invoking this method
+   * invalidates this instance.
+   */
+  void dispose();
+
+
+
+  /**
+   * Unwraps a byte array received from the peer.
+   *
+   * @param incoming
+   *          A non-{@code null} byte array containing the encoded bytes from
+   *          the peer.
+   * @param offset
+   *          The starting position in {@code incoming} of the bytes to be
+   *          unwrapped.
+   * @param len
+   *          The number of bytes from {@code incoming} to be unwrapped.
+   * @return A non-{@code null} byte array containing the unwrapped bytes.
+   * @throws org.opends.sdk.ErrorResultException
+   *           If {@code incoming} cannot be successfully unwrapped.
+   */
+  byte[] unwrap(byte[] incoming, int offset, int len)
+      throws ErrorResultException;
+
+
+
+  /**
+   * Wraps a byte array to be sent to the peer.
+   *
+   * @param outgoing
+   *          A non-{@code null} byte array containing the unencoded bytes to be
+   *          sent to the peer.
+   * @param offset
+   *          The starting position in {@code outgoing} of the bytes to be
+   *          wrapped.
+   * @param len
+   *          The number of bytes from {@code outgoing} to be wrapped.
+   * @return A non-{@code null} byte array containing the wrapped bytes.
+   * @throws ErrorResultException
+   *           If {@code outgoing} cannot be successfully wrapped.
+   */
+  byte[] wrap(byte[] outgoing, int offset, int len) throws ErrorResultException;
+}
diff --git a/sdk/src/org/opends/sdk/Connections.java b/sdk/src/org/opends/sdk/Connections.java
index fd2b22b..9d9fec6 100644
--- a/sdk/src/org/opends/sdk/Connections.java
+++ b/sdk/src/org/opends/sdk/Connections.java
@@ -47,21 +47,20 @@
 {
   /**
    * Creates a new authenticated connection factory which will obtain
-   * connections using the provided connection factory and immediately
-   * perform the provided Bind request.
+   * connections using the provided connection factory and immediately perform
+   * the provided Bind request.
    * <p>
-   * The connections returned by an authenticated connection factory
-   * support all operations with the exception of Bind requests.
-   * Attempts to perform a Bind will result in an {@code
-   * UnsupportedOperationException}.
+   * The connections returned by an authenticated connection factory support all
+   * operations with the exception of Bind requests. Attempts to perform a Bind
+   * will result in an {@code UnsupportedOperationException}.
    * <p>
-   * If the Bind request fails for some reason (e.g. invalid
-   * credentials), then the connection attempt will fail and an {@code
-   * ErrorResultException} will be thrown.
+   * If the Bind request fails for some reason (e.g. invalid credentials), then
+   * the connection attempt will fail and an {@code ErrorResultException} will
+   * be thrown.
    *
    * @param factory
-   *          The connection factory to use for connecting to the
-   *          Directory Server.
+   *          The connection factory to use for connecting to the Directory
+   *          Server.
    * @param request
    *          The Bind request to use for authentication.
    * @return The new connection pool.
@@ -69,7 +68,7 @@
    *           If {@code factory} or {@code request} was {@code null}.
    */
   public static ConnectionFactory newAuthenticatedConnectionFactory(
-      ConnectionFactory factory, BindRequest request)
+      final ConnectionFactory factory, final BindRequest request)
       throws NullPointerException
   {
     Validator.ensureNotNull(factory, request);
@@ -84,8 +83,7 @@
    * connections created using the provided connection factory.
    *
    * @param factory
-   *          The connection factory to use for creating new
-   *          connections.
+   *          The connection factory to use for creating new connections.
    * @param poolSize
    *          The maximum size of the connection pool.
    * @return The new connection pool.
@@ -95,7 +93,7 @@
    *           If {@code factory} was {@code null}.
    */
   public static ConnectionFactory newConnectionPool(
-      ConnectionFactory factory, int poolSize)
+      final ConnectionFactory factory, final int poolSize)
       throws IllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(factory);
@@ -106,21 +104,19 @@
 
 
   /**
-   * Creates a new connection factory providing fault tolerance across
-   * multiple underlying connection factories.
+   * Creates a new connection factory providing fault tolerance across multiple
+   * underlying connection factories.
    * <p>
-   * The returned fail-over connection factory forwards connection
-   * requests to one of the provided connection factories. If the
-   * request fails for some reason (for example, due to network
-   * failure), then the fail-over connection factory switches to another
-   * connection faction, repeating the process until the connection
-   * request succeeds, or until all the connection factories are
-   * determined to be unavailable, in which case the connection request
-   * will fail.
+   * The returned fail-over connection factory forwards connection requests to
+   * one of the provided connection factories. If the request fails for some
+   * reason (for example, due to network failure), then the fail-over connection
+   * factory switches to another connection faction, repeating the process until
+   * the connection request succeeds, or until all the connection factories are
+   * determined to be unavailable, in which case the connection request will
+   * fail.
    * <p>
-   * The implementation periodically attempts to connect to failed
-   * connection factories in order to determine if they have become
-   * available again.
+   * The implementation periodically attempts to connect to failed connection
+   * factories in order to determine if they have become available again.
    *
    * @param factories
    *          The connection factories which will be used for fail-over.
@@ -129,10 +125,10 @@
    *           If {@code factories} was {@code null}.
    */
   public static ConnectionFactory newFailoverConnectionFactory(
-      Collection<ConnectionFactory> factories)
+      final Collection<ConnectionFactory> factories)
       throws NullPointerException
   {
-    FailoverLoadBalancingAlgorithm algorithm = new FailoverLoadBalancingAlgorithm(
+    final FailoverLoadBalancingAlgorithm algorithm = new FailoverLoadBalancingAlgorithm(
         factories);
     return new LoadBalancingConnectionFactory(algorithm);
   }
@@ -140,21 +136,19 @@
 
 
   /**
-   * Creates a new connection factory providing fault tolerance across
-   * multiple underlying connection factories.
+   * Creates a new connection factory providing fault tolerance across multiple
+   * underlying connection factories.
    * <p>
-   * The returned fail-over connection factory forwards connection
-   * requests to one of the provided connection factories. If the
-   * request fails for some reason (for example, due to network
-   * failure), then the fail-over connection factory switches to another
-   * connection faction, repeating the process until the connection
-   * request succeeds, or until all the connection factories are
-   * determined to be unavailable, in which case the connection request
-   * will fail.
+   * The returned fail-over connection factory forwards connection requests to
+   * one of the provided connection factories. If the request fails for some
+   * reason (for example, due to network failure), then the fail-over connection
+   * factory switches to another connection faction, repeating the process until
+   * the connection request succeeds, or until all the connection factories are
+   * determined to be unavailable, in which case the connection request will
+   * fail.
    * <p>
-   * The implementation periodically attempts to connect to failed
-   * connection factories in order to determine if they have become
-   * available again.
+   * The implementation periodically attempts to connect to failed connection
+   * factories in order to determine if they have become available again.
    *
    * @param factories
    *          The connection factories which will be used for fail-over.
@@ -163,9 +157,9 @@
    *           If {@code factories} was {@code null}.
    */
   public static ConnectionFactory newFailoverConnectionFactory(
-      ConnectionFactory... factories) throws NullPointerException
+      final ConnectionFactory... factories) throws NullPointerException
   {
-    FailoverLoadBalancingAlgorithm algorithm = new FailoverLoadBalancingAlgorithm(
+    final FailoverLoadBalancingAlgorithm algorithm = new FailoverLoadBalancingAlgorithm(
         factories);
     return new LoadBalancingConnectionFactory(algorithm);
   }
@@ -173,9 +167,9 @@
 
 
   /**
-   * Creates a new connection factory which will create connections
-   * using the provided connection factory and periodically probe any
-   * created connections in order to detect that they are still alive.
+   * Creates a new connection factory which will create connections using the
+   * provided connection factory and periodically probe any created connections
+   * in order to detect that they are still alive.
    *
    * @param factory
    *          The connection factory to use for creating connections.
@@ -190,7 +184,7 @@
    *           If {@code factory} or {@code unit} was {@code null}.
    */
   public static ConnectionFactory newHeartBeatConnectionFactory(
-      ConnectionFactory factory, long timeout, TimeUnit unit)
+      final ConnectionFactory factory, final long timeout, final TimeUnit unit)
       throws IllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(factory, unit);
@@ -202,10 +196,10 @@
 
 
   /**
-   * Creates a new connection factory which will create connections
-   * using the provided connection factory and periodically probe any
-   * created connections using the specified search request in order to
-   * detect that they are still alive.
+   * Creates a new connection factory which will create connections using the
+   * provided connection factory and periodically probe any created connections
+   * using the specified search request in order to detect that they are still
+   * alive.
    *
    * @param factory
    *          The connection factory to use for creating connections.
@@ -219,19 +213,44 @@
    * @throws IllegalArgumentException
    *           If {@code timeout} was negative.
    * @throws NullPointerException
-   *           If {@code factory}, {@code unit}, or {@code heartBeat}
-   *           was {@code null}.
+   *           If {@code factory}, {@code unit}, or {@code heartBeat} was
+   *           {@code null}.
    */
   public static ConnectionFactory newHeartBeatConnectionFactory(
-      ConnectionFactory factory, long timeout, TimeUnit unit,
-      SearchRequest heartBeat) throws IllegalArgumentException,
+      final ConnectionFactory factory, final long timeout, final TimeUnit unit,
+      final SearchRequest heartBeat) throws IllegalArgumentException,
       NullPointerException
   {
     Validator.ensureNotNull(factory, unit, heartBeat);
     Validator.ensureTrue(timeout >= 0, "negative timeout");
 
-    return new HeartBeatConnectionFactory(factory, timeout, unit,
-        heartBeat);
+    return new HeartBeatConnectionFactory(factory, timeout, unit, heartBeat);
+  }
+
+
+
+  /**
+   * Creates a new connection factory which will create internal connections
+   * using the provided server connection factory. The server connection will be
+   * provided with request context whose value is unique integer associated with
+   * the request.
+   *
+   * @param <C>
+   *          The type of client context.
+   * @param factory
+   *          The server connection factory to use for creating connections.
+   * @param clientContext
+   *          The client context.
+   * @return The new internal connection factory.
+   * @throws NullPointerException
+   *           If {@code factory} was {@code null}.
+   */
+  public static <C> ConnectionFactory newInternalConnectionFactory(
+      final ServerConnectionFactory<C, Integer> factory, final C clientContext)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(factory);
+    return new InternalConnectionFactory<C>(factory, clientContext);
   }
 
 
diff --git a/sdk/src/org/opends/sdk/ConstraintViolationException.java b/sdk/src/org/opends/sdk/ConstraintViolationException.java
new file mode 100644
index 0000000..5d8c9c0
--- /dev/null
+++ b/sdk/src/org/opends/sdk/ConstraintViolationException.java
@@ -0,0 +1,80 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import org.opends.sdk.responses.Result;
+
+
+
+/**
+ * Thrown when the result code returned in a Result indicates that the update
+ * Request failed because it would have left the Directory in an inconsistent
+ * state. More specifically, this exception is used for the following error
+ * result codes:
+ * <ul>
+ * <li>{@link ResultCode#ATTRIBUTE_OR_VALUE_EXISTS ATTRIBUTE_OR_VALUE_EXISTS} -
+ * the Request failed because it would have resulted in a conflict with an
+ * existing attribute or attribute value in the target entry.
+ * <li>{@link ResultCode#CONSTRAINT_VIOLATION CONSTRAINT_VIOLATION} - the
+ * Request failed because it would have violated some constraint defined in the
+ * server.
+ * <li>{@link ResultCode#ENTRY_ALREADY_EXISTS ENTRY_ALREADY_EXISTS} - the
+ * Request failed because it would have resulted in an entry that conflicts with
+ * an entry that already exists.
+ * <li>{@link ResultCode#INVALID_ATTRIBUTE_SYNTAX INVALID_ATTRIBUTE_SYNTAX} -
+ * the Request failed because it violated the syntax for a specified attribute.
+ * <li>{@link ResultCode#INVALID_DN_SYNTAX INVALID_DN_SYNTAX} - the Request
+ * failed because it would have resulted in an entry with an invalid or
+ * malformed DN.
+ * <li>{@link ResultCode#NAMING_VIOLATION NAMING_VIOLATION} - the Request failed
+ * becauseit would have violated the server's naming configuration.
+ * <li>{@link ResultCode#NOT_ALLOWED_ON_NONLEAF NOT_ALLOWED_ON_NONLEAF} - the
+ * Request failed because it is not allowed for non-leaf entries.
+ * <li>{@link ResultCode#NOT_ALLOWED_ON_RDN NOT_ALLOWED_ON_RDN} - the Request
+ * failed because it is not allowed on an RDN attribute.
+ * <li>{@link ResultCode#OBJECTCLASS_MODS_PROHIBITED
+ * OBJECTCLASS_MODS_PROHIBITED} - the Request failed because it would have
+ * modified the objectclasses associated with an entry in an illegal manner.
+ * <li>{@link ResultCode#OBJECTCLASS_VIOLATION OBJECTCLASS_VIOLATION} - the
+ * Request failed because it would have resulted in an entry that violated the
+ * server schema.
+ * <li>{@link ResultCode#UNDEFINED_ATTRIBUTE_TYPE UNDEFINED_ATTRIBUTE_TYPE} -
+ * the Request failed because it referenced an attribute that is not defined in
+ * the server schema.
+ * </ul>
+ */
+@SuppressWarnings("serial")
+public class ConstraintViolationException extends ErrorResultException
+{
+  ConstraintViolationException(final Result result)
+  {
+    super(result);
+  }
+}
diff --git a/sdk/src/org/opends/sdk/DN.java b/sdk/src/org/opends/sdk/DN.java
index 042c004..7d4dd30 100644
--- a/sdk/src/org/opends/sdk/DN.java
+++ b/sdk/src/org/opends/sdk/DN.java
@@ -22,14 +22,14 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_DN_TYPE_NOT_FOUND;
 
 import java.util.*;
 
@@ -43,9 +43,8 @@
 
 /**
  * A distinguished name (DN) as defined in RFC 4512 section 2.3 is the
- * concatenation of its relative distinguished name (RDN) and its
- * immediate superior's DN. A DN unambiguously refers to an entry in the
- * Directory.
+ * concatenation of its relative distinguished name (RDN) and its immediate
+ * superior's DN. A DN unambiguously refers to an entry in the Directory.
  * <p>
  * The following are examples of string representations of DNs:
  *
@@ -54,9 +53,9 @@
  * Smith,OU=Sales,O=ACME Limited,L=Moab,ST=Utah,C=US
  * </pre>
  *
- * @see <a href="http://tools.ietf.org/html/rfc4512#section-2.3">RFC
- *      4512 - Lightweight Directory Access Protocol (LDAP): Directory
- *      Information Models </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4512#section-2.3">RFC 4512 -
+ *      Lightweight Directory Access Protocol (LDAP): Directory Information
+ *      Models </a>
  */
 public final class DN implements Iterable<RDN>, Comparable<DN>
 {
@@ -67,7 +66,8 @@
   // cache parent DNs, so there's no need for it to be big.
   private static final int DN_CACHE_SIZE = 32;
 
-  private static final ThreadLocal<WeakHashMap<Schema, Map<String, DN>>> CACHE = new ThreadLocal<WeakHashMap<Schema, Map<String, DN>>>()
+  private static final ThreadLocal<WeakHashMap<Schema, Map<String, DN>>> CACHE =
+    new ThreadLocal<WeakHashMap<Schema, Map<String, DN>>>()
   {
 
     /**
@@ -84,8 +84,8 @@
 
 
   /**
-   * Returns the Root DN. The Root DN does not contain and RDN
-   * components and is superior to all other DNs.
+   * Returns the Root DN. The Root DN does not contain and RDN components and is
+   * superior to all other DNs.
    *
    * @return The Root DN.
    */
@@ -97,19 +97,18 @@
 
 
   /**
-   * Parses the provided LDAP string representation of a DN using the
-   * default schema.
+   * Parses the provided LDAP string representation of a DN using the default
+   * schema.
    *
    * @param dn
    *          The LDAP string representation of a DN.
    * @return The parsed DN.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} is not a valid LDAP string representation
-   *           of a DN.
+   *           If {@code dn} is not a valid LDAP string representation of a DN.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public static DN valueOf(String dn)
+  public static DN valueOf(final String dn)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     return valueOf(dn, Schema.getDefaultSchema());
@@ -118,8 +117,8 @@
 
 
   /**
-   * Parses the provided LDAP string representation of a DN using the
-   * provided schema.
+   * Parses the provided LDAP string representation of a DN using the provided
+   * schema.
    *
    * @param dn
    *          The LDAP string representation of a DN.
@@ -127,15 +126,14 @@
    *          The schema to use when parsing the DN.
    * @return The parsed DN.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} is not a valid LDAP string representation
-   *           of a DN.
+   *           If {@code dn} is not a valid LDAP string representation of a DN.
    * @throws NullPointerException
    *           If {@code dn} or {@code schema} was {@code null}.
    */
-  public static DN valueOf(String dn, Schema schema)
-      throws LocalizedIllegalArgumentException
+  public static DN valueOf(final String dn, final Schema schema)
+      throws LocalizedIllegalArgumentException, NullPointerException
   {
-    Validator.ensureNotNull(schema);
+    Validator.ensureNotNull(dn, schema);
     if (dn.length() == 0)
     {
       return ROOT_DN;
@@ -157,8 +155,8 @@
 
 
   // Decodes a DN using the provided reader and schema.
-  private static DN decode(String dnString, SubstringReader reader,
-      Schema schema, Map<String, DN> cache)
+  private static DN decode(final String dnString, final SubstringReader reader,
+      final Schema schema, final Map<String, DN> cache)
       throws LocalizedIllegalArgumentException
   {
     reader.skipWhitespaces();
@@ -207,19 +205,17 @@
 
 
   @SuppressWarnings("serial")
-  private static Map<String, DN> getCache(Schema schema)
+  private static Map<String, DN> getCache(final Schema schema)
   {
-    final WeakHashMap<Schema, Map<String, DN>> threadLocalMap = CACHE
-        .get();
+    final WeakHashMap<Schema, Map<String, DN>> threadLocalMap = CACHE.get();
     Map<String, DN> schemaLocalMap = threadLocalMap.get(schema);
 
     if (schemaLocalMap == null)
     {
-      schemaLocalMap = new LinkedHashMap<String, DN>(DN_CACHE_SIZE,
-          0.75f, true)
+      schemaLocalMap = new LinkedHashMap<String, DN>(DN_CACHE_SIZE, 0.75f, true)
       {
         @Override
-        protected boolean removeEldestEntry(Map.Entry<String, DN> e)
+        protected boolean removeEldestEntry(final Map.Entry<String, DN> e)
         {
           return size() > DN_CACHE_SIZE;
         }
@@ -246,7 +242,7 @@
 
 
   // Private constructor.
-  private DN(RDN rdn, DN parent, String stringValue)
+  private DN(final RDN rdn, final DN parent, final String stringValue)
   {
     this.rdn = rdn;
     this.parent = parent;
@@ -257,17 +253,16 @@
 
 
   /**
-   * Returns a DN which is subordinate to this DN and having the
-   * additional RDN components contained in the provided DN.
+   * Returns a DN which is subordinate to this DN and having the additional RDN
+   * components contained in the provided DN.
    *
    * @param dn
-   *          The DN containing the RDN components to be added to this
-   *          DN.
+   *          The DN containing the RDN components to be added to this DN.
    * @return The subordinate DN.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public DN child(DN dn) throws NullPointerException
+  public DN child(final DN dn) throws NullPointerException
   {
     Validator.ensureNotNull(dn);
 
@@ -308,7 +303,7 @@
    * @throws NullPointerException
    *           If {@code rdn} was {@code null}.
    */
-  public DN child(RDN rdn) throws NullPointerException
+  public DN child(final RDN rdn) throws NullPointerException
   {
     Validator.ensureNotNull(rdn);
     return new DN(rdn, this, null);
@@ -317,21 +312,18 @@
 
 
   /**
-   * Returns a DN which is subordinate to this DN and having the
-   * additional RDN components contained in the provided DN decoded
-   * using the default schema.
+   * Returns a DN which is subordinate to this DN and having the additional RDN
+   * components contained in the provided DN decoded using the default schema.
    *
    * @param dn
-   *          The DN containing the RDN components to be added to this
-   *          DN.
+   *          The DN containing the RDN components to be added to this DN.
    * @return The subordinate DN.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} is not a valid LDAP string representation
-   *           of a DN.
+   *           If {@code dn} is not a valid LDAP string representation of a DN.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public DN child(String dn) throws LocalizedIllegalArgumentException,
+  public DN child(final String dn) throws LocalizedIllegalArgumentException,
       NullPointerException
   {
     Validator.ensureNotNull(dn);
@@ -343,11 +335,90 @@
   /**
    * {@inheritDoc}
    */
-  public int compareTo(DN dn)
+  public int compareTo(final DN dn)
   {
-    final String s1 = toNormalizedString();
-    final String s2 = dn.toNormalizedString();
-    return s1.compareTo(s2);
+    return compareTo(this, dn);
+  }
+
+
+
+  /**
+   * Compares the provided DN values to determine their relative order in a
+   * sorted list.
+   *
+   * @param dn1
+   *          The first DN to be compared. It must not be {@code null}.
+   * @param dn2
+   *          The second DN to be compared. It must not be {@code null}.
+   * @return A negative integer if the first DN should come before the second DN
+   *         in a sorted list, a positive integer if the first DN should come
+   *         after the second DN in a sorted list, or zero if the two DN values
+   *         can be considered equal.
+   */
+  public int compareTo(final DN dn1, final DN dn2)
+  {
+    // Quicly check if we are comparing against root dse.
+    if (dn1.isRootDN())
+    {
+      if (dn2.isRootDN())
+      {
+        // both are equal.
+        return 0;
+      }
+      else
+      {
+        // dn1 comes before dn2.
+        return -1;
+      }
+    }
+
+    if (dn2.isRootDN())
+    {
+      // dn1 comes after dn2.
+      return 1;
+    }
+
+    int dn1Size = dn1.size - 1;
+    int dn2Size = dn2.size - 1;
+    while (dn1Size >= 0 && dn2Size >= 0)
+    {
+      final DN dn1Parent = dn1.parent(dn1Size--);
+      final DN dn2Parent = dn2.parent(dn2Size--);
+      if (dn1Parent.isRootDN())
+      {
+        if (dn2Parent.isRootDN())
+        {
+          break;
+        }
+        return -1;
+      }
+
+      if (dn2Parent.isRootDN())
+      {
+        return 1;
+      }
+
+      final int result = dn1Parent.rdn.compareTo(dn2Parent.rdn);
+      if (result > 0)
+      {
+        return 1;
+      }
+      else if (result < 0)
+      {
+        return -1;
+      }
+    }
+    // What do we have here?
+    if (dn1Size > dn2Size)
+    {
+      return 1;
+    }
+    else if (dn1Size < dn2Size)
+    {
+      return -1;
+    }
+
+    return 0;
   }
 
 
@@ -355,7 +426,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean equals(Object obj)
+  @Override
+  public boolean equals(final Object obj)
   {
     if (this == obj)
     {
@@ -378,6 +450,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public int hashCode()
   {
     final String s = toNormalizedString();
@@ -387,17 +460,16 @@
 
 
   /**
-   * Returns {@code true} if this DN is an immediate child of the
-   * provided DN.
+   * Returns {@code true} if this DN is an immediate child of the provided DN.
    *
    * @param dn
    *          The potential parent DN.
-   * @return {@code true} if this DN is the immediate child of the
-   *         provided DN, otherwise {@code false}.
+   * @return {@code true} if this DN is the immediate child of the provided DN,
+   *         otherwise {@code false}.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public boolean isChildOf(DN dn) throws NullPointerException
+  public boolean isChildOf(final DN dn) throws NullPointerException
   {
     // If this is the Root DN then parent will be null but this is ok.
     return dn.equals(parent);
@@ -406,20 +478,19 @@
 
 
   /**
-   * Returns {@code true} if this DN is an immediate child of the
-   * provided DN decoded using the default schema.
+   * Returns {@code true} if this DN is an immediate child of the provided DN
+   * decoded using the default schema.
    *
    * @param dn
    *          The potential parent DN.
-   * @return {@code true} if this DN is the immediate child of the
-   *         provided DN, otherwise {@code false}.
+   * @return {@code true} if this DN is the immediate child of the provided DN,
+   *         otherwise {@code false}.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} is not a valid LDAP string representation
-   *           of a DN.
+   *           If {@code dn} is not a valid LDAP string representation of a DN.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public boolean isChildOf(String dn)
+  public boolean isChildOf(final String dn)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     // If this is the Root DN then parent will be null but this is ok.
@@ -429,17 +500,16 @@
 
 
   /**
-   * Returns {@code true} if this DN is the immediate parent of the
-   * provided DN.
+   * Returns {@code true} if this DN is the immediate parent of the provided DN.
    *
    * @param dn
    *          The potential child DN.
-   * @return {@code true} if this DN is the immediate parent of the
-   *         provided DN, otherwise {@code false}.
+   * @return {@code true} if this DN is the immediate parent of the provided DN,
+   *         otherwise {@code false}.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public boolean isParentOf(DN dn) throws NullPointerException
+  public boolean isParentOf(final DN dn) throws NullPointerException
   {
     // If dn is the Root DN then parent will be null but this is ok.
     return equals(dn.parent);
@@ -448,20 +518,18 @@
 
 
   /**
-   * Returns {@code true} if this DN is the immediate parent of the
-   * provided DN.
+   * Returns {@code true} if this DN is the immediate parent of the provided DN.
    *
    * @param dn
    *          The potential child DN.
-   * @return {@code true} if this DN is the immediate parent of the
-   *         provided DN, otherwise {@code false}.
+   * @return {@code true} if this DN is the immediate parent of the provided DN,
+   *         otherwise {@code false}.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} is not a valid LDAP string representation
-   *           of a DN.
+   *           If {@code dn} is not a valid LDAP string representation of a DN.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public boolean isParentOf(String dn)
+  public boolean isParentOf(final String dn)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     // If dn is the Root DN then parent will be null but this is ok.
@@ -473,8 +541,7 @@
   /**
    * Returns {@code true} if this DN is the Root DN.
    *
-   * @return {@code true} if this DN is the Root DN, otherwise {@code
-   *         false}.
+   * @return {@code true} if this DN is the Root DN, otherwise {@code false}.
    */
   public boolean isRootDN()
   {
@@ -484,17 +551,17 @@
 
 
   /**
-   * Returns {@code true} if this DN is subordinate to or equal to the
-   * provided DN.
+   * Returns {@code true} if this DN is subordinate to or equal to the provided
+   * DN.
    *
    * @param dn
    *          The potential child DN.
-   * @return {@code true} if this DN is subordinate to or equal to the
-   *         provided DN, otherwise {@code false}.
+   * @return {@code true} if this DN is subordinate to or equal to the provided
+   *         DN, otherwise {@code false}.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public boolean isSubordinateOrEqualTo(DN dn)
+  public boolean isSubordinateOrEqualTo(final DN dn)
       throws NullPointerException
   {
     if (size < dn.size)
@@ -508,27 +575,26 @@
     else
     {
       // dn is a potential superior of this.
-      return parent(dn.size - size).equals(dn);
+      return parent(size - dn.size).equals(dn);
     }
   }
 
 
 
   /**
-   * Returns {@code true} if this DN is subordinate to or equal to the
-   * provided DN.
+   * Returns {@code true} if this DN is subordinate to or equal to the provided
+   * DN.
    *
    * @param dn
    *          The potential child DN.
-   * @return {@code true} if this DN is subordinate to or equal to the
-   *         provided DN, otherwise {@code false}.
+   * @return {@code true} if this DN is subordinate to or equal to the provided
+   *         DN, otherwise {@code false}.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} is not a valid LDAP string representation
-   *           of a DN.
+   *           If {@code dn} is not a valid LDAP string representation of a DN.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public boolean isSubordinateOrEqualTo(String dn)
+  public boolean isSubordinateOrEqualTo(final String dn)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     return isSubordinateOrEqualTo(valueOf(dn));
@@ -537,17 +603,16 @@
 
 
   /**
-   * Returns {@code true} if this DN is superior to or equal to the
-   * provided DN.
+   * Returns {@code true} if this DN is superior to or equal to the provided DN.
    *
    * @param dn
    *          The potential child DN.
-   * @return {@code true} if this DN is superior to or equal to the
-   *         provided DN, otherwise {@code false}.
+   * @return {@code true} if this DN is superior to or equal to the provided DN,
+   *         otherwise {@code false}.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public boolean isSuperiorOrEqualTo(DN dn) throws NullPointerException
+  public boolean isSuperiorOrEqualTo(final DN dn) throws NullPointerException
   {
     if (size > dn.size)
     {
@@ -567,20 +632,18 @@
 
 
   /**
-   * Returns {@code true} if this DN is superior to or equal to the
-   * provided DN.
+   * Returns {@code true} if this DN is superior to or equal to the provided DN.
    *
    * @param dn
    *          The potential child DN.
-   * @return {@code true} if this DN is superior to or equal to the
-   *         provided DN, otherwise {@code false}.
+   * @return {@code true} if this DN is superior to or equal to the provided DN,
+   *         otherwise {@code false}.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} is not a valid LDAP string representation
-   *           of a DN.
+   *           If {@code dn} is not a valid LDAP string representation of a DN.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  public boolean isSuperiorOrEqualTo(String dn)
+  public boolean isSuperiorOrEqualTo(final String dn)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     return isSuperiorOrEqualTo(valueOf(dn));
@@ -589,13 +652,13 @@
 
 
   /**
-   * Returns an iterator of the RDNs contained in this DN. The RDNs will
-   * be returned in the order starting with this DN's RDN, followed by
-   * the RDN of the parent DN, and so on.
+   * Returns an iterator of the RDNs contained in this DN. The RDNs will be
+   * returned in the order starting with this DN's RDN, followed by the RDN of
+   * the parent DN, and so on.
    * <p>
-   * Attempts to remove RDNs using an iterator's {@code remove()} method
-   * are not permitted and will result in an {@code
-   * UnsupportedOperationException} being thrown.
+   * Attempts to remove RDNs using an iterator's {@code remove()} method are not
+   * permitted and will result in an {@code UnsupportedOperationException} being
+   * thrown.
    *
    * @return An iterator of the RDNs contained in this DN.
    */
@@ -638,8 +701,8 @@
 
 
   /**
-   * Returns the DN which is the immediate parent of this DN, or {@code
-   * null} if this DN is the Root DN.
+   * Returns the DN which is the immediate parent of this DN, or {@code null} if
+   * this DN is the Root DN.
    * <p>
    * This method is equivalent to:
    *
@@ -647,8 +710,8 @@
    * parent(1);
    * </pre>
    *
-   * @return The DN which is the immediate parent of this DN, or {@code
-   *         null} if this DN is the Root DN.
+   * @return The DN which is the immediate parent of this DN, or {@code null} if
+   *         this DN is the Root DN.
    */
   public DN parent()
   {
@@ -658,19 +721,18 @@
 
 
   /**
-   * Returns the DN which is equal to this DN with the specified number
-   * of RDNs removed. Note that if {@code index} is zero then this DN
-   * will be returned (identity).
+   * Returns the DN which is equal to this DN with the specified number of RDNs
+   * removed. Note that if {@code index} is zero then this DN will be returned
+   * (identity).
    *
    * @param index
    *          The number of RDNs to be removed.
-   * @return The DN which is equal to this DN with the specified number
-   *         of RDNs removed, or {@code null} if the parent of the Root
-   *         DN is reached.
+   * @return The DN which is equal to this DN with the specified number of RDNs
+   *         removed, or {@code null} if the parent of the Root DN is reached.
    * @throws IllegalArgumentException
    *           If {@code index} is less than zero.
    */
-  public DN parent(int index) throws IllegalArgumentException
+  public DN parent(final int index) throws IllegalArgumentException
   {
     // We allow size + 1 so that we can return null as the parent of the
     // Root DN.
@@ -687,11 +749,9 @@
 
 
   /**
-   * Returns the RDN of this DN, or {@code null} if this DN is the Root
-   * DN.
+   * Returns the RDN of this DN, or {@code null} if this DN is the Root DN.
    *
-   * @return The RDN of this DN, or {@code null} if this DN is the Root
-   *         DN.
+   * @return The RDN of this DN, or {@code null} if this DN is the Root DN.
    */
   public RDN rdn()
   {
@@ -719,15 +779,19 @@
    */
   public String toNormalizedString()
   {
+    if (rdn == null)
+    {
+      return "".intern();
+    }
     if (normalizedStringValue == null)
     {
       final StringBuilder builder = new StringBuilder();
+      rdn.toNormalizedString(builder);
       if (!parent.isRootDN())
       {
-        builder.append(parent.toNormalizedString());
         builder.append(',');
+        builder.append(parent.toNormalizedString());
       }
-      rdn.toNormalizedString(builder);
       normalizedStringValue = builder.toString();
     }
     return normalizedStringValue;
@@ -739,10 +803,11 @@
    * Returns the RFC 4514 string representation of this DN.
    *
    * @return The RFC 4514 string representation of this DN.
-   * @see <a href="http://tools.ietf.org/html/rfc4514">RFC 4514 -
-   *      Lightweight Directory Access Protocol (LDAP): String
-   *      Representation of Distinguished Names </a>
+   * @see <a href="http://tools.ietf.org/html/rfc4514">RFC 4514 - Lightweight
+   *      Directory Access Protocol (LDAP): String Representation of
+   *      Distinguished Names </a>
    */
+  @Override
   public String toString()
   {
     // We don't care about potential race conditions here.
diff --git a/sdk/src/org/opends/sdk/DecodeException.java b/sdk/src/org/opends/sdk/DecodeException.java
index c3c3384..c80bcae 100644
--- a/sdk/src/org/opends/sdk/DecodeException.java
+++ b/sdk/src/org/opends/sdk/DecodeException.java
@@ -33,20 +33,44 @@
 
 
 
-
 /**
- * Thrown when data from an input source cannot be decoded, perhaps due
- * to the data being malformed in some way. By default decoding
- * exceptions are fatal, indicating that the associated input source is
- * no longer usable.
+ * Thrown when data from an input source cannot be decoded, perhaps due to the
+ * data being malformed in some way. By default decoding exceptions are fatal,
+ * indicating that the associated input source is no longer usable.
  */
 @SuppressWarnings("serial")
 public final class DecodeException extends IOException implements
     LocalizableException
 {
-  private final LocalizableMessage message;
+  /**
+   * Creates a new non-fatal decode exception with the provided message.
+   *
+   * @param message
+   *          The message that explains the problem that occurred.
+   * @return The new non-fatal decode exception.
+   */
+  public static DecodeException error(final LocalizableMessage message)
+  {
+    return new DecodeException(message, false, null);
+  }
 
-  private final boolean isFatal;
+
+
+  /**
+   * Creates a new non-fatal decode exception with the provided message and root
+   * cause.
+   *
+   * @param message
+   *          The message that explains the problem that occurred.
+   * @param cause
+   *          The underlying cause of this exception.
+   * @return The new non-fatal decode exception.
+   */
+  public static DecodeException error(final LocalizableMessage message,
+      final Throwable cause)
+  {
+    return new DecodeException(message, false, cause);
+  }
 
 
 
@@ -58,7 +82,7 @@
    *          The message that explains the problem that occurred.
    * @return The new fatal decode exception.
    */
-  public static DecodeException fatalError(LocalizableMessage message)
+  public static DecodeException fatalError(final LocalizableMessage message)
   {
     return new DecodeException(message, true, null);
   }
@@ -66,8 +90,8 @@
 
 
   /**
-   * Creates a new fatal decode exception with the provided message and
-   * root cause. The associated input source can no longer be used.
+   * Creates a new fatal decode exception with the provided message and root
+   * cause. The associated input source can no longer be used.
    *
    * @param message
    *          The message that explains the problem that occurred.
@@ -75,48 +99,23 @@
    *          The underlying cause of this exception.
    * @return The new fatal decode exception.
    */
-  public static DecodeException fatalError(LocalizableMessage message,
-      Throwable cause)
+  public static DecodeException fatalError(final LocalizableMessage message,
+      final Throwable cause)
   {
     return new DecodeException(message, true, cause);
   }
 
 
 
-  /**
-   * Creates a new non-fatal decode exception with the provided message.
-   *
-   * @param message
-   *          The message that explains the problem that occurred.
-   * @return The new non-fatal decode exception.
-   */
-  public static DecodeException error(LocalizableMessage message)
-  {
-    return new DecodeException(message, false, null);
-  }
+  private final LocalizableMessage message;
 
-
-
-  /**
-   * Creates a new non-fatal decode exception with the provided message
-   * and root cause.
-   *
-   * @param message
-   *          The message that explains the problem that occurred.
-   * @param cause
-   *          The underlying cause of this exception.
-   * @return The new non-fatal decode exception.
-   */
-  public static DecodeException error(LocalizableMessage message, Throwable cause)
-  {
-    return new DecodeException(message, false, cause);
-  }
+  private final boolean isFatal;
 
 
 
   // Construction is provided via factory methods.
-  private DecodeException(LocalizableMessage message, boolean isFatal,
-      Throwable cause)
+  private DecodeException(final LocalizableMessage message,
+      final boolean isFatal, final Throwable cause)
   {
     super(message.toString(), cause);
     this.message = message;
@@ -138,12 +137,11 @@
 
 
   /**
-   * Indicates whether or not the error was fatal and the associated
-   * input source can no longer be used.
+   * Indicates whether or not the error was fatal and the associated input
+   * source can no longer be used.
    *
-   * @return {@code true} if the error was fatal and the associated
-   *         input source can no longer be used, otherwise {@code false}
-   *         .
+   * @return {@code true} if the error was fatal and the associated input source
+   *         can no longer be used, otherwise {@code false} .
    */
   public boolean isFatal()
   {
diff --git a/sdk/src/org/opends/sdk/DecodeOptions.java b/sdk/src/org/opends/sdk/DecodeOptions.java
new file mode 100644
index 0000000..886191e
--- /dev/null
+++ b/sdk/src/org/opends/sdk/DecodeOptions.java
@@ -0,0 +1,241 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import org.opends.sdk.schema.Schema;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * Decode options allow applications to control how requests and responses are
+ * decoded. In particular:
+ * <ul>
+ * <li>The strategy for selecting which {@code Schema} should be used for
+ * decoding distinguished names, attribute descriptions, and other objects which
+ * require a schema in order to be decoded.
+ * <li>The {@code Attribute} implementation which should be used when decoding
+ * attributes.
+ * <li>The {@code Entry} implementation which should be used when decoding
+ * entries or entry like objects.
+ * </ul>
+ */
+public final class DecodeOptions
+{
+  private static final class FixedSchemaResolver implements SchemaResolver
+  {
+    private final Schema schema;
+
+
+
+    private FixedSchemaResolver(final Schema schema)
+    {
+      this.schema = schema;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public Schema resolveSchema(final String dn)
+    {
+      return schema;
+    }
+
+  }
+
+
+
+  private SchemaResolver schemaResolver;
+
+  private EntryFactory entryFactory;
+
+  private AttributeFactory attributeFactory;
+
+
+
+  /**
+   * Creates a new set of decode options which will always use the default
+   * schema returned by {@link Schema#getDefaultSchema()},
+   * {@link LinkedAttribute}, and {@link LinkedHashMapEntry}.
+   */
+  public DecodeOptions()
+  {
+    this.attributeFactory = LinkedAttribute.FACTORY;
+    this.entryFactory = LinkedHashMapEntry.FACTORY;
+    this.schemaResolver = new FixedSchemaResolver(Schema.getDefaultSchema());
+  }
+
+
+
+  /**
+   * Creates a new set of decode options having the same initial set of options
+   * as the provided set of decode options.
+   *
+   * @param options
+   *          The set of decode options to be copied.
+   */
+  public DecodeOptions(final DecodeOptions options)
+  {
+    this.attributeFactory = options.attributeFactory;
+    this.entryFactory = options.entryFactory;
+    this.schemaResolver = options.schemaResolver;
+  }
+
+
+
+  /**
+   * Returns the {@code AttributeFactory} which will be used for creating new
+   * {@code Attribute} instances when decoding attributes.
+   *
+   * @return The {@code AttributeFactory} which will be used for creating new
+   *         {@code Attribute} instances when decoding attributes.
+   */
+  public final AttributeFactory getAttributeFactory()
+  {
+    return attributeFactory;
+  }
+
+
+
+  /**
+   * Returns the {@code EntryFactory} which will be used for creating new
+   * {@code Entry} instances when decoding entries.
+   *
+   * @return The {@code EntryFactory} which will be used for creating new
+   *         {@code Entry} instances when decoding entries.
+   */
+  public final EntryFactory getEntryFactory()
+  {
+    return entryFactory;
+  }
+
+
+
+  /**
+   * Returns the strategy for selecting which {@code Schema} should be used for
+   * decoding distinguished names, attribute descriptions, and other objects
+   * which require a {@code Schema} in order to be decoded.
+   *
+   * @return The schema resolver which will be used for decoding.
+   */
+  public final SchemaResolver getSchemaResolver()
+  {
+    return schemaResolver;
+  }
+
+
+
+  /**
+   * Sets the {@code AttributeFactory} which will be used for creating new
+   * {@code Attribute} instances when decoding attributes.
+   *
+   * @param factory
+   *          The {@code AttributeFactory} which will be used for creating new
+   *          {@code Attribute} instances when decoding attributes.
+   * @return A reference to this set of decode options.
+   * @throws NullPointerException
+   *           If {@code factory} was {@code null}.
+   */
+  public final DecodeOptions setAttributeFactory(final AttributeFactory factory)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(factory);
+    this.attributeFactory = factory;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the {@code EntryFactory} which will be used for creating new {@code
+   * Entry} instances when decoding entries.
+   *
+   * @param factory
+   *          The {@code EntryFactory} which will be used for creating new
+   *          {@code Entry} instances when decoding entries.
+   * @return A reference to this set of decode options.
+   * @throws NullPointerException
+   *           If {@code factory} was {@code null}.
+   */
+  public final DecodeOptions setEntryFactory(final EntryFactory factory)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(factory);
+    this.entryFactory = factory;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the {@code Schema} which will be used for decoding distinguished
+   * names, attribute descriptions, and other objects which require a schema in
+   * order to be decoded. This setting overrides the currently active schema
+   * resolver set using {@link #setSchemaResolver}.
+   *
+   * @param schema
+   *          The {@code Schema} which will be used for decoding.
+   * @return A reference to this set of decode options.
+   * @throws NullPointerException
+   *           If {@code schema} was {@code null}.
+   */
+  public final DecodeOptions setSchema(final Schema schema)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(schema);
+    this.schemaResolver = new FixedSchemaResolver(schema);
+    return this;
+  }
+
+
+
+  /**
+   * Sets the strategy for selecting which {@code Schema} should be used for
+   * decoding distinguished names, attribute descriptions, and other objects
+   * which require a {@code Schema} in order to be decoded. This setting
+   * overrides the currently active schema set using {@link #setSchema}.
+   *
+   * @param resolver
+   *          The {@code SchemaResolver} which will be used for decoding.
+   * @return A reference to this set of decode options.
+   * @throws NullPointerException
+   *           If {@code resolver} was {@code null}.
+   */
+  public final DecodeOptions setSchemaResolver(final SchemaResolver resolver)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(resolver);
+    this.schemaResolver = resolver;
+    return this;
+  }
+}
diff --git a/sdk/src/org/opends/sdk/DereferenceAliasesPolicy.java b/sdk/src/org/opends/sdk/DereferenceAliasesPolicy.java
index 43cf1fb..3bd0309 100644
--- a/sdk/src/org/opends/sdk/DereferenceAliasesPolicy.java
+++ b/sdk/src/org/opends/sdk/DereferenceAliasesPolicy.java
@@ -36,18 +36,16 @@
 
 
 /**
- * A Search operation alias dereferencing policy as defined in RFC 4511
- * section 4.5.1.3 is used to indicate whether or not alias entries (as
- * defined in RFC 4512) are to be dereferenced during stages of a Search
- * operation. The act of dereferencing an alias includes recursively
- * dereferencing aliases that refer to aliases.
+ * A Search operation alias dereferencing policy as defined in RFC 4511 section
+ * 4.5.1.3 is used to indicate whether or not alias entries (as defined in RFC
+ * 4512) are to be dereferenced during stages of a Search operation. The act of
+ * dereferencing an alias includes recursively dereferencing aliases that refer
+ * to aliases.
  *
- * @see <a href="http://tools.ietf.org/html/rfc4511#section-4.5.1.3">RFC
- *      4511 - Lightweight Directory Access Protocol (LDAP): The
- *      Protocol </a>
- * @see <a href="http://tools.ietf.org/html/rfc4512">RFC 4512 -
- *      Lightweight Directory Access Protocol (LDAP): Directory
- *      Information Models </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4511#section-4.5.1.3">RFC 4511 -
+ *      Lightweight Directory Access Protocol (LDAP): The Protocol </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4512">RFC 4512 - Lightweight
+ *      Directory Access Protocol (LDAP): Directory Information Models </a>
  */
 public final class DereferenceAliasesPolicy
 {
@@ -57,52 +55,48 @@
       .unmodifiableList(Arrays.asList(ELEMENTS));
 
   /**
-   * Do not dereference aliases in searching or in locating the base
-   * object of a Search operation.
+   * Do not dereference aliases in searching or in locating the base object of a
+   * Search operation.
    */
-  public static final DereferenceAliasesPolicy NEVER = register(0,
-      "never");
+  public static final DereferenceAliasesPolicy NEVER = register(0, "never");
 
   /**
-   * While searching subordinates of the base object, dereference any
-   * alias within the scope of the Search operation. Dereferenced
-   * objects become the vertices of further search scopes where the
-   * Search operation is also applied. If the search scope is {@code
-   * WHOLE_SUBTREE}, the Search continues in the subtree(s) of any
-   * dereferenced object. If the search scope is {@code SINGLE_LEVEL},
-   * the search is applied to any dereferenced objects and is not
-   * applied to their subordinates.
+   * While searching subordinates of the base object, dereference any alias
+   * within the scope of the Search operation. Dereferenced objects become the
+   * vertices of further search scopes where the Search operation is also
+   * applied. If the search scope is {@code WHOLE_SUBTREE}, the Search continues
+   * in the subtree(s) of any dereferenced object. If the search scope is
+   * {@code SINGLE_LEVEL}, the search is applied to any dereferenced objects and
+   * is not applied to their subordinates.
    */
-  public static final DereferenceAliasesPolicy IN_SEARCHING = register(
-      1, "search");
+  public static final DereferenceAliasesPolicy IN_SEARCHING = register(1,
+      "search");
 
   /**
-   * Dereference aliases in locating the base object of a Search
-   * operation, but not when searching subordinates of the base object.
+   * Dereference aliases in locating the base object of a Search operation, but
+   * not when searching subordinates of the base object.
    */
-  public static final DereferenceAliasesPolicy FINDING_BASE = register(
-      2, "find");
+  public static final DereferenceAliasesPolicy FINDING_BASE = register(2,
+      "find");
 
   /**
-   * Dereference aliases both in searching and in locating the base
-   * object of a Search operation.
+   * Dereference aliases both in searching and in locating the base object of a
+   * Search operation.
    */
-  public static final DereferenceAliasesPolicy ALWAYS = register(3,
-      "always");
+  public static final DereferenceAliasesPolicy ALWAYS = register(3, "always");
 
 
 
   /**
-   * Returns the alias dereferencing policy having the specified integer
-   * value as defined in RFC 4511 section 4.5.1.
+   * Returns the alias dereferencing policy having the specified integer value
+   * as defined in RFC 4511 section 4.5.1.
    *
    * @param intValue
    *          The integer value of the alias dereferencing policy.
-   * @return The dereference aliases policy, or {@code null} if there
-   *         was no alias dereferencing policy associated with {@code
-   *         intValue}.
+   * @return The dereference aliases policy, or {@code null} if there was no
+   *         alias dereferencing policy associated with {@code intValue}.
    */
-  public static DereferenceAliasesPolicy valueOf(int intValue)
+  public static DereferenceAliasesPolicy valueOf(final int intValue)
   {
     if (intValue < 0 || intValue >= ELEMENTS.length)
     {
@@ -115,8 +109,8 @@
 
   /**
    * Returns an unmodifiable list containing the set of available alias
-   * dereferencing policies indexed on their integer value as defined in
-   * RFC 4511 section 4.5.1.
+   * dereferencing policies indexed on their integer value as defined in RFC
+   * 4511 section 4.5.1.
    *
    * @return An unmodifiable list containing the set of available alias
    *         dereferencing policies.
@@ -133,17 +127,17 @@
    * application.
    *
    * @param intValue
-   *          The integer value of the alias dereferencing policy as
-   *          defined in RFC 4511 section 4.5.1.
+   *          The integer value of the alias dereferencing policy as defined in
+   *          RFC 4511 section 4.5.1.
    * @param name
    *          The name of the alias dereferencing policy.
    * @return The new alias dereferencing policy.
    */
-  private static DereferenceAliasesPolicy register(int intValue,
-      String name)
+  private static DereferenceAliasesPolicy register(final int intValue,
+      final String name)
   {
-    final DereferenceAliasesPolicy t = new DereferenceAliasesPolicy(
-        intValue, name);
+    final DereferenceAliasesPolicy t = new DereferenceAliasesPolicy(intValue,
+        name);
     ELEMENTS[intValue] = t;
     return t;
   }
@@ -157,7 +151,7 @@
 
 
   // Prevent direct instantiation.
-  private DereferenceAliasesPolicy(int intValue, String name)
+  private DereferenceAliasesPolicy(final int intValue, final String name)
   {
     this.intValue = intValue;
     this.name = name;
@@ -168,7 +162,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean equals(Object obj)
+  @Override
+  public boolean equals(final Object obj)
   {
     if (this == obj)
     {
@@ -189,6 +184,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public int hashCode()
   {
     return intValue;
@@ -197,8 +193,8 @@
 
 
   /**
-   * Returns the integer value of this alias dereferencing policy as
-   * defined in RFC 4511 section 4.5.1.
+   * Returns the integer value of this alias dereferencing policy as defined in
+   * RFC 4511 section 4.5.1.
    *
    * @return The integer value of this alias dereferencing policy.
    */
@@ -210,12 +206,11 @@
 
 
   /**
-   * Returns the string representation of this alias dereferencing
-   * policy.
+   * Returns the string representation of this alias dereferencing policy.
    *
-   * @return The string representation of this alias dereferencing
-   *         policy.
+   * @return The string representation of this alias dereferencing policy.
    */
+  @Override
   public String toString()
   {
     return name;
diff --git a/sdk/src/org/opends/sdk/Entry.java b/sdk/src/org/opends/sdk/Entry.java
index 38c1541..0b588e4 100644
--- a/sdk/src/org/opends/sdk/Entry.java
+++ b/sdk/src/org/opends/sdk/Entry.java
@@ -31,55 +31,75 @@
 
 import java.util.Collection;
 
-import org.opends.sdk.schema.ObjectClass;
-
-
 
 
 /**
- * An entry, comprising of a distinguished name and zero or more
- * attributes.
+ * An entry, comprising of a distinguished name and zero or more attributes.
  * <p>
- * Some methods require a schema in order to decode their parameters
- * (e.g. {@link #addAttribute(String, Object...)} and
- * {@link #setName(String)}). In these cases the default schema is used
- * unless an alternative schema is specified in the {@code Entry}
- * constructor. The default schema is not used for any other purpose. In
- * particular, an {@code Entry} will permit attributes to be added which
- * have been decoded using a different schema.
+ * Some methods require a schema in order to decode their parameters (e.g.
+ * {@link #addAttribute(String, Object...)} and {@link #setName(String)}). In
+ * these cases the default schema is used unless an alternative schema is
+ * specified in the {@code Entry} constructor. The default schema is not used
+ * for any other purpose. In particular, an {@code Entry} will permit attributes
+ * to be added which have been decoded using multiple schemas.
  * <p>
- * Full LDAP modify semantics are provided via the {@link #addAttribute}, {@link #removeAttribute}, and {@link #replaceAttribute} methods.
+ * Full LDAP modify semantics are provided via the {@link #addAttribute},
+ * {@link #removeAttribute}, and {@link #replaceAttribute} methods.
  * <p>
  * Implementations should specify any constraints or special behavior.
- * In particular, which methods are supported, and the order in which
- * attributes are returned using the {@link #getAttributes()} method.
- * <p>
- * TODO: can we return collections/lists instead of iterables?
- * <p>
- * TODO: containsAttributeValue(String, Object)
+ * Specifically:
+ * <ul>
+ * <li>Which methods are supported.
+ * <li>The order in which attributes are returned using the
+ * {@link #getAllAttributes()} method.
+ * <li>How existing attributes are modified during calls to
+ * {@link #addAttribute}, {@link #removeAttribute}, and
+ * {@link #replaceAttribute} and the conditions, if any, where a reference to
+ * the passed in attribute is maintained.
+ * </ul>
  */
 public interface Entry
 {
 
   /**
-   * Adds all of the attribute values contained in {@code attribute} to
-   * this entry, merging with any existing attribute values (optional
-   * operation). If {@code attribute} is empty then this entry is left
-   * unchanged.
+   * Adds all of the attribute values contained in {@code attribute} to this
+   * entry, merging with any existing attribute values (optional operation). If
+   * {@code attribute} is empty then this entry is left unchanged.
    * <p>
    * <b>NOTE:</b> This method implements LDAP Modify add semantics.
    *
    * @param attribute
-   *          The attribute values to be added to this entry, merging
-   *          with any existing attribute values.
-   * @param duplicateValues
-   *          A collection into which duplicate values will be added, or
-   *          {@code null} if duplicate values should not be saved.
-   * @return {@code true} if this entry changed as a result of this
-   *         call.
+   *          The attribute values to be added to this entry, merging with any
+   *          existing attribute values.
+   * @return {@code true} if this entry changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this entry does not permit attributes or their values
-   *           to be added.
+   *           If this entry does not permit attributes or their values to be
+   *           added.
+   * @throws NullPointerException
+   *           If {@code attribute} was {@code null}.
+   */
+  boolean addAttribute(Attribute attribute)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * Adds all of the attribute values contained in {@code attribute} to this
+   * entry, merging with any existing attribute values (optional operation). If
+   * {@code attribute} is empty then this entry is left unchanged.
+   * <p>
+   * <b>NOTE:</b> This method implements LDAP Modify add semantics.
+   *
+   * @param attribute
+   *          The attribute values to be added to this entry, merging with any
+   *          existing attribute values.
+   * @param duplicateValues
+   *          A collection into which duplicate values will be added, or {@code
+   *          null} if duplicate values should not be saved.
+   * @return {@code true} if this entry changed as a result of this call.
+   * @throws UnsupportedOperationException
+   *           If this entry does not permit attributes or their values to be
+   *           added.
    * @throws NullPointerException
    *           If {@code attribute} was {@code null}.
    */
@@ -90,71 +110,36 @@
 
 
   /**
-   * Adds all of the attribute values contained in {@code attribute} to
-   * this entry, merging with any existing attribute values (optional
-   * operation). If {@code attribute} is empty then this entry is left
-   * unchanged.
+   * Adds all of the attribute values contained in {@code values} to this entry,
+   * merging with any existing attribute values (optional operation). If {@code
+   * values} is {@code null} or empty then this entry is left unchanged.
    * <p>
-   * If {@code attribute} is an instance of {@code Attribute} then it
-   * will be added to this entry as if {@link #addAttribute} was called.
+   * The attribute description will be decoded using the schema associated with
+   * this entry (usually the default schema).
    * <p>
-   * If {@code attribute} is not an instance of {@code Attribute} then
-   * its attribute description will be decoded using the schema
-   * associated with this entry, and any attribute values which are not
-   * instances of {@code ByteString} will be converted using the
-   * {@link ByteString#valueOf(Object)} method.
-   * <p>
-   * <b>NOTE:</b> This method implements LDAP Modify add semantics.
-   *
-   * @param attribute
-   *          The attribute values to be added to this entry merging
-   *          with any existing attribute values.
-   * @return {@code true} if this entry changed as a result of this
-   *         call.
-   * @throws UnsupportedOperationException
-   *           If this entry does not permit attributes or their values
-   *           to be added.
-   * @throws NullPointerException
-   *           If {@code attribute} was {@code null}.
-   */
-  boolean addAttribute(Attribute attribute)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Adds all of the attribute values contained in {@code values} to
-   * this entry, merging with any existing attribute values (optional
-   * operation). If {@code values} is {@code null} or empty then this
-   * entry is left unchanged.
-   * <p>
-   * The attribute description will be decoded using the schema
-   * associated with this entry.
-   * <p>
-   * Any attribute values which are not instances of {@code ByteString}
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    * <p>
    * <b>NOTE:</b> This method implements LDAP Modify add semantics.
    *
    * @param attributeDescription
    *          The name of the attribute whose values are to be added.
    * @param values
-   *          The attribute values to be added to this entry, merging
-   *          any existing attribute values.
+   *          The attribute values to be added to this entry, merging any
+   *          existing attribute values.
    * @return This entry.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the schema associated with this entry.
+   *           If {@code attributeDescription} could not be decoded using the
+   *           schema associated with this entry.
    * @throws UnsupportedOperationException
-   *           If this entry does not permit attributes or their values
-   *           to be added.
+   *           If this entry does not permit attributes or their values to be
+   *           added.
    * @throws NullPointerException
-   *           If {@code attribute} was {@code null}.
+   *           If {@code attributeDescription} was {@code null}.
    */
   Entry addAttribute(String attributeDescription, Object... values)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 
 
@@ -170,94 +155,88 @@
 
 
   /**
-   * Indicates whether or not this entry contains the named attribute.
+   * Returns {@code true} if this entry contains all of the attribute values
+   * contained in {@code attribute}. If {@code attribute} is empty then this
+   * method will return {@code true} if the attribute is present in this entry,
+   * regardless of how many values it contains.
    *
-   * @param attributeDescription
-   *          The name of the attribute.
-   * @return {@code true} if this entry contains the named attribute,
-   *         otherwise {@code false}.
+   * @param attribute
+   *          The attribute values whose presence in this entry is to be tested.
+   * @param missingValues
+   *          A collection into which missing values will be added, or {@code
+   *          null} if missing values should not be saved.
+   * @return {@code true} if this entry contains all of the attribute values
+   *         contained in {@code attribute}.
    * @throws NullPointerException
-   *           If {@code attributeDescription} was {@code null}.
+   *           If {@code attribute} was {@code null}.
    */
-  boolean containsAttribute(AttributeDescription attributeDescription)
-      throws NullPointerException;
+  boolean containsAttribute(Attribute attribute,
+      Collection<ByteString> missingValues) throws NullPointerException;
 
 
 
   /**
-   * Indicates whether or not this entry contains the named attribute.
+   * Returns {@code true} if this entry contains all of the attribute values
+   * contained in {@code values}. If {@code values} is {@code null} or empty
+   * then this method will return {@code true} if the attribute is present in
+   * this entry, regardless of how many values it contains.
    * <p>
-   * The attribute description will be decoded using the schema
-   * associated with this entry.
+   * The attribute description will be decoded using the schema associated with
+   * this entry (usually the default schema).
+   * <p>
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param attributeDescription
-   *          The name of the attribute.
-   * @return {@code true} if this entry contains the named attribute,
-   *         otherwise {@code false}.
+   *          The name of the attribute whose presence in this entry is to be
+   *          tested.
+   * @param values
+   *          The attribute values whose presence in this entry is to be tested,
+   *          which may be {@code null}.
+   * @return {@code true} if this entry contains all of the attribute values
+   *         contained in {@code values}.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the schema associated with this entry.
+   *           If {@code attributeDescription} could not be decoded using the
+   *           schema associated with this entry.
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
-  boolean containsAttribute(String attributeDescription)
+  boolean containsAttribute(String attributeDescription, Object... values)
       throws LocalizedIllegalArgumentException, NullPointerException;
 
 
 
   /**
-   * Indicates whether or not this entry contains the provided object
-   * class.
-   *
-   * @param objectClass
-   *          The object class.
-   * @return {@code true} if this entry contains the object class,
-   *         otherwise {@code false}.
-   * @throws NullPointerException
-   *           If {@code objectClass} was {@code null}.
-   */
-  boolean containsObjectClass(ObjectClass objectClass)
-      throws NullPointerException;
-
-
-
-  /**
-   * Indicates whether or not this entry contains the named object
-   * class.
-   *
-   * @param objectClass
-   *          The name of the object class.
-   * @return {@code true} if this entry contains the object class,
-   *         otherwise {@code false}.
-   * @throws NullPointerException
-   *           If {@code objectClass} was {@code null}.
-   */
-  boolean containsObjectClass(String objectClass)
-      throws NullPointerException;
-
-
-
-  /**
-   * Returns {@code true} if {@code object} is an entry which is equal
-   * to this entry. Two entries are considered equal if their
-   * distinguished names are equal, they both have the same number of
-   * attributes, and every attribute contained in the first entry is
-   * also contained in the second entry.
+   * Returns {@code true} if {@code object} is an entry which is equal to this
+   * entry. Two entries are considered equal if their distinguished names are
+   * equal, they both have the same number of attributes, and every attribute
+   * contained in the first entry is also contained in the second entry.
    *
    * @param object
    *          The object to be tested for equality with this entry.
-   * @return {@code true} if {@code object} is an entry which is equal
-   *         to this entry, or {@code false} if not.
+   * @return {@code true} if {@code object} is an entry which is equal to this
+   *         entry, or {@code false} if not.
    */
   boolean equals(Object object);
 
 
 
   /**
-   * Returns an {@code Iterable} containing all the attributes in this
-   * entry having an attribute description which is a sub-type of the
-   * provided attribute description. The returned {@code Iterable} may
-   * be used to remove attributes if permitted by this entry.
+   * Returns an {@code Iterable} containing all of the attributes in this entry.
+   * The returned {@code Iterable} may be used to remove attributes if permitted
+   * by this entry.
+   *
+   * @return An {@code Iterable} containing all of the attributes.
+   */
+  Iterable<Attribute> getAllAttributes();
+
+
+
+  /**
+   * Returns an {@code Iterable} containing all the attributes in this entry
+   * having an attribute description which is a sub-type of the provided
+   * attribute description. The returned {@code Iterable} may be used to remove
+   * attributes if permitted by this entry.
    *
    * @param attributeDescription
    *          The name of the attributes to be returned.
@@ -265,43 +244,42 @@
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
-  Iterable<Attribute> findAttributes(
-      AttributeDescription attributeDescription)
+  Iterable<Attribute> getAllAttributes(AttributeDescription attributeDescription)
       throws NullPointerException;
 
 
 
   /**
-   * Returns an {@code Iterable} containing all the attributes in this
-   * entry having an attribute description which is a sub-type of the
-   * provided attribute description. The returned {@code Iterable} may
-   * be used to remove attributes if permitted by this entry.
+   * Returns an {@code Iterable} containing all the attributes in this entry
+   * having an attribute description which is a sub-type of the provided
+   * attribute description. The returned {@code Iterable} may be used to remove
+   * attributes if permitted by this entry.
    * <p>
-   * The attribute description will be decoded using the schema
-   * associated with this entry.
+   * The attribute description will be decoded using the schema associated with
+   * this entry (usually the default schema).
    *
    * @param attributeDescription
    *          The name of the attributes to be returned.
    * @return An {@code Iterable} containing the matching attributes.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the schema associated with this entry.
+   *           If {@code attributeDescription} could not be decoded using the
+   *           schema associated with this entry.
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
-  Iterable<Attribute> findAttributes(String attributeDescription)
+  Iterable<Attribute> getAllAttributes(String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException;
 
 
 
   /**
-   * Returns the named attribute contained in this entry, or {@code
-   * null} if it is not included with this entry.
+   * Returns the named attribute contained in this entry, or {@code null} if it
+   * is not included with this entry.
    *
    * @param attributeDescription
    *          The name of the attribute to be returned.
-   * @return The named attribute, or {@code null} if it is not included
-   *         with this entry.
+   * @return The named attribute, or {@code null} if it is not included with
+   *         this entry.
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
@@ -311,19 +289,19 @@
 
 
   /**
-   * Returns the named attribute contained in this entry, or {@code
-   * null} if it is not included with this entry.
+   * Returns the named attribute contained in this entry, or {@code null} if it
+   * is not included with this entry.
    * <p>
-   * The attribute description will be decoded using the schema
-   * associated with this entry.
+   * The attribute description will be decoded using the schema associated with
+   * this entry (usually the default schema).
    *
    * @param attributeDescription
    *          The name of the attribute to be returned.
-   * @return The named attribute, or {@code null} if it is not included
-   *         with this entry.
+   * @return The named attribute, or {@code null} if it is not included with
+   *         this entry.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the schema associated with this entry.
+   *           If {@code attributeDescription} could not be decoded using the
+   *           schema associated with this entry.
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
@@ -342,19 +320,7 @@
 
 
   /**
-   * Returns an {@code Iterable} containing the attributes in this
-   * entry. The returned {@code Iterable} may be used to remove
-   * attributes if permitted by this entry.
-   *
-   * @return An {@code Iterable} containing the attributes.
-   */
-  Iterable<Attribute> getAttributes();
-
-
-
-  /**
-   * Returns the string representation of the distinguished name of this
-   * entry.
+   * Returns the string representation of the distinguished name of this entry.
    *
    * @return The string representation of the distinguished name.
    */
@@ -363,20 +329,8 @@
 
 
   /**
-   * Returns an {@code Iterable} containing the names of the object
-   * classes in this entry. The returned {@code Iterable} may be used to
-   * remove object classes if permitted by this entry.
-   *
-   * @return An {@code Iterable} containing the object classes.
-   */
-  Iterable<String> getObjectClasses();
-
-
-
-  /**
-   * Returns the hash code for this entry. It will be calculated as the
-   * sum of the hash codes of the distinguished name and all of the
-   * attributes.
+   * Returns the hash code for this entry. It will be calculated as the sum of
+   * the hash codes of the distinguished name and all of the attributes.
    *
    * @return The hash code for this entry.
    */
@@ -385,24 +339,22 @@
 
 
   /**
-   * Removes all of the attribute values contained in {@code attribute}
-   * from this entry if it is present (optional operation). If {@code
-   * attribute} is empty then the entire attribute will be removed if it
-   * is present.
+   * Removes all of the attribute values contained in {@code attribute} from
+   * this entry if it is present (optional operation). If {@code attribute} is
+   * empty then the entire attribute will be removed if it is present.
    * <p>
    * <b>NOTE:</b> This method implements LDAP Modify delete semantics.
    *
    * @param attribute
-   *          The attribute values to be removed from this entry, which
-   *          may be empty if the entire attribute is to be removed.
+   *          The attribute values to be removed from this entry, which may be
+   *          empty if the entire attribute is to be removed.
    * @param missingValues
-   *          A collection into which missing values will be added, or
-   *          {@code null} if missing values should not be saved.
-   * @return {@code true} if this entry changed as a result of this
-   *         call.
+   *          A collection into which missing values will be added, or {@code
+   *          null} if missing values should not be saved.
+   * @return {@code true} if this entry changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this entry does not permit attributes or their values
-   *           to be removed.
+   *           If this entry does not permit attributes or their values to be
+   *           removed.
    * @throws NullPointerException
    *           If {@code attribute} was {@code null}.
    */
@@ -413,15 +365,13 @@
 
 
   /**
-   * Removes the named attribute from this entry if it is present
-   * (optional operation). If this attribute does not contain the
-   * attribute, the call leaves this entry unchanged and returns {@code
-   * false}.
+   * Removes the named attribute from this entry if it is present (optional
+   * operation). If this attribute does not contain the attribute, the call
+   * leaves this entry unchanged and returns {@code false}.
    *
    * @param attributeDescription
    *          The name of the attribute to be removed.
-   * @return {@code true} if this entry changed as a result of this
-   *         call.
+   * @return {@code true} if this entry changed as a result of this call.
    * @throws UnsupportedOperationException
    *           If this entry does not permit attributes to be removed.
    * @throws NullPointerException
@@ -433,84 +383,56 @@
 
 
   /**
-   * Removes the named attribute from this entry if it is present
-   * (optional operation). If this attribute does not contain the
-   * attribute, the call leaves this entry unchanged.
+   * Removes all of the attribute values contained in {@code values} from the
+   * named attribute in this entry if it is present (optional operation). If
+   * {@code values} is {@code null} or empty then the entire attribute will be
+   * removed if it is present.
    * <p>
-   * The attribute description will be decoded using the schema
-   * associated with this entry.
-   *
-   * @param attributeDescription
-   *          The name of the attribute to be removed.
-   * @return This entry.
-   * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the schema associated with this entry.
-   * @throws UnsupportedOperationException
-   *           If this entry does not permit attributes to be removed.
-   * @throws NullPointerException
-   *           If {@code attributeDescription} was {@code null}.
-   */
-  Entry removeAttribute(String attributeDescription)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Removes all of the attribute values contained in {@code values}
-   * from the named attribute in this entry if it is present (optional
-   * operation). If {@code values} is {@code null} or empty then the
-   * entire attribute will be removed if it is present.
+   * The attribute description will be decoded using the schema associated with
+   * this entry (usually the default schema).
    * <p>
-   * The attribute description will be decoded using the schema
-   * associated with this entry.
-   * <p>
-   * Any attribute values which are not instances of {@code ByteString}
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    * <p>
    * <b>NOTE:</b> This method implements LDAP Modify delete semantics.
    *
    * @param attributeDescription
    *          The name of the attribute whose values are to be removed.
    * @param values
-   *          The attribute values to be removed from this entry, which
-   *          may be {@code null} or empty if the entire attribute is to
-   *          be removed.
+   *          The attribute values to be removed from this entry, which may be
+   *          {@code null} or empty if the entire attribute is to be removed.
    * @return This entry.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the schema associated with this entry.
+   *           If {@code attributeDescription} could not be decoded using the
+   *           schema associated with this entry.
    * @throws UnsupportedOperationException
-   *           If this entry does not permit attributes or their values
-   *           to be removed.
+   *           If this entry does not permit attributes or their values to be
+   *           removed.
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
   Entry removeAttribute(String attributeDescription, Object... values)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Adds all of the attribute values contained in {@code attribute} to
-   * this entry, replacing any existing attribute values (optional
-   * operation). If {@code attribute} is empty then the entire attribute
-   * will be removed if it is present.
+   * Adds all of the attribute values contained in {@code attribute} to this
+   * entry, replacing any existing attribute values (optional operation). If
+   * {@code attribute} is empty then the entire attribute will be removed if it
+   * is present.
    * <p>
    * <b>NOTE:</b> This method implements LDAP Modify replace semantics.
    *
    * @param attribute
-   *          The attribute values to be added to this entry, replacing
-   *          any existing attribute values, and which may be empty if
-   *          the entire attribute is to be removed.
-   * @return {@code true} if this entry changed as a result of this
-   *         call.
+   *          The attribute values to be added to this entry, replacing any
+   *          existing attribute values, and which may be empty if the entire
+   *          attribute is to be removed.
+   * @return {@code true} if this entry changed as a result of this call.
    * @throws UnsupportedOperationException
-   *           If this entry does not permit attributes or their values
-   *           to be replaced.
+   *           If this entry does not permit attributes or their values to be
+   *           replaced.
    * @throws NullPointerException
    *           If {@code attribute} was {@code null}.
    */
@@ -520,59 +442,38 @@
 
 
   /**
-   * Adds all of the attribute values contained in {@code values} to
-   * this entry, replacing any existing attribute values (optional
-   * operation). If {@code values} is {@code null} or empty then the
-   * entire attribute will be removed if it is present.
+   * Adds all of the attribute values contained in {@code values} to this entry,
+   * replacing any existing attribute values (optional operation). If {@code
+   * values} is {@code null} or empty then the entire attribute will be removed
+   * if it is present.
    * <p>
-   * The attribute description will be decoded using the schema
-   * associated with this entry.
+   * The attribute description will be decoded using the schema associated with
+   * this entry (usually the default schema).
    * <p>
-   * Any attribute values which are not instances of {@code ByteString}
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    * <p>
    * <b>NOTE:</b> This method implements LDAP Modify replace semantics.
    *
    * @param attributeDescription
    *          The name of the attribute whose values are to be replaced.
    * @param values
-   *          The attribute values to be added to this entry, replacing
-   *          any existing attribute values, and which may be {@code
-   *          null} or empty if the entire attribute is to be removed.
+   *          The attribute values to be added to this entry, replacing any
+   *          existing attribute values, and which may be {@code null} or empty
+   *          if the entire attribute is to be removed.
    * @return This entry.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the schema associated with this entry.
+   *           If {@code attributeDescription} could not be decoded using the
+   *           schema associated with this entry.
    * @throws UnsupportedOperationException
-   *           If this entry does not permit attributes or their values
-   *           to be replaced.
+   *           If this entry does not permit attributes or their values to be
+   *           replaced.
    * @throws NullPointerException
    *           If {@code attribute} was {@code null}.
    */
   Entry replaceAttribute(String attributeDescription, Object... values)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Sets the distinguished name of this entry (optional operation).
-   *
-   * @param dn
-   *          The string representation of the distinguished name.
-   * @return This entry.
-   * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} could not be decoded using the schema
-   *           associated with this entry.
-   * @throws UnsupportedOperationException
-   *           If this entry does not permit the distinguished name to
-   *           be set.
-   * @throws NullPointerException
-   *           If {@code dn} was {@code null}.
-   */
-  Entry setName(String dn) throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 
 
@@ -583,8 +484,7 @@
    *          The distinguished name.
    * @return This entry.
    * @throws UnsupportedOperationException
-   *           If this entry does not permit the distinguished name to
-   *           be set.
+   *           If this entry does not permit the distinguished name to be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
@@ -594,6 +494,28 @@
 
 
   /**
+   * Sets the distinguished name of this entry (optional operation).
+   * <p>
+   * The distinguished name will be decoded using the schema associated with
+   * this entry (usually the default schema).
+   *
+   * @param dn
+   *          The string representation of the distinguished name.
+   * @return This entry.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code dn} could not be decoded using the schema associated
+   *           with this entry.
+   * @throws UnsupportedOperationException
+   *           If this entry does not permit the distinguished name to be set.
+   * @throws NullPointerException
+   *           If {@code dn} was {@code null}.
+   */
+  Entry setName(String dn) throws LocalizedIllegalArgumentException,
+      UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
    * Returns a string representation of this entry.
    *
    * @return The string representation of this entry.
diff --git a/sdk/src/org/opends/sdk/EntryFactory.java b/sdk/src/org/opends/sdk/EntryFactory.java
new file mode 100644
index 0000000..2c4b2e6
--- /dev/null
+++ b/sdk/src/org/opends/sdk/EntryFactory.java
@@ -0,0 +1,53 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+/**
+ * Entry factories are included with a set of {@code DecodeOptions} in order to
+ * allow application to control how {@code Entry} instances are created when
+ * decoding requests and responses.
+ *
+ * @see Entry
+ * @see DecodeOptions
+ */
+public interface EntryFactory
+{
+  /**
+   * Creates an empty entry using the provided distinguished name and no
+   * attributes.
+   *
+   * @param name
+   *          The distinguished name of the entry to be created.
+   * @return The new entry.
+   * @throws NullPointerException
+   *           If {@code name} was {@code null}.
+   */
+  Entry newEntry(DN name) throws NullPointerException;
+}
diff --git a/sdk/src/org/opends/sdk/EntryNotFoundException.java b/sdk/src/org/opends/sdk/EntryNotFoundException.java
index 87493d5..31f7de8 100644
--- a/sdk/src/org/opends/sdk/EntryNotFoundException.java
+++ b/sdk/src/org/opends/sdk/EntryNotFoundException.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
@@ -34,22 +34,26 @@
 
 
 /**
- * Thrown when the result code returned in a Result indicates that the
- * Request failed because the target entry was not found by the
- * Directory Server. More specifically, this exception is used for the
- * following error result codes:
+ * Thrown when the result code returned in a Result indicates that the Request
+ * failed because the target entry was not found by the Directory Server. More
+ * specifically, this exception is used for the following error result codes:
  * <ul>
- * <li>{@link ResultCode#NO_SUCH_OBJECT} - the requested operation
- * failed because it referenced an entry that does not exist.
- * <li>{@link ResultCode#CLIENT_SIDE_NO_RESULTS_RETURNED} - the
- * requested single entry search operation or read operation failed
- * because the Directory Server did not return any matching entries.
+ * <li>{@link ResultCode#NO_SUCH_OBJECT NO_SUCH_OBJECT} - the requested
+ * operation failed because it referenced an entry that does not exist.
+ * <li>{@link ResultCode#REFERRAL REFERRAL} - the requested operation failed
+ * because it referenced an entry that is located on another server.
+ * <li>{@link ResultCode#CLIENT_SIDE_NO_RESULTS_RETURNED
+ * CLIENT_SIDE_NO_RESULTS_RETURNED} - the requested single entry search
+ * operation or read operation failed because the Directory Server did not
+ * return any matching entries.
  * </ul>
+ * <b>NOTE:</b> referrals are handled by the {@link ReferralException}
+ * sub-class.
  */
 @SuppressWarnings("serial")
 public class EntryNotFoundException extends ErrorResultException
 {
-  EntryNotFoundException(Result result)
+  EntryNotFoundException(final Result result)
   {
     super(result);
   }
diff --git a/sdk/src/org/opends/sdk/ErrorResultException.java b/sdk/src/org/opends/sdk/ErrorResultException.java
index 89af186..f64756f 100644
--- a/sdk/src/org/opends/sdk/ErrorResultException.java
+++ b/sdk/src/org/opends/sdk/ErrorResultException.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
@@ -36,20 +36,15 @@
 
 
 /**
- * Thrown when the result code returned in a Result indicates that the
- * Request was unsuccessful.
+ * Thrown when the result code returned in a Result indicates that the Request
+ * was unsuccessful.
  */
 @SuppressWarnings("serial")
 public class ErrorResultException extends ExecutionException
 {
-  private final Result result;
-
-
-
   /**
-   * Wraps the provided result in an appropriate error result exception.
-   * The type of error result exception used depends on the underlying
-   * result code.
+   * Wraps the provided result in an appropriate error result exception. The
+   * type of error result exception used depends on the underlying result code.
    *
    * @param result
    *          The result whose result code indicates a failure.
@@ -59,7 +54,7 @@
    * @throws NullPointerException
    *           If {@code result} was {@code null}.
    */
-  public static ErrorResultException wrap(Result result)
+  public static ErrorResultException wrap(final Result result)
       throws IllegalArgumentException, NullPointerException
   {
     if (!result.getResultCode().isExceptional())
@@ -68,50 +63,86 @@
           "Attempted to wrap a successful result: " + result);
     }
 
-    // TODO: choose type of exception based on result code (e.g.
-    // referral).
-    if (result.getResultCode() == ResultCode.CLIENT_SIDE_SERVER_DOWN
-        || result.getResultCode() == ResultCode.CLIENT_SIDE_CONNECT_ERROR
-        || result.getResultCode() == ResultCode.CLIENT_SIDE_DECODING_ERROR
-        || result.getResultCode() == ResultCode.CLIENT_SIDE_ENCODING_ERROR)
+    ResultCode rc = result.getResultCode();
+    if (rc == ResultCode.ASSERTION_FAILED)
+    {
+      return new AssertionFailureException(result);
+    }
+    else if (rc == ResultCode.AUTH_METHOD_NOT_SUPPORTED
+        || rc == ResultCode.CLIENT_SIDE_AUTH_UNKNOWN
+        || rc == ResultCode.INAPPROPRIATE_AUTHENTICATION
+        || rc == ResultCode.INVALID_CREDENTIALS)
+    {
+      return new AuthenticationException(result);
+    }
+    else if (rc == ResultCode.AUTHORIZATION_DENIED
+        || rc == ResultCode.CONFIDENTIALITY_REQUIRED
+        || rc == ResultCode.INSUFFICIENT_ACCESS_RIGHTS
+        || rc == ResultCode.STRONG_AUTH_REQUIRED)
+    {
+      return new AuthorizationException(result);
+    }
+    else if (rc == ResultCode.CLIENT_SIDE_USER_CANCELLED
+        || rc == ResultCode.CANCELLED)
+    {
+      return new CancelledResultException(result);
+    }
+    else if (rc == ResultCode.CLIENT_SIDE_SERVER_DOWN
+        || rc == ResultCode.CLIENT_SIDE_CONNECT_ERROR
+        || rc == ResultCode.CLIENT_SIDE_DECODING_ERROR
+        || rc == ResultCode.CLIENT_SIDE_ENCODING_ERROR)
     {
       return new ConnectionException(result);
     }
-
-    if (result.getResultCode() == ResultCode.CLIENT_SIDE_TIMEOUT)
+    else if (rc == ResultCode.ATTRIBUTE_OR_VALUE_EXISTS
+        || rc == ResultCode.CONSTRAINT_VIOLATION
+        || rc == ResultCode.ENTRY_ALREADY_EXISTS
+        || rc == ResultCode.INVALID_ATTRIBUTE_SYNTAX
+        || rc == ResultCode.INVALID_DN_SYNTAX
+        || rc == ResultCode.NAMING_VIOLATION
+        || rc == ResultCode.NOT_ALLOWED_ON_NONLEAF
+        || rc == ResultCode.NOT_ALLOWED_ON_RDN
+        || rc == ResultCode.OBJECTCLASS_MODS_PROHIBITED
+        || rc == ResultCode.OBJECTCLASS_VIOLATION
+        || rc == ResultCode.UNDEFINED_ATTRIBUTE_TYPE)
+    {
+      return new ConstraintViolationException(result);
+    }
+    else if (rc == ResultCode.REFERRAL)
+    {
+      return new ReferralException(result);
+    }
+    else if (rc == ResultCode.NO_SUCH_OBJECT
+        || rc == ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
+    {
+      return new EntryNotFoundException(result);
+    }
+    else if (rc == ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
+    {
+      return new MultipleEntriesFoundException(result);
+    }
+    else if (rc == ResultCode.CLIENT_SIDE_TIMEOUT
+        || rc == ResultCode.TIME_LIMIT_EXCEEDED)
     {
       return new TimeoutResultException(result);
     }
 
-    if (result.getResultCode() == ResultCode.CLIENT_SIDE_USER_CANCELLED
-        || result.getResultCode() == ResultCode.CANCELLED)
-    {
-      return new CancelledResultException(result);
-    }
-
-    if (result.getResultCode() == ResultCode.NO_SUCH_OBJECT
-        || result.getResultCode() == ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
-    {
-      return new EntryNotFoundException(result);
-    }
-
-    if (result.getResultCode() == ResultCode.CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED)
-    {
-      return new MultipleEntriesFoundException(result);
-    }
-
     return new ErrorResultException(result);
   }
 
 
 
+  private final Result result;
+
+
+
   /**
    * Creates a new error result exception using the provided result.
    *
    * @param result
    *          The error result.
    */
-  ErrorResultException(Result result)
+  ErrorResultException(final Result result)
   {
     super(result.getResultCode() + ": " + result.getDiagnosticMessage());
     this.result = result;
@@ -120,9 +151,9 @@
 
 
   /**
-   * Returns the error result which caused this exception to be thrown.
-   * The type of result returned corresponds to the expected result type
-   * of the original request.
+   * Returns the error result which caused this exception to be thrown. The type
+   * of result returned corresponds to the expected result type of the original
+   * request.
    *
    * @return The error result which caused this exception to be thrown.
    */
diff --git a/sdk/src/org/opends/sdk/ErrorResultIOException.java b/sdk/src/org/opends/sdk/ErrorResultIOException.java
index 109ed21..7366bbd 100644
--- a/sdk/src/org/opends/sdk/ErrorResultIOException.java
+++ b/sdk/src/org/opends/sdk/ErrorResultIOException.java
@@ -36,8 +36,8 @@
 
 
 /**
- * An {@code ErrorResultIOException} adapts an {@code
- * ErrorResultException} to an {@code IOException}.
+ * An {@code ErrorResultIOException} adapts an {@code ErrorResultException} to
+ * an {@code IOException}.
  */
 @SuppressWarnings("serial")
 public final class ErrorResultIOException extends IOException
@@ -50,12 +50,12 @@
    * Creates a new error result IO exception with the provided cause.
    *
    * @param cause
-   *          The cause which may be later retrieved by the
-   *          {@link #getCause} method.
+   *          The cause which may be later retrieved by the {@link #getCause}
+   *          method.
    * @throws NullPointerException
    *           If {@code cause} was {@code null}.
    */
-  public ErrorResultIOException(ErrorResultException cause)
+  public ErrorResultIOException(final ErrorResultException cause)
       throws NullPointerException
   {
     super(Validator.ensureNotNull(cause));
@@ -68,6 +68,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public ErrorResultException getCause()
   {
     return cause;
diff --git a/sdk/src/org/opends/sdk/FailoverLoadBalancingAlgorithm.java b/sdk/src/org/opends/sdk/FailoverLoadBalancingAlgorithm.java
index 2bbc581..4843021 100644
--- a/sdk/src/org/opends/sdk/FailoverLoadBalancingAlgorithm.java
+++ b/sdk/src/org/opends/sdk/FailoverLoadBalancingAlgorithm.java
@@ -42,25 +42,20 @@
 
 
 /**
- * A fail-over load balancing algorithm provides fault tolerance across
- * multiple underlying connection factories.
+ * A fail-over load balancing algorithm provides fault tolerance across multiple
+ * underlying connection factories.
  * <p>
- * If a problem occurs that temporarily prevents connections from being
- * obtained for one of the connection factories, then this algorithm
- * "fails over" to another operational connection factory in the list.
- * If none of the connection factories are operational then a {@code
- * ConnectionException} is returned to the client.
+ * If a problem occurs that temporarily prevents connections from being obtained
+ * for one of the connection factories, then this algorithm "fails over" to
+ * another operational connection factory in the list. If none of the connection
+ * factories are operational then a {@code ConnectionException} is returned to
+ * the client.
  * <p>
- * The implementation periodically attempts to connect to failed
- * connection factories in order to determine if they have become
- * available again.
+ * The implementation periodically attempts to connect to failed connection
+ * factories in order to determine if they have become available again.
  */
 class FailoverLoadBalancingAlgorithm implements LoadBalancingAlgorithm
 {
-  private final List<MonitoredConnectionFactory> monitoredFactories;
-
-
-
   private static final class MonitoredConnectionFactory extends
       AbstractConnectionFactory implements
       ResultHandler<AsynchronousConnection>
@@ -73,7 +68,7 @@
 
 
 
-    private MonitoredConnectionFactory(ConnectionFactory factory)
+    private MonitoredConnectionFactory(final ConnectionFactory factory)
     {
       this.factory = factory;
       this.isOperational = true;
@@ -81,35 +76,14 @@
 
 
 
-    private boolean isOperational()
-    {
-      return isOperational;
-    }
-
-
-
-    public void handleErrorResult(ErrorResultException error)
-    {
-      isOperational = false;
-    }
-
-
-
-    public void handleResult(AsynchronousConnection result)
-    {
-      isOperational = true;
-      // TODO: Notify the server is back up
-      result.close();
-    }
-
-
-
+    @Override
     public FutureResult<AsynchronousConnection> getAsynchronousConnection(
         final ResultHandler<AsynchronousConnection> resultHandler)
     {
-      ResultHandler<AsynchronousConnection> handler = new ResultHandler<AsynchronousConnection>()
+      final ResultHandler<AsynchronousConnection> handler =
+        new ResultHandler<AsynchronousConnection>()
       {
-        public void handleErrorResult(ErrorResultException error)
+        public void handleErrorResult(final ErrorResultException error)
         {
           isOperational = false;
           if (resultHandler != null)
@@ -118,16 +92,15 @@
           }
           if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
           {
-            StaticUtils.DEBUG_LOG.warning(String
-                .format("Connection factory " + factory
-                    + " is no longer operational: "
-                    + error.getMessage()));
+            StaticUtils.DEBUG_LOG
+                .warning(String.format("Connection factory " + factory
+                    + " is no longer operational: " + error.getMessage()));
           }
         }
 
 
 
-        public void handleResult(AsynchronousConnection result)
+        public void handleResult(final AsynchronousConnection result)
         {
           isOperational = true;
           if (resultHandler != null)
@@ -136,19 +109,41 @@
           }
           if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
           {
-            StaticUtils.DEBUG_LOG.warning(String
-                .format("Connection factory " + factory
-                    + " is now operational"));
+            StaticUtils.DEBUG_LOG.warning(String.format("Connection factory "
+                + factory + " is now operational"));
           }
         }
       };
       return factory.getAsynchronousConnection(handler);
     }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      isOperational = false;
+    }
+
+
+
+    public void handleResult(final AsynchronousConnection result)
+    {
+      isOperational = true;
+      // TODO: Notify the server is back up
+      result.close();
+    }
+
+
+
+    private boolean isOperational()
+    {
+      return isOperational;
+    }
   }
 
 
 
-  private class MonitorThread extends Thread
+  private final class MonitorThread extends Thread
   {
     private MonitorThread()
     {
@@ -158,11 +153,12 @@
 
 
 
+    @Override
     public void run()
     {
       while (true)
       {
-        for (MonitoredConnectionFactory f : monitoredFactories)
+        for (final MonitoredConnectionFactory f : monitoredFactories)
         {
           if (!f.isOperational
               && (f.pendingConnectFuture == null || f.pendingConnectFuture
@@ -173,8 +169,7 @@
               StaticUtils.DEBUG_LOG.finest(String
                   .format("Attempting connect on factory " + f));
             }
-            f.pendingConnectFuture = f.factory
-                .getAsynchronousConnection(f);
+            f.pendingConnectFuture = f.factory.getAsynchronousConnection(f);
           }
         }
 
@@ -182,7 +177,7 @@
         {
           sleep(10000);
         }
-        catch (InterruptedException e)
+        catch (final InterruptedException e)
         {
           // Termination requested - exit.
           break;
@@ -193,20 +188,25 @@
 
 
 
+  private final List<MonitoredConnectionFactory> monitoredFactories;
+
+
+
   /**
-   * Creates a new fail-over load balancing algorithm which will
-   * fail-over across the provided list of connection factories.
+   * Creates a new fail-over load balancing algorithm which will fail-over
+   * across the provided collection of connection factories.
    *
    * @param factories
    *          The connection factories which will be used for fail-over.
    */
-  public FailoverLoadBalancingAlgorithm(ConnectionFactory... factories)
+  public FailoverLoadBalancingAlgorithm(
+      final Collection<ConnectionFactory> factories)
   {
-    Validator.ensureNotNull((Object[]) factories);
+    Validator.ensureNotNull(factories);
 
-    monitoredFactories = new ArrayList<MonitoredConnectionFactory>(
-        factories.length);
-    for (ConnectionFactory f : factories)
+    monitoredFactories = new ArrayList<MonitoredConnectionFactory>(factories
+        .size());
+    for (final ConnectionFactory f : factories)
     {
       monitoredFactories.add(new MonitoredConnectionFactory(f));
     }
@@ -217,20 +217,19 @@
 
 
   /**
-   * Creates a new fail-over load balancing algorithm which will
-   * fail-over across the provided collection of connection factories.
+   * Creates a new fail-over load balancing algorithm which will fail-over
+   * across the provided list of connection factories.
    *
    * @param factories
    *          The connection factories which will be used for fail-over.
    */
-  public FailoverLoadBalancingAlgorithm(
-      Collection<ConnectionFactory> factories)
+  public FailoverLoadBalancingAlgorithm(final ConnectionFactory... factories)
   {
-    Validator.ensureNotNull(factories);
+    Validator.ensureNotNull((Object[]) factories);
 
     monitoredFactories = new ArrayList<MonitoredConnectionFactory>(
-        factories.size());
-    for (ConnectionFactory f : factories)
+        factories.length);
+    for (final ConnectionFactory f : factories)
     {
       monitoredFactories.add(new MonitoredConnectionFactory(f));
     }
@@ -243,7 +242,7 @@
   public ConnectionFactory getNextConnectionFactory()
       throws ErrorResultException
   {
-    for (MonitoredConnectionFactory f : monitoredFactories)
+    for (final MonitoredConnectionFactory f : monitoredFactories)
     {
       if (f.isOperational())
       {
diff --git a/sdk/src/org/opends/sdk/Filter.java b/sdk/src/org/opends/sdk/Filter.java
index 996f348..f52bbba 100644
--- a/sdk/src/org/opends/sdk/Filter.java
+++ b/sdk/src/org/opends/sdk/Filter.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
@@ -30,7 +30,9 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.util.StaticUtils.byteToHex;
+import static com.sun.opends.sdk.util.StaticUtils.getBytes;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
 
 import java.util.*;
 
@@ -42,25 +44,24 @@
 
 
 /**
- * A search filter as defined in RFC 4511. In addition this class also
- * provides support for the absolute true and absolute false filters as
- * defined in RFC 4526.
+ * A search filter as defined in RFC 4511. In addition this class also provides
+ * support for the absolute true and absolute false filters as defined in RFC
+ * 4526.
  * <p>
- * This class provides many factory methods for creating common types of
- * filter. Applications interact with a filter using
- * {@link FilterVisitor} which is applied to a filter using the
- * {@link #accept(FilterVisitor, Object)} method.
+ * This class provides many factory methods for creating common types of filter.
+ * Applications interact with a filter using {@link FilterVisitor} which is
+ * applied to a filter using the {@link #accept(FilterVisitor, Object)} method.
  * <p>
- * The RFC 4515 string representation of a filter can be generated using
- * the {@link #toString} methods and parsed using the
- * {@link #valueOf(String)} factory method.
+ * The RFC 4515 string representation of a filter can be generated using the
+ * {@link #toString} methods and parsed using the {@link #valueOf(String)}
+ * factory method.
  *
- * @see <a href="http://tools.ietf.org/html/rfc4511">RFC 4511 -
- *      Lightweight Directory Access Protocol (LDAP): The Protocol </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4511">RFC 4511 - Lightweight
+ *      Directory Access Protocol (LDAP): The Protocol </a>
  * @see <a href="http://tools.ietf.org/html/rfc4515">RFC 4515 - String
  *      Representation of Search Filters </a>
- * @see <a href="http://tools.ietf.org/html/rfc4526">RFC 4526 - Absolute
- *      True and False Filters </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4526">RFC 4526 - Absolute True
+ *      and False Filters </a>
  */
 public final class Filter
 {
@@ -70,7 +71,7 @@
 
 
 
-    public AndImpl(List<Filter> subFilters)
+    public AndImpl(final List<Filter> subFilters)
     {
       this.subFilters = subFilters;
     }
@@ -78,7 +79,7 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
       return v.visitAndFilter(p, subFilters);
     }
@@ -96,8 +97,8 @@
 
 
 
-    public ApproxMatchImpl(String attributeDescription,
-        ByteString assertionValue)
+    public ApproxMatchImpl(final String attributeDescription,
+        final ByteString assertionValue)
     {
       this.attributeDescription = attributeDescription;
       this.assertionValue = assertionValue;
@@ -106,10 +107,9 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
-      return v.visitApproxMatchFilter(p, attributeDescription,
-          assertionValue);
+      return v.visitApproxMatchFilter(p, attributeDescription, assertionValue);
     }
 
   }
@@ -125,8 +125,8 @@
 
 
 
-    public EqualityMatchImpl(String attributeDescription,
-        ByteString assertionValue)
+    public EqualityMatchImpl(final String attributeDescription,
+        final ByteString assertionValue)
     {
       this.attributeDescription = attributeDescription;
       this.assertionValue = assertionValue;
@@ -135,10 +135,10 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
-      return v.visitEqualityMatchFilter(p, attributeDescription,
-          assertionValue);
+      return v
+          .visitEqualityMatchFilter(p, attributeDescription, assertionValue);
     }
 
   }
@@ -157,9 +157,9 @@
 
 
 
-    public ExtensibleMatchImpl(String matchingRule,
-        String attributeDescription, ByteString matchValue,
-        boolean dnAttributes)
+    public ExtensibleMatchImpl(final String matchingRule,
+        final String attributeDescription, final ByteString matchValue,
+        final boolean dnAttributes)
     {
       this.matchingRule = matchingRule;
       this.attributeDescription = attributeDescription;
@@ -170,7 +170,7 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
       return v.visitExtensibleMatchFilter(p, matchingRule,
           attributeDescription, matchValue, dnAttributes);
@@ -189,8 +189,8 @@
 
 
 
-    public GreaterOrEqualImpl(String attributeDescription,
-        ByteString assertionValue)
+    public GreaterOrEqualImpl(final String attributeDescription,
+        final ByteString assertionValue)
     {
       this.attributeDescription = attributeDescription;
       this.assertionValue = assertionValue;
@@ -199,7 +199,7 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
       return v.visitGreaterOrEqualFilter(p, attributeDescription,
           assertionValue);
@@ -232,8 +232,8 @@
 
 
 
-    public LessOrEqualImpl(String attributeDescription,
-        ByteString assertionValue)
+    public LessOrEqualImpl(final String attributeDescription,
+        final ByteString assertionValue)
     {
       this.attributeDescription = attributeDescription;
       this.assertionValue = assertionValue;
@@ -242,10 +242,9 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
-      return v.visitLessOrEqualFilter(p, attributeDescription,
-          assertionValue);
+      return v.visitLessOrEqualFilter(p, attributeDescription, assertionValue);
     }
 
   }
@@ -258,7 +257,7 @@
 
 
 
-    public NotImpl(Filter subFilter)
+    public NotImpl(final Filter subFilter)
     {
       this.subFilter = subFilter;
     }
@@ -266,7 +265,7 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
       return v.visitNotFilter(p, subFilter);
     }
@@ -281,7 +280,7 @@
 
 
 
-    public OrImpl(List<Filter> subFilters)
+    public OrImpl(final List<Filter> subFilters)
     {
       this.subFilters = subFilters;
     }
@@ -289,7 +288,7 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
       return v.visitOrFilter(p, subFilters);
     }
@@ -305,7 +304,7 @@
 
 
 
-    public PresentImpl(String attributeDescription)
+    public PresentImpl(final String attributeDescription)
     {
       this.attributeDescription = attributeDescription;
     }
@@ -313,7 +312,7 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
       return v.visitPresentFilter(p, attributeDescription);
     }
@@ -335,9 +334,9 @@
 
 
 
-    public SubstringsImpl(String attributeDescription,
-        ByteString initialString, List<ByteString> anyStrings,
-        ByteString finalString)
+    public SubstringsImpl(final String attributeDescription,
+        final ByteString initialString, final List<ByteString> anyStrings,
+        final ByteString finalString)
     {
       this.attributeDescription = attributeDescription;
       this.initialString = initialString;
@@ -349,10 +348,10 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
-      return v.visitSubstringsFilter(p, attributeDescription,
-          initialString, anyStrings, finalString);
+      return v.visitSubstringsFilter(p, attributeDescription, initialString,
+          anyStrings, finalString);
     }
 
   }
@@ -368,7 +367,7 @@
 
 
 
-    public UnrecognizedImpl(byte filterTag, ByteString filterBytes)
+    public UnrecognizedImpl(final byte filterTag, final ByteString filterBytes)
     {
       this.filterTag = filterTag;
       this.filterBytes = filterBytes;
@@ -377,7 +376,7 @@
 
 
     @Override
-    public <R, P> R accept(FilterVisitor<R, P> v, P p)
+    public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
     {
       return v.visitUnrecognizedFilter(p, filterTag, filterBytes);
     }
@@ -394,14 +393,15 @@
   private static final Filter OBJECT_CLASS_PRESENT = new Filter(
       new PresentImpl("objectClass"));
 
-  private static final FilterVisitor<StringBuilder, StringBuilder> TO_STRING_VISITOR = new FilterVisitor<StringBuilder, StringBuilder>()
+  private static final FilterVisitor<StringBuilder, StringBuilder>
+    TO_STRING_VISITOR = new FilterVisitor<StringBuilder, StringBuilder>()
   {
 
-    public StringBuilder visitAndFilter(StringBuilder builder,
-        List<Filter> subFilters)
+    public StringBuilder visitAndFilter(final StringBuilder builder,
+        final List<Filter> subFilters)
     {
       builder.append("(&");
-      for (Filter subFilter : subFilters)
+      for (final Filter subFilter : subFilters)
       {
         subFilter.accept(this, builder);
       }
@@ -411,8 +411,8 @@
 
 
 
-    public StringBuilder visitApproxMatchFilter(StringBuilder builder,
-        String attributeDescription, ByteString assertionValue)
+    public StringBuilder visitApproxMatchFilter(final StringBuilder builder,
+        final String attributeDescription, final ByteString assertionValue)
     {
       builder.append('(');
       builder.append(attributeDescription);
@@ -424,9 +424,8 @@
 
 
 
-    public StringBuilder visitEqualityMatchFilter(
-        StringBuilder builder, String attributeDescription,
-        ByteString assertionValue)
+    public StringBuilder visitEqualityMatchFilter(final StringBuilder builder,
+        final String attributeDescription, final ByteString assertionValue)
     {
       builder.append('(');
       builder.append(attributeDescription);
@@ -439,9 +438,9 @@
 
 
     public StringBuilder visitExtensibleMatchFilter(
-        StringBuilder builder, String matchingRule,
-        String attributeDescription, ByteString assertionValue,
-        boolean dnAttributes)
+        final StringBuilder builder, final String matchingRule,
+        final String attributeDescription, final ByteString assertionValue,
+        final boolean dnAttributes)
     {
       builder.append('(');
 
@@ -469,9 +468,8 @@
 
 
 
-    public StringBuilder visitGreaterOrEqualFilter(
-        StringBuilder builder, String attributeDescription,
-        ByteString assertionValue)
+    public StringBuilder visitGreaterOrEqualFilter(final StringBuilder builder,
+        final String attributeDescription, final ByteString assertionValue)
     {
       builder.append('(');
       builder.append(attributeDescription);
@@ -483,8 +481,8 @@
 
 
 
-    public StringBuilder visitLessOrEqualFilter(StringBuilder builder,
-        String attributeDescription, ByteString assertionValue)
+    public StringBuilder visitLessOrEqualFilter(final StringBuilder builder,
+        final String attributeDescription, final ByteString assertionValue)
     {
       builder.append('(');
       builder.append(attributeDescription);
@@ -496,8 +494,8 @@
 
 
 
-    public StringBuilder visitNotFilter(StringBuilder builder,
-        Filter subFilter)
+    public StringBuilder visitNotFilter(final StringBuilder builder,
+        final Filter subFilter)
     {
       builder.append("(|");
       subFilter.accept(this, builder);
@@ -507,11 +505,11 @@
 
 
 
-    public StringBuilder visitOrFilter(StringBuilder builder,
-        List<Filter> subFilters)
+    public StringBuilder visitOrFilter(final StringBuilder builder,
+        final List<Filter> subFilters)
     {
       builder.append("(|");
-      for (Filter subFilter : subFilters)
+      for (final Filter subFilter : subFilters)
       {
         subFilter.accept(this, builder);
       }
@@ -521,8 +519,8 @@
 
 
 
-    public StringBuilder visitPresentFilter(StringBuilder builder,
-        String attributeDescription)
+    public StringBuilder visitPresentFilter(final StringBuilder builder,
+        final String attributeDescription)
     {
       builder.append('(');
       builder.append(attributeDescription);
@@ -532,9 +530,9 @@
 
 
 
-    public StringBuilder visitSubstringsFilter(StringBuilder builder,
-        String attributeDescription, ByteString initialSubstring,
-        List<ByteString> anySubstrings, ByteString finalSubstring)
+    public StringBuilder visitSubstringsFilter(final StringBuilder builder,
+        final String attributeDescription, final ByteString initialSubstring,
+        final List<ByteString> anySubstrings, final ByteString finalSubstring)
     {
       builder.append('(');
       builder.append(attributeDescription);
@@ -543,7 +541,7 @@
       {
         valueToFilterString(builder, initialSubstring);
       }
-      for (ByteString anySubstring : anySubstrings)
+      for (final ByteString anySubstring : anySubstrings)
       {
         builder.append('*');
         valueToFilterString(builder, anySubstring);
@@ -559,8 +557,8 @@
 
 
 
-    public StringBuilder visitUnrecognizedFilter(StringBuilder builder,
-        byte filterTag, ByteString filterBytes)
+    public StringBuilder visitUnrecognizedFilter(final StringBuilder builder,
+        final byte filterTag, final ByteString filterBytes)
     {
       // Fake up a representation.
       builder.append('(');
@@ -579,9 +577,8 @@
 
 
   /**
-   * Returns the {@code absolute false} filter as defined in RFC 4526
-   * which is comprised of an {@code or} filter containing zero
-   * components.
+   * Returns the {@code absolute false} filter as defined in RFC 4526 which is
+   * comprised of an {@code or} filter containing zero components.
    *
    * @return The absolute false filter.
    * @see <a href="http://tools.ietf.org/html/rfc4526">RFC 4526</a>
@@ -594,9 +591,8 @@
 
 
   /**
-   * Returns the {@code absolute true} filter as defined in RFC 4526
-   * which is comprised of an {@code and} filter containing zero
-   * components.
+   * Returns the {@code absolute true} filter as defined in RFC 4526 which is
+   * comprised of an {@code and} filter containing zero components.
    *
    * @return The absolute true filter.
    * @see <a href="http://tools.ietf.org/html/rfc4526">RFC 4526</a>
@@ -609,8 +605,7 @@
 
 
   /**
-   * Returns the {@code objectClass} presence filter {@code
-   * (objectClass=*)}.
+   * Returns the {@code objectClass} presence filter {@code (objectClass=*)}.
    * <p>
    * A call to this method is equivalent to but more efficient than the
    * following code:
@@ -619,8 +614,7 @@
    * Filter.present(&quot;objectClass&quot;);
    * </pre>
    *
-   * @return The {@code objectClass} presence filter {@code
-   *         (objectClass=*)}.
+   * @return The {@code objectClass} presence filter {@code (objectClass=*)}.
    */
   public static Filter getObjectClassPresentFilter()
   {
@@ -630,18 +624,16 @@
 
 
   /**
-   * Creates a new {@code and} filter using the provided list of
-   * sub-filters.
+   * Creates a new {@code and} filter using the provided list of sub-filters.
    * <p>
-   * Creating a new {@code and} filter with a {@code null} or empty list
-   * of sub-filters is equivalent to calling
-   * {@link #getAbsoluteTrueFilter()}.
+   * Creating a new {@code and} filter with a {@code null} or empty list of
+   * sub-filters is equivalent to calling {@link #getAbsoluteTrueFilter()}.
    *
    * @param subFilters
    *          The list of sub-filters, may be empty or {@code null}.
    * @return The newly created {@code and} filter.
    */
-  public static Filter newAndFilter(Collection<Filter> subFilters)
+  public static Filter newAndFilter(final Collection<Filter> subFilters)
   {
     if (subFilters == null || subFilters.isEmpty())
     {
@@ -650,16 +642,15 @@
     }
     else if (subFilters.size() == 1)
     {
-      Filter subFilter = subFilters.iterator().next();
+      final Filter subFilter = subFilters.iterator().next();
       Validator.ensureNotNull(subFilter);
-      return new Filter(new AndImpl(Collections
-          .singletonList(subFilter)));
+      return new Filter(new AndImpl(Collections.singletonList(subFilter)));
     }
     else
     {
-      List<Filter> subFiltersList = new ArrayList<Filter>(subFilters
+      final List<Filter> subFiltersList = new ArrayList<Filter>(subFilters
           .size());
-      for (Filter subFilter : subFilters)
+      for (final Filter subFilter : subFilters)
       {
         Validator.ensureNotNull(subFilter);
         subFiltersList.add(subFilter);
@@ -672,18 +663,16 @@
 
 
   /**
-   * Creates a new {@code and} filter using the provided list of
-   * sub-filters.
+   * Creates a new {@code and} filter using the provided list of sub-filters.
    * <p>
-   * Creating a new {@code and} filter with a {@code null} or empty list
-   * of sub-filters is equivalent to calling
-   * {@link #getAbsoluteTrueFilter()}.
+   * Creating a new {@code and} filter with a {@code null} or empty list of
+   * sub-filters is equivalent to calling {@link #getAbsoluteTrueFilter()}.
    *
    * @param subFilters
    *          The list of sub-filters, may be empty or {@code null}.
    * @return The newly created {@code and} filter.
    */
-  public static Filter newAndFilter(Filter... subFilters)
+  public static Filter newAndFilter(final Filter... subFilters)
   {
     if ((subFilters == null) || (subFilters.length == 0))
     {
@@ -693,14 +682,13 @@
     else if (subFilters.length == 1)
     {
       Validator.ensureNotNull(subFilters[0]);
-      return new Filter(new AndImpl(Collections
-          .singletonList(subFilters[0])));
+      return new Filter(new AndImpl(Collections.singletonList(subFilters[0])));
     }
     else
     {
-      List<Filter> subFiltersList = new ArrayList<Filter>(
+      final List<Filter> subFiltersList = new ArrayList<Filter>(
           subFilters.length);
-      for (Filter subFilter : subFilters)
+      for (final Filter subFilter : subFilters)
       {
         Validator.ensureNotNull(subFilter);
         subFiltersList.add(subFilter);
@@ -713,8 +701,8 @@
 
 
   /**
-   * Creates a new {@code approximate match} filter using the provided
-   * attribute description and assertion value.
+   * Creates a new {@code approximate match} filter using the provided attribute
+   * description and assertion value.
    *
    * @param attributeDescription
    *          The attribute description.
@@ -722,23 +710,21 @@
    *          The assertion value.
    * @return The newly created {@code approximate match} filter.
    */
-  public static Filter newApproxMatchFilter(
-      String attributeDescription, ByteString assertionValue)
+  public static Filter newApproxMatchFilter(final String attributeDescription,
+      final ByteString assertionValue)
   {
     Validator.ensureNotNull(attributeDescription, assertionValue);
-    return new Filter(new ApproxMatchImpl(attributeDescription,
-        assertionValue));
+    return new Filter(new ApproxMatchImpl(attributeDescription, assertionValue));
   }
 
 
 
   /**
-   * Creates a new {@code approximate match} filter using the provided
-   * attribute description and assertion value.
+   * Creates a new {@code approximate match} filter using the provided attribute
+   * description and assertion value.
    * <p>
-   * If {@code assertionValue} is not an instance of {@code ByteString}
-   * then it will be converted using the
-   * {@link ByteString#valueOf(Object)} method.
+   * If {@code assertionValue} is not an instance of {@code ByteString} then it
+   * will be converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param attributeDescription
    *          The attribute description.
@@ -746,19 +732,19 @@
    *          The assertion value.
    * @return The newly created {@code approximate match} filter.
    */
-  public static Filter newApproxMatchFilter(
-      String attributeDescription, Object assertionValue)
+  public static Filter newApproxMatchFilter(final String attributeDescription,
+      final Object assertionValue)
   {
     Validator.ensureNotNull(attributeDescription, assertionValue);
-    return new Filter(new ApproxMatchImpl(attributeDescription,
-        ByteString.valueOf(assertionValue)));
+    return new Filter(new ApproxMatchImpl(attributeDescription, ByteString
+        .valueOf(assertionValue)));
   }
 
 
 
   /**
-   * Creates a new {@code equality match} filter using the provided
-   * attribute description and assertion value.
+   * Creates a new {@code equality match} filter using the provided attribute
+   * description and assertion value.
    *
    * @param attributeDescription
    *          The attribute description.
@@ -767,7 +753,7 @@
    * @return The newly created {@code equality match} filter.
    */
   public static Filter newEqualityMatchFilter(
-      String attributeDescription, ByteString assertionValue)
+      final String attributeDescription, final ByteString assertionValue)
   {
     Validator.ensureNotNull(attributeDescription, assertionValue);
     return new Filter(new EqualityMatchImpl(attributeDescription,
@@ -777,12 +763,11 @@
 
 
   /**
-   * Creates a new {@code equality match} filter using the provided
-   * attribute description and assertion value.
+   * Creates a new {@code equality match} filter using the provided attribute
+   * description and assertion value.
    * <p>
-   * If {@code assertionValue} is not an instance of {@code ByteString}
-   * then it will be converted using the
-   * {@link ByteString#valueOf(Object)} method.
+   * If {@code assertionValue} is not an instance of {@code ByteString} then it
+   * will be converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param attributeDescription
    *          The attribute description.
@@ -791,11 +776,11 @@
    * @return The newly created {@code equality match} filter.
    */
   public static Filter newEqualityMatchFilter(
-      String attributeDescription, Object assertionValue)
+      final String attributeDescription, final Object assertionValue)
   {
     Validator.ensureNotNull(attributeDescription, assertionValue);
-    return new Filter(new EqualityMatchImpl(attributeDescription,
-        ByteString.valueOf(assertionValue)));
+    return new Filter(new EqualityMatchImpl(attributeDescription, ByteString
+        .valueOf(assertionValue)));
   }
 
 
@@ -815,9 +800,9 @@
    *          Indicates whether DN matching should be performed.
    * @return The newly created {@code extensible match} filter.
    */
-  public static Filter newExtensibleMatchFilter(String matchingRule,
-      String attributeDescription, ByteString assertionValue,
-      boolean dnAttributes)
+  public static Filter newExtensibleMatchFilter(final String matchingRule,
+      final String attributeDescription, final ByteString assertionValue,
+      final boolean dnAttributes)
   {
     Validator.ensureTrue((matchingRule != null)
         || (attributeDescription != null), "matchingRule and/or "
@@ -832,9 +817,8 @@
   /**
    * Creates a new {@code extensible match} filter.
    * <p>
-   * If {@code assertionValue} is not an instance of {@code ByteString}
-   * then it will be converted using the
-   * {@link ByteString#valueOf(Object)} method.
+   * If {@code assertionValue} is not an instance of {@code ByteString} then it
+   * will be converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param matchingRule
    *          The matching rule name, may be {@code null} if {@code
@@ -848,24 +832,23 @@
    *          Indicates whether DN matching should be performed.
    * @return The newly created {@code extensible match} filter.
    */
-  public static Filter newExtensibleMatchFilter(String matchingRule,
-      String attributeDescription, Object assertionValue,
-      boolean dnAttributes)
+  public static Filter newExtensibleMatchFilter(final String matchingRule,
+      final String attributeDescription, final Object assertionValue,
+      final boolean dnAttributes)
   {
     Validator.ensureTrue((matchingRule != null)
         || (attributeDescription != null), "matchingRule and/or "
         + "attributeDescription must not be null");
     Validator.ensureNotNull(assertionValue);
     return new Filter(new ExtensibleMatchImpl(matchingRule,
-        attributeDescription, ByteString.valueOf(assertionValue),
-        dnAttributes));
+        attributeDescription, ByteString.valueOf(assertionValue), dnAttributes));
   }
 
 
 
   /**
-   * Creates a new {@code greater or equal} filter using the provided
-   * attribute description and assertion value.
+   * Creates a new {@code greater or equal} filter using the provided attribute
+   * description and assertion value.
    *
    * @param attributeDescription
    *          The attribute description.
@@ -874,7 +857,7 @@
    * @return The newly created {@code greater or equal} filter.
    */
   public static Filter newGreaterOrEqualFilter(
-      String attributeDescription, ByteString assertionValue)
+      final String attributeDescription, final ByteString assertionValue)
   {
     Validator.ensureNotNull(attributeDescription, assertionValue);
     return new Filter(new GreaterOrEqualImpl(attributeDescription,
@@ -884,12 +867,11 @@
 
 
   /**
-   * Creates a new {@code greater or equal} filter using the provided
-   * attribute description and assertion value.
+   * Creates a new {@code greater or equal} filter using the provided attribute
+   * description and assertion value.
    * <p>
-   * If {@code assertionValue} is not an instance of {@code ByteString}
-   * then it will be converted using the
-   * {@link ByteString#valueOf(Object)} method.
+   * If {@code assertionValue} is not an instance of {@code ByteString} then it
+   * will be converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param attributeDescription
    *          The attribute description.
@@ -898,18 +880,18 @@
    * @return The newly created {@code greater or equal} filter.
    */
   public static Filter newGreaterOrEqualFilter(
-      String attributeDescription, Object assertionValue)
+      final String attributeDescription, final Object assertionValue)
   {
     Validator.ensureNotNull(attributeDescription, assertionValue);
-    return new Filter(new GreaterOrEqualImpl(attributeDescription,
-        ByteString.valueOf(assertionValue)));
+    return new Filter(new GreaterOrEqualImpl(attributeDescription, ByteString
+        .valueOf(assertionValue)));
   }
 
 
 
   /**
-   * Creates a new {@code less or equal} filter using the provided
-   * attribute description and assertion value.
+   * Creates a new {@code less or equal} filter using the provided attribute
+   * description and assertion value.
    *
    * @param attributeDescription
    *          The attribute description.
@@ -917,23 +899,21 @@
    *          The assertion value.
    * @return The newly created {@code less or equal} filter.
    */
-  public static Filter newLessOrEqualFilter(
-      String attributeDescription, ByteString assertionValue)
+  public static Filter newLessOrEqualFilter(final String attributeDescription,
+      final ByteString assertionValue)
   {
     Validator.ensureNotNull(attributeDescription, assertionValue);
-    return new Filter(new LessOrEqualImpl(attributeDescription,
-        assertionValue));
+    return new Filter(new LessOrEqualImpl(attributeDescription, assertionValue));
   }
 
 
 
   /**
-   * Creates a new {@code less or equal} filter using the provided
-   * attribute description and assertion value.
+   * Creates a new {@code less or equal} filter using the provided attribute
+   * description and assertion value.
    * <p>
-   * If {@code assertionValue} is not an instance of {@code ByteString}
-   * then it will be converted using the
-   * {@link ByteString#valueOf(Object)} method.
+   * If {@code assertionValue} is not an instance of {@code ByteString} then it
+   * will be converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param attributeDescription
    *          The attribute description.
@@ -941,12 +921,12 @@
    *          The assertion value.
    * @return The newly created {@code less or equal} filter.
    */
-  public static Filter newLessOrEqualFilter(
-      String attributeDescription, Object assertionValue)
+  public static Filter newLessOrEqualFilter(final String attributeDescription,
+      final Object assertionValue)
   {
     Validator.ensureNotNull(attributeDescription, assertionValue);
-    return new Filter(new LessOrEqualImpl(attributeDescription,
-        ByteString.valueOf(assertionValue)));
+    return new Filter(new LessOrEqualImpl(attributeDescription, ByteString
+        .valueOf(assertionValue)));
   }
 
 
@@ -958,7 +938,7 @@
    *          The sub-filter.
    * @return The newly created {@code not} filter.
    */
-  public static Filter newNotFilter(Filter subFilter)
+  public static Filter newNotFilter(final Filter subFilter)
   {
     Validator.ensureNotNull(subFilter);
     return new Filter(new NotImpl(subFilter));
@@ -967,18 +947,16 @@
 
 
   /**
-   * Creates a new {@code or} filter using the provided list of
-   * sub-filters.
+   * Creates a new {@code or} filter using the provided list of sub-filters.
    * <p>
-   * Creating a new {@code or} filter with a {@code null} or empty list
-   * of sub-filters is equivalent to calling
-   * {@link #getAbsoluteFalseFilter()}.
+   * Creating a new {@code or} filter with a {@code null} or empty list of
+   * sub-filters is equivalent to calling {@link #getAbsoluteFalseFilter()}.
    *
    * @param subFilters
    *          The list of sub-filters, may be empty or {@code null}.
    * @return The newly created {@code or} filter.
    */
-  public static Filter newOrFilter(Collection<Filter> subFilters)
+  public static Filter newOrFilter(final Collection<Filter> subFilters)
   {
     if (subFilters == null || subFilters.isEmpty())
     {
@@ -987,40 +965,37 @@
     }
     else if (subFilters.size() == 1)
     {
-      Filter subFilter = subFilters.iterator().next();
+      final Filter subFilter = subFilters.iterator().next();
       Validator.ensureNotNull(subFilter);
-      return new Filter(
-          new OrImpl(Collections.singletonList(subFilter)));
+      return new Filter(new OrImpl(Collections.singletonList(subFilter)));
     }
     else
     {
-      List<Filter> subFiltersList = new ArrayList<Filter>(subFilters
+      final List<Filter> subFiltersList = new ArrayList<Filter>(subFilters
           .size());
-      for (Filter subFilter : subFilters)
+      for (final Filter subFilter : subFilters)
       {
         Validator.ensureNotNull(subFilter);
         subFiltersList.add(subFilter);
       }
-      return new Filter(new OrImpl(Collections
-          .unmodifiableList(subFiltersList)));
+      return new Filter(
+          new OrImpl(Collections.unmodifiableList(subFiltersList)));
     }
   }
 
 
 
   /**
-   * Creates a new {@code or} filter using the provided list of
-   * sub-filters.
+   * Creates a new {@code or} filter using the provided list of sub-filters.
    * <p>
-   * Creating a new {@code or} filter with a {@code null} or empty list
-   * of sub-filters is equivalent to calling
-   * {@link #getAbsoluteFalseFilter()}.
+   * Creating a new {@code or} filter with a {@code null} or empty list of
+   * sub-filters is equivalent to calling {@link #getAbsoluteFalseFilter()}.
    *
    * @param subFilters
    *          The list of sub-filters, may be empty or {@code null}.
    * @return The newly created {@code or} filter.
    */
-  public static Filter newOrFilter(Filter... subFilters)
+  public static Filter newOrFilter(final Filter... subFilters)
   {
     if ((subFilters == null) || (subFilters.length == 0))
     {
@@ -1030,20 +1005,19 @@
     else if (subFilters.length == 1)
     {
       Validator.ensureNotNull(subFilters[0]);
-      return new Filter(new OrImpl(Collections
-          .singletonList(subFilters[0])));
+      return new Filter(new OrImpl(Collections.singletonList(subFilters[0])));
     }
     else
     {
-      List<Filter> subFiltersList = new ArrayList<Filter>(
+      final List<Filter> subFiltersList = new ArrayList<Filter>(
           subFilters.length);
-      for (Filter subFilter : subFilters)
+      for (final Filter subFilter : subFilters)
       {
         Validator.ensureNotNull(subFilter);
         subFiltersList.add(subFilter);
       }
-      return new Filter(new OrImpl(Collections
-          .unmodifiableList(subFiltersList)));
+      return new Filter(
+          new OrImpl(Collections.unmodifiableList(subFiltersList)));
     }
   }
 
@@ -1057,7 +1031,7 @@
    *          The attribute description.
    * @return The newly created {@code present} filter.
    */
-  public static Filter newPresentFilter(String attributeDescription)
+  public static Filter newPresentFilter(final String attributeDescription)
   {
     Validator.ensureNotNull(attributeDescription);
     if (toLowerCase(attributeDescription).equals("objectclass"))
@@ -1070,36 +1044,34 @@
 
 
   /**
-   * Creates a new {@code substrings} filter using the provided
-   * attribute description, {@code initial}, {@code final}, and {@code
-   * any} sub-strings.
+   * Creates a new {@code substrings} filter using the provided attribute
+   * description, {@code initial}, {@code final}, and {@code any} sub-strings.
    *
    * @param attributeDescription
    *          The attribute description.
    * @param initialSubstring
-   *          The initial sub-string, may be {@code null} if either
-   *          {@code finalSubstring} or {@code anySubstrings} are
-   *          specified.
+   *          The initial sub-string, may be {@code null} if either {@code
+   *          finalSubstring} or {@code anySubstrings} are specified.
    * @param anySubstrings
-   *          The final sub-string, may be {@code null} or empty if
-   *          either {@code finalSubstring} or {@code initialSubstring}
-   *          are specified.
+   *          The final sub-string, may be {@code null} or empty if either
+   *          {@code finalSubstring} or {@code initialSubstring} are specified.
    * @param finalSubstring
-   *          The final sub-string, may be {@code null}, may be {@code
-   *          null} if either {@code initialSubstring} or {@code
-   *          anySubstrings} are specified.
+   *          The final sub-string, may be {@code null}, may be {@code null} if
+   *          either {@code initialSubstring} or {@code anySubstrings} are
+   *          specified.
    * @return The newly created {@code substrings} filter.
    */
-  public static Filter newSubstringsFilter(String attributeDescription,
-      ByteString initialSubstring,
-      Collection<ByteString> anySubstrings, ByteString finalSubstring)
+  public static Filter newSubstringsFilter(final String attributeDescription,
+      final ByteString initialSubstring,
+      final Collection<ByteString> anySubstrings,
+      final ByteString finalSubstring)
   {
     Validator.ensureNotNull(attributeDescription);
-    Validator.ensureTrue((initialSubstring != null)
-        || (finalSubstring != null)
-        || ((anySubstrings != null) && (anySubstrings.size() > 0)),
-        "at least one substring (initial, any or final)"
-            + " must be specified");
+    Validator
+        .ensureTrue((initialSubstring != null) || (finalSubstring != null)
+            || ((anySubstrings != null) && (anySubstrings.size() > 0)),
+            "at least one substring (initial, any or final)"
+                + " must be specified");
 
     List<ByteString> anySubstringList;
     if ((anySubstrings == null) || (anySubstrings.size() == 0))
@@ -1108,14 +1080,14 @@
     }
     else if (anySubstrings.size() == 1)
     {
-      ByteString anySubstring = anySubstrings.iterator().next();
+      final ByteString anySubstring = anySubstrings.iterator().next();
       Validator.ensureNotNull(anySubstring);
       anySubstringList = Collections.singletonList(anySubstring);
     }
     else
     {
       anySubstringList = new ArrayList<ByteString>(anySubstrings.size());
-      for (ByteString anySubstring : anySubstrings)
+      for (final ByteString anySubstring : anySubstrings)
       {
         Validator.ensureNotNull(anySubstring);
 
@@ -1131,39 +1103,36 @@
 
 
   /**
-   * Creates a new {@code substrings} filter using the provided
-   * attribute description, {@code initial}, {@code final}, and {@code
-   * any} sub-strings.
+   * Creates a new {@code substrings} filter using the provided attribute
+   * description, {@code initial}, {@code final}, and {@code any} sub-strings.
    * <p>
-   * Any substrings which are not instances of {@code ByteString} will
-   * be converted using the {@link ByteString#valueOf(Object)} method.
+   * Any substrings which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param attributeDescription
    *          The attribute description.
    * @param initialSubstring
-   *          The initial sub-string, may be {@code null} if either
-   *          {@code finalSubstring} or {@code anySubstrings} are
-   *          specified.
+   *          The initial sub-string, may be {@code null} if either {@code
+   *          finalSubstring} or {@code anySubstrings} are specified.
    * @param anySubstrings
-   *          The final sub-string, may be {@code null} or empty if
-   *          either {@code finalSubstring} or {@code initialSubstring}
-   *          are specified.
+   *          The final sub-string, may be {@code null} or empty if either
+   *          {@code finalSubstring} or {@code initialSubstring} are specified.
    * @param finalSubstring
-   *          The final sub-string, may be {@code null}, may be {@code
-   *          null} if either {@code initialSubstring} or {@code
-   *          anySubstrings} are specified.
+   *          The final sub-string, may be {@code null}, may be {@code null} if
+   *          either {@code initialSubstring} or {@code anySubstrings} are
+   *          specified.
    * @return The newly created {@code substrings} filter.
    */
-  public static Filter newSubstringsFilter(String attributeDescription,
-      Object initialSubstring, Collection<?> anySubstrings,
-      Object finalSubstring)
+  public static Filter newSubstringsFilter(final String attributeDescription,
+      final Object initialSubstring, final Collection<?> anySubstrings,
+      final Object finalSubstring)
   {
     Validator.ensureNotNull(attributeDescription);
-    Validator.ensureTrue((initialSubstring != null)
-        || (finalSubstring != null)
-        || ((anySubstrings != null) && (anySubstrings.size() > 0)),
-        "at least one substring (initial, any or final)"
-            + " must be specified");
+    Validator
+        .ensureTrue((initialSubstring != null) || (finalSubstring != null)
+            || ((anySubstrings != null) && (anySubstrings.size() > 0)),
+            "at least one substring (initial, any or final)"
+                + " must be specified");
 
     List<ByteString> anySubstringList;
     if ((anySubstrings == null) || (anySubstrings.size() == 0))
@@ -1172,7 +1141,7 @@
     }
     else if (anySubstrings.size() == 1)
     {
-      Object anySubstring = anySubstrings.iterator().next();
+      final Object anySubstring = anySubstrings.iterator().next();
       Validator.ensureNotNull(anySubstring);
       anySubstringList = Collections.singletonList(ByteString
           .valueOf(anySubstring));
@@ -1180,7 +1149,7 @@
     else
     {
       anySubstringList = new ArrayList<ByteString>(anySubstrings.size());
-      for (Object anySubstring : anySubstrings)
+      for (final Object anySubstring : anySubstrings)
       {
         Validator.ensureNotNull(anySubstring);
 
@@ -1190,16 +1159,17 @@
     }
 
     return new Filter(new SubstringsImpl(attributeDescription,
-        ByteString.valueOf(initialSubstring), anySubstringList,
-        ByteString.valueOf(finalSubstring)));
+        initialSubstring != null ? ByteString.valueOf(initialSubstring) : null,
+        anySubstringList, finalSubstring != null ? ByteString
+            .valueOf(finalSubstring) : null));
   }
 
 
 
   /**
-   * Creates a new {@code unrecognized} filter using the provided ASN1
-   * filter tag and content. This type of filter should be used for
-   * filters which are not part of the standard filter definition.
+   * Creates a new {@code unrecognized} filter using the provided ASN1 filter
+   * tag and content. This type of filter should be used for filters which are
+   * not part of the standard filter definition.
    *
    * @param filterTag
    *          The ASN.1 tag.
@@ -1207,8 +1177,8 @@
    *          The filter content.
    * @return The newly created {@code unrecognized} filter.
    */
-  public static Filter newUnrecognizedFilter(byte filterTag,
-      ByteString filterBytes)
+  public static Filter newUnrecognizedFilter(final byte filterTag,
+      final ByteString filterBytes)
   {
     Validator.ensureNotNull(filterBytes);
     return new Filter(new UnrecognizedImpl(filterTag, filterBytes));
@@ -1217,70 +1187,339 @@
 
 
   /**
-   * Parses the provided LDAP string representation of a filter as a
-   * {@code Filter}.
+   * Parses the provided LDAP string representation of a filter as a {@code
+   * Filter}.
    *
    * @param string
    *          The LDAP string representation of a filter.
    * @return The parsed {@code Filter}.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code string} is not a valid LDAP string
-   *           representation of a filter.
+   *           If {@code string} is not a valid LDAP string representation of a
+   *           filter.
    */
-  public static Filter valueOf(String string)
+  public static Filter valueOf(final String string)
       throws LocalizedIllegalArgumentException
   {
     Validator.ensureNotNull(string);
 
     // If the filter is enclosed in a pair of single quotes it
     // is invalid (issue #1024).
-    if ((string.length() > 1) && string.startsWith("'")
-        && string.endsWith("'"))
+    if ((string.length() > 1) && string.startsWith("'") && string.endsWith("'"))
     {
-      LocalizableMessage message = ERR_LDAP_FILTER_ENCLOSED_IN_APOSTROPHES
+      final LocalizableMessage message = ERR_LDAP_FILTER_ENCLOSED_IN_APOSTROPHES
           .get(string);
       throw new LocalizedIllegalArgumentException(message);
     }
 
-    if (string.startsWith("("))
+    try
     {
-      if (string.endsWith(")"))
+      if (string.startsWith("("))
       {
-        return valueOf0(string, 1, string.length() - 1);
+        if (string.endsWith(")"))
+        {
+          return valueOf0(string, 1, string.length() - 1);
+        }
+        else
+        {
+          final LocalizableMessage message = ERR_LDAP_FILTER_MISMATCHED_PARENTHESES
+              .get(string, 1, string.length());
+          throw new LocalizedIllegalArgumentException(message);
+        }
       }
       else
       {
-        LocalizableMessage message = ERR_LDAP_FILTER_MISMATCHED_PARENTHESES
-            .get(string, 1, string.length());
-        throw new LocalizedIllegalArgumentException(message);
+        // We tolerate the top level filter component not being surrounded
+        // by parentheses.
+        return valueOf0(string, 0, string.length());
       }
     }
-    else
+    catch (final LocalizedIllegalArgumentException liae)
     {
-      // We tolerate the top level filter component not being surrounded
-      // by parentheses.
-      return valueOf0(string, 0, string.length());
+      throw liae;
+    }
+    catch (final Exception e)
+    {
+      final LocalizableMessage message = ERR_LDAP_FILTER_UNCAUGHT_EXCEPTION
+          .get(string, String.valueOf(e));
+      throw new LocalizedIllegalArgumentException(message);
     }
   }
 
 
 
-  private static Filter valueOf0(String string,
-      int beginIndex /* inclusive */, int endIndex /* exclusive */)
+  // Converts an assertion value to a substring filter.
+  private static Filter assertionValue2SubstringFilter(
+      final String filterString, final String attrType, final int equalPos,
+      final int endPos) throws LocalizedIllegalArgumentException
+  {
+    // Get a binary representation of the value.
+    final byte[] valueBytes = getBytes(filterString.substring(equalPos, endPos));
+
+    // Find the locations of all the asterisks in the value. Also, check to
+    // see if there are any escaped values, since they will need special
+    // treatment.
+    boolean hasEscape = false;
+    final LinkedList<Integer> asteriskPositions = new LinkedList<Integer>();
+    for (int i = 0; i < valueBytes.length; i++)
+    {
+      if (valueBytes[i] == 0x2A) // The asterisk.
+      {
+        asteriskPositions.add(i);
+      }
+      else if (valueBytes[i] == 0x5C) // The backslash.
+      {
+        hasEscape = true;
+      }
+    }
+
+    // If there were no asterisks, then this isn't a substring filter.
+    if (asteriskPositions.isEmpty())
+    {
+      final LocalizableMessage message = ERR_LDAP_FILTER_SUBSTRING_NO_ASTERISKS
+          .get(filterString, equalPos + 1, endPos);
+      throw new LocalizedIllegalArgumentException(message);
+    }
+
+    // If the value starts with an asterisk, then there is no subInitial
+    // component. Otherwise, parse out the subInitial.
+    ByteString subInitial;
+    int firstPos = asteriskPositions.removeFirst();
+    if (firstPos == 0)
+    {
+      subInitial = null;
+    }
+    else
+    {
+      if (hasEscape)
+      {
+        final ByteStringBuilder buffer = new ByteStringBuilder(firstPos);
+        escapeHexChars(buffer, attrType, valueBytes, 0, firstPos, equalPos);
+        subInitial = buffer.toByteString();
+      }
+      else
+      {
+        subInitial = ByteString.wrap(valueBytes, 0, firstPos);
+      }
+    }
+
+    // Next, process through the rest of the asterisks to get the subAny values.
+    final ArrayList<ByteString> subAny = new ArrayList<ByteString>();
+    for (final int asteriskPos : asteriskPositions)
+    {
+      final int length = asteriskPos - firstPos - 1;
+
+      if (hasEscape)
+      {
+        final ByteStringBuilder buffer = new ByteStringBuilder(length);
+        escapeHexChars(buffer, attrType, valueBytes, firstPos + 1, asteriskPos,
+            equalPos);
+        subAny.add(buffer.toByteString());
+        buffer.clear();
+      }
+      else
+      {
+        subAny.add(ByteString.wrap(valueBytes, firstPos + 1, length));
+      }
+      firstPos = asteriskPos;
+    }
+
+    // Finally, see if there is anything after the last asterisk, which would be
+    // the subFinal value.
+    ByteString subFinal;
+    if (firstPos == (valueBytes.length - 1))
+    {
+      subFinal = null;
+    }
+    else
+    {
+      final int length = valueBytes.length - firstPos - 1;
+
+      if (hasEscape)
+      {
+        final ByteStringBuilder buffer = new ByteStringBuilder(length);
+        escapeHexChars(buffer, attrType, valueBytes, firstPos + 1,
+            valueBytes.length, equalPos);
+        subFinal = buffer.toByteString();
+      }
+      else
+      {
+        subFinal = ByteString.wrap(valueBytes, firstPos + 1, length);
+      }
+    }
+    return new Filter(
+        new SubstringsImpl(attrType, subInitial, subAny, subFinal));
+  }
+
+
+
+  private static void escapeHexChars(final ByteStringBuilder valueBuffer,
+      final String string, final byte[] valueBytes, final int fromIndex,
+      final int len, final int errorIndex)
+      throws LocalizedIllegalArgumentException
+  {
+    for (int i = fromIndex; i < len; i++)
+    {
+      if (valueBytes[i] == 0x5C) // The backslash character
+      {
+        // The next two bytes must be the hex characters that comprise
+        // the binary value.
+        if ((i + 2) >= valueBytes.length)
+        {
+          final LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE
+              .get(string, errorIndex + i + 1);
+          throw new LocalizedIllegalArgumentException(message);
+        }
+
+        byte byteValue = 0;
+        switch (valueBytes[++i])
+        {
+        case 0x30: // '0'
+          break;
+        case 0x31: // '1'
+          byteValue = (byte) 0x10;
+          break;
+        case 0x32: // '2'
+          byteValue = (byte) 0x20;
+          break;
+        case 0x33: // '3'
+          byteValue = (byte) 0x30;
+          break;
+        case 0x34: // '4'
+          byteValue = (byte) 0x40;
+          break;
+        case 0x35: // '5'
+          byteValue = (byte) 0x50;
+          break;
+        case 0x36: // '6'
+          byteValue = (byte) 0x60;
+          break;
+        case 0x37: // '7'
+          byteValue = (byte) 0x70;
+          break;
+        case 0x38: // '8'
+          byteValue = (byte) 0x80;
+          break;
+        case 0x39: // '9'
+          byteValue = (byte) 0x90;
+          break;
+        case 0x41: // 'A'
+        case 0x61: // 'a'
+          byteValue = (byte) 0xA0;
+          break;
+        case 0x42: // 'B'
+        case 0x62: // 'b'
+          byteValue = (byte) 0xB0;
+          break;
+        case 0x43: // 'C'
+        case 0x63: // 'c'
+          byteValue = (byte) 0xC0;
+          break;
+        case 0x44: // 'D'
+        case 0x64: // 'd'
+          byteValue = (byte) 0xD0;
+          break;
+        case 0x45: // 'E'
+        case 0x65: // 'e'
+          byteValue = (byte) 0xE0;
+          break;
+        case 0x46: // 'F'
+        case 0x66: // 'f'
+          byteValue = (byte) 0xF0;
+          break;
+        default:
+          final LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE
+              .get(string, errorIndex + i + 1);
+          throw new LocalizedIllegalArgumentException(message);
+        }
+
+        switch (valueBytes[++i])
+        {
+        case 0x30: // '0'
+          break;
+        case 0x31: // '1'
+          byteValue |= (byte) 0x01;
+          break;
+        case 0x32: // '2'
+          byteValue |= (byte) 0x02;
+          break;
+        case 0x33: // '3'
+          byteValue |= (byte) 0x03;
+          break;
+        case 0x34: // '4'
+          byteValue |= (byte) 0x04;
+          break;
+        case 0x35: // '5'
+          byteValue |= (byte) 0x05;
+          break;
+        case 0x36: // '6'
+          byteValue |= (byte) 0x06;
+          break;
+        case 0x37: // '7'
+          byteValue |= (byte) 0x07;
+          break;
+        case 0x38: // '8'
+          byteValue |= (byte) 0x08;
+          break;
+        case 0x39: // '9'
+          byteValue |= (byte) 0x09;
+          break;
+        case 0x41: // 'A'
+        case 0x61: // 'a'
+          byteValue |= (byte) 0x0A;
+          break;
+        case 0x42: // 'B'
+        case 0x62: // 'b'
+          byteValue |= (byte) 0x0B;
+          break;
+        case 0x43: // 'C'
+        case 0x63: // 'c'
+          byteValue |= (byte) 0x0C;
+          break;
+        case 0x44: // 'D'
+        case 0x64: // 'd'
+          byteValue |= (byte) 0x0D;
+          break;
+        case 0x45: // 'E'
+        case 0x65: // 'e'
+          byteValue |= (byte) 0x0E;
+          break;
+        case 0x46: // 'F'
+        case 0x66: // 'f'
+          byteValue |= (byte) 0x0F;
+          break;
+        default:
+          final LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE
+              .get(string, errorIndex + i + 1);
+          throw new LocalizedIllegalArgumentException(message);
+        }
+
+        valueBuffer.append(byteValue);
+      }
+      else
+      {
+        valueBuffer.append(valueBytes[i]);
+      }
+    }
+  }
+
+
+
+  private static Filter valueOf0(final String string,
+      final int beginIndex /* inclusive */, final int endIndex /* exclusive */)
       throws LocalizedIllegalArgumentException
   {
     if (beginIndex >= endIndex)
     {
-      LocalizableMessage message = ERR_LDAP_FILTER_STRING_NULL.get();
+      final LocalizableMessage message = ERR_LDAP_FILTER_STRING_NULL.get();
       throw new LocalizedIllegalArgumentException(message);
     }
 
-    int index = beginIndex;
-    char c = string.charAt(index);
+    final int index = beginIndex;
+    final char c = string.charAt(index);
 
     if (c == '&')
     {
-      List<Filter> subFilters = valueOfFilterList(string, index + 1,
+      final List<Filter> subFilters = valueOfFilterList(string, index + 1,
           endIndex);
       if (subFilters.isEmpty())
       {
@@ -1293,7 +1532,7 @@
     }
     else if (c == '|')
     {
-      List<Filter> subFilters = valueOfFilterList(string, index + 1,
+      final List<Filter> subFilters = valueOfFilterList(string, index + 1,
           endIndex);
       if (subFilters.isEmpty())
       {
@@ -1309,13 +1548,19 @@
       if ((string.charAt(index + 1) != '(')
           || (string.charAt(endIndex - 1) != ')'))
       {
-        LocalizableMessage message = ERR_LDAP_FILTER_COMPOUND_MISSING_PARENTHESES
+        final LocalizableMessage message = ERR_LDAP_FILTER_COMPOUND_MISSING_PARENTHESES
             .get(string, index, endIndex - 1);
         throw new LocalizedIllegalArgumentException(message);
       }
-
-      Filter subFilter = valueOf0(string, index + 2, endIndex - 1);
-      return new Filter(new NotImpl(subFilter));
+      final List<Filter> subFilters = valueOfFilterList(string, index + 1,
+          endIndex);
+      if (subFilters.size() != 1)
+      {
+        final LocalizableMessage message = ERR_LDAP_FILTER_NOT_EXACTLY_ONE.get(
+            string, index, endIndex);
+        throw new LocalizedIllegalArgumentException(message);
+      }
+      return new Filter(new NotImpl(subFilters.get(0)));
     }
     else
     {
@@ -1331,6 +1576,13 @@
         }
       }
 
+      if (equalPos <= index)
+      {
+        final LocalizableMessage message = ERR_LDAP_FILTER_NO_EQUAL_SIGN.get(
+            string, index, endIndex);
+        throw new LocalizedIllegalArgumentException(message);
+      }
+
       // Look at the character immediately before the equal sign,
       // because it may help determine the filter type.
       String attributeDescription;
@@ -1339,47 +1591,43 @@
       switch (string.charAt(equalPos - 1))
       {
       case '~':
-        attributeDescription = valueOfAttributeDescription(string,
-            index, equalPos - 1);
-        assertionValue = valueOfAssertionValue(string, equalPos + 1,
-            endIndex);
+        attributeDescription = valueOfAttributeDescription(string, index,
+            equalPos - 1);
+        assertionValue = valueOfAssertionValue(string, equalPos + 1, endIndex);
         return new Filter(new ApproxMatchImpl(attributeDescription,
             assertionValue));
       case '>':
-        attributeDescription = valueOfAttributeDescription(string,
-            index, equalPos - 1);
-        assertionValue = valueOfAssertionValue(string, equalPos + 1,
-            endIndex);
+        attributeDescription = valueOfAttributeDescription(string, index,
+            equalPos - 1);
+        assertionValue = valueOfAssertionValue(string, equalPos + 1, endIndex);
         return new Filter(new GreaterOrEqualImpl(attributeDescription,
             assertionValue));
       case '<':
-        attributeDescription = valueOfAttributeDescription(string,
-            index, equalPos - 1);
-        assertionValue = valueOfAssertionValue(string, equalPos + 1,
-            endIndex);
+        attributeDescription = valueOfAttributeDescription(string, index,
+            equalPos - 1);
+        assertionValue = valueOfAssertionValue(string, equalPos + 1, endIndex);
         return new Filter(new LessOrEqualImpl(attributeDescription,
             assertionValue));
       case ':':
-        return valueOfExtensibleFilter(string, index, equalPos,
-            endIndex);
+        return valueOfExtensibleFilter(string, index, equalPos, endIndex);
       default:
-        attributeDescription = valueOfAttributeDescription(string,
-            index, equalPos);
-        return valueOfGenericFilter(string, attributeDescription,
-            equalPos + 1, endIndex);
+        attributeDescription = valueOfAttributeDescription(string, index,
+            equalPos);
+        return valueOfGenericFilter(string, attributeDescription, equalPos + 1,
+            endIndex);
       }
     }
   }
 
 
 
-  private static ByteString valueOfAssertionValue(String string,
-      int startIndex, int endIndex)
+  private static ByteString valueOfAssertionValue(final String string,
+      final int startIndex, final int endIndex)
       throws LocalizedIllegalArgumentException
   {
     boolean hasEscape = false;
-    byte[] valueBytes = getBytes(string.substring(startIndex, endIndex));
-    for (byte valueByte : valueBytes)
+    final byte[] valueBytes = getBytes(string.substring(startIndex, endIndex));
+    for (final byte valueByte : valueBytes)
     {
       if (valueByte == 0x5C) // The backslash character
       {
@@ -1390,152 +1638,10 @@
 
     if (hasEscape)
     {
-      ByteStringBuilder valueBuffer = new ByteStringBuilder(
+      final ByteStringBuilder valueBuffer = new ByteStringBuilder(
           valueBytes.length);
-      for (int i = 0; i < valueBytes.length; i++)
-      {
-        if (valueBytes[i] == 0x5C) // The backslash character
-        {
-          // The next two bytes must be the hex characters that comprise
-          // the binary value.
-          if ((i + 2) >= valueBytes.length)
-          {
-            LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE
-                .get(string, startIndex + i + 1);
-            throw new LocalizedIllegalArgumentException(message);
-          }
-
-          byte byteValue = 0;
-          switch (valueBytes[++i])
-          {
-          case 0x30: // '0'
-            break;
-          case 0x31: // '1'
-            byteValue = (byte) 0x10;
-            break;
-          case 0x32: // '2'
-            byteValue = (byte) 0x20;
-            break;
-          case 0x33: // '3'
-            byteValue = (byte) 0x30;
-            break;
-          case 0x34: // '4'
-            byteValue = (byte) 0x40;
-            break;
-          case 0x35: // '5'
-            byteValue = (byte) 0x50;
-            break;
-          case 0x36: // '6'
-            byteValue = (byte) 0x60;
-            break;
-          case 0x37: // '7'
-            byteValue = (byte) 0x70;
-            break;
-          case 0x38: // '8'
-            byteValue = (byte) 0x80;
-            break;
-          case 0x39: // '9'
-            byteValue = (byte) 0x90;
-            break;
-          case 0x41: // 'A'
-          case 0x61: // 'a'
-            byteValue = (byte) 0xA0;
-            break;
-          case 0x42: // 'B'
-          case 0x62: // 'b'
-            byteValue = (byte) 0xB0;
-            break;
-          case 0x43: // 'C'
-          case 0x63: // 'c'
-            byteValue = (byte) 0xC0;
-            break;
-          case 0x44: // 'D'
-          case 0x64: // 'd'
-            byteValue = (byte) 0xD0;
-            break;
-          case 0x45: // 'E'
-          case 0x65: // 'e'
-            byteValue = (byte) 0xE0;
-            break;
-          case 0x46: // 'F'
-          case 0x66: // 'f'
-            byteValue = (byte) 0xF0;
-            break;
-          default:
-            LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE
-                .get(string, startIndex + i + 1);
-            throw new LocalizedIllegalArgumentException(message);
-          }
-
-          switch (valueBytes[++i])
-          {
-          case 0x30: // '0'
-            break;
-          case 0x31: // '1'
-            byteValue |= (byte) 0x01;
-            break;
-          case 0x32: // '2'
-            byteValue |= (byte) 0x02;
-            break;
-          case 0x33: // '3'
-            byteValue |= (byte) 0x03;
-            break;
-          case 0x34: // '4'
-            byteValue |= (byte) 0x04;
-            break;
-          case 0x35: // '5'
-            byteValue |= (byte) 0x05;
-            break;
-          case 0x36: // '6'
-            byteValue |= (byte) 0x06;
-            break;
-          case 0x37: // '7'
-            byteValue |= (byte) 0x07;
-            break;
-          case 0x38: // '8'
-            byteValue |= (byte) 0x08;
-            break;
-          case 0x39: // '9'
-            byteValue |= (byte) 0x09;
-            break;
-          case 0x41: // 'A'
-          case 0x61: // 'a'
-            byteValue |= (byte) 0x0A;
-            break;
-          case 0x42: // 'B'
-          case 0x62: // 'b'
-            byteValue |= (byte) 0x0B;
-            break;
-          case 0x43: // 'C'
-          case 0x63: // 'c'
-            byteValue |= (byte) 0x0C;
-            break;
-          case 0x44: // 'D'
-          case 0x64: // 'd'
-            byteValue |= (byte) 0x0D;
-            break;
-          case 0x45: // 'E'
-          case 0x65: // 'e'
-            byteValue |= (byte) 0x0E;
-            break;
-          case 0x46: // 'F'
-          case 0x66: // 'f'
-            byteValue |= (byte) 0x0F;
-            break;
-          default:
-            LocalizableMessage message = ERR_LDAP_FILTER_INVALID_ESCAPED_BYTE
-                .get(string, startIndex + i + 1);
-            throw new LocalizedIllegalArgumentException(message);
-          }
-
-          valueBuffer.append(byteValue);
-        }
-        else
-        {
-          valueBuffer.append(valueBytes[i]);
-        }
-      }
-
+      escapeHexChars(valueBuffer, string, valueBytes, 0, valueBytes.length,
+          startIndex);
       return valueBuffer.toByteString();
     }
     else
@@ -1546,8 +1652,8 @@
 
 
 
-  private static String valueOfAttributeDescription(String string,
-      int startIndex, int endIndex)
+  private static String valueOfAttributeDescription(final String string,
+      final int startIndex, final int endIndex)
       throws LocalizedIllegalArgumentException
   {
     // The part of the filter string before the equal sign should be the
@@ -1556,7 +1662,7 @@
     // attribute name exceptions (ASCII letters and digits, the dash,
     // and the underscore). We also need to allow attribute options,
     // which includes the semicolon and the equal sign.
-    String attrType = string.substring(startIndex, endIndex);
+    final String attrType = string.substring(startIndex, endIndex);
     for (int i = 0; i < attrType.length(); i++)
     {
       switch (attrType.charAt(i))
@@ -1648,7 +1754,7 @@
         // can help make the switch statement more efficient. We'll fall
         // through to the default clause to reject them.
       default:
-        LocalizableMessage message = ERR_LDAP_FILTER_INVALID_CHAR_IN_ATTR_TYPE
+        final LocalizableMessage message = ERR_LDAP_FILTER_INVALID_CHAR_IN_ATTR_TYPE
             .get(attrType, String.valueOf(attrType.charAt(i)), i);
         throw new LocalizedIllegalArgumentException(message);
       }
@@ -1659,8 +1765,8 @@
 
 
 
-  private static Filter valueOfExtensibleFilter(String string,
-      int startIndex, int equalIndex, int endIndex)
+  private static Filter valueOfExtensibleFilter(final String string,
+      final int startIndex, final int equalIndex, final int endIndex)
       throws LocalizedIllegalArgumentException
   {
     String attributeDescription = null;
@@ -1670,7 +1776,7 @@
     // Look at the first character. If it is a colon, then it must be
     // followed by either the string "dn" or the matching rule ID. If it
     // is not, then must be the attribute type.
-    String lowerLeftStr = toLowerCase(string.substring(startIndex,
+    final String lowerLeftStr = toLowerCase(string.substring(startIndex,
         equalIndex));
     if (string.charAt(startIndex) == ':')
     {
@@ -1682,8 +1788,7 @@
 
         if ((startIndex + 4) < (equalIndex - 1))
         {
-          matchingRule = string.substring(startIndex + 4,
-              equalIndex - 1);
+          matchingRule = string.substring(startIndex + 4, equalIndex - 1);
         }
       }
       else
@@ -1693,10 +1798,10 @@
     }
     else
     {
-      int colonPos = string.indexOf(':', startIndex);
+      final int colonPos = string.indexOf(':', startIndex);
       if (colonPos < 0)
       {
-        LocalizableMessage message = ERR_LDAP_FILTER_EXTENSIBLE_MATCH_NO_COLON
+        final LocalizableMessage message = ERR_LDAP_FILTER_EXTENSIBLE_MATCH_NO_COLON
             .get(string, startIndex);
         throw new LocalizedIllegalArgumentException(message);
       }
@@ -1713,8 +1818,7 @@
 
           if ((colonPos + 4) < (equalIndex - 1))
           {
-            matchingRule = string.substring(colonPos + 4,
-                equalIndex - 1);
+            matchingRule = string.substring(colonPos + 4, equalIndex - 1);
           }
         }
         else
@@ -1725,14 +1829,14 @@
     }
 
     // Parse out the attribute value.
-    ByteString matchValue = valueOfAssertionValue(string,
-        equalIndex + 1, endIndex);
+    final ByteString matchValue = valueOfAssertionValue(string, equalIndex + 1,
+        endIndex);
 
     // Make sure that the filter has at least one of an attribute
     // description and/or a matching rule ID.
     if ((attributeDescription == null) && (matchingRule == null))
     {
-      LocalizableMessage message = ERR_LDAP_FILTER_EXTENSIBLE_MATCH_NO_AD_OR_MR
+      final LocalizableMessage message = ERR_LDAP_FILTER_EXTENSIBLE_MATCH_NO_AD_OR_MR
           .get(string, startIndex);
       throw new LocalizedIllegalArgumentException(message);
     }
@@ -1743,8 +1847,8 @@
 
 
 
-  private static List<Filter> valueOfFilterList(String string,
-      int startIndex, int endIndex)
+  private static List<Filter> valueOfFilterList(final String string,
+      final int startIndex, final int endIndex)
       throws LocalizedIllegalArgumentException
   {
     // If the end index is equal to the start index, then there are no
@@ -1763,7 +1867,7 @@
     if ((string.charAt(startIndex) != '(')
         || (string.charAt(endIndex - 1) != ')'))
     {
-      LocalizableMessage message = ERR_LDAP_FILTER_COMPOUND_MISSING_PARENTHESES
+      final LocalizableMessage message = ERR_LDAP_FILTER_COMPOUND_MISSING_PARENTHESES
           .get(string, startIndex, endIndex);
       throw new LocalizedIllegalArgumentException(message);
     }
@@ -1775,7 +1879,7 @@
     int openIndex = -1;
     for (int i = startIndex; i < endIndex; i++)
     {
-      char c = string.charAt(i);
+      final char c = string.charAt(i);
       if (c == '(')
       {
         if (openIndex < 0)
@@ -1789,7 +1893,7 @@
         pendingOpens--;
         if (pendingOpens == 0)
         {
-          Filter subFilter = valueOf0(string, openIndex + 1, i);
+          final Filter subFilter = valueOf0(string, openIndex + 1, i);
           if (subFilters != null)
           {
             subFilters.add(subFilter);
@@ -1809,14 +1913,14 @@
         }
         else if (pendingOpens < 0)
         {
-          LocalizableMessage message = ERR_LDAP_FILTER_NO_CORRESPONDING_OPEN_PARENTHESIS
+          final LocalizableMessage message = ERR_LDAP_FILTER_NO_CORRESPONDING_OPEN_PARENTHESIS
               .get(string, i);
           throw new LocalizedIllegalArgumentException(message);
         }
       }
       else if (pendingOpens <= 0)
       {
-        LocalizableMessage message = ERR_LDAP_FILTER_COMPOUND_MISSING_PARENTHESES
+        final LocalizableMessage message = ERR_LDAP_FILTER_COMPOUND_MISSING_PARENTHESES
             .get(string, startIndex, endIndex);
         throw new LocalizedIllegalArgumentException(message);
       }
@@ -1826,7 +1930,7 @@
     // components. The list of open parenthesis positions must be empty.
     if (pendingOpens != 0)
     {
-      LocalizableMessage message = ERR_LDAP_FILTER_NO_CORRESPONDING_CLOSE_PARENTHESIS
+      final LocalizableMessage message = ERR_LDAP_FILTER_NO_CORRESPONDING_CLOSE_PARENTHESIS
           .get(string, openIndex);
       throw new LocalizedIllegalArgumentException(message);
     }
@@ -1843,123 +1947,54 @@
 
 
 
-  private static Filter valueOfGenericFilter(String string,
-      String attributeDescription, int startIndex, int endIndex)
-      throws LocalizedIllegalArgumentException
+  private static Filter valueOfGenericFilter(final String string,
+      final String attributeDescription, final int startIndex,
+      final int endIndex) throws LocalizedIllegalArgumentException
   {
+    final int asteriskIdx = string.indexOf('*', startIndex);
     if (startIndex >= endIndex)
     {
       // Equality filter with empty assertion value.
-      return new Filter(new EqualityMatchImpl(attributeDescription,
-          ByteString.empty()));
+      return new Filter(new EqualityMatchImpl(attributeDescription, ByteString
+          .empty()));
     }
-    else if ((endIndex - startIndex == 1)
-        && (string.charAt(startIndex) == '*'))
+    else if ((endIndex - startIndex == 1) && (string.charAt(startIndex) == '*'))
     {
       // Single asterisk is a present filter.
       return newPresentFilter(attributeDescription);
     }
+    else if (asteriskIdx > 0 && asteriskIdx <= endIndex)
+    {
+      // Substring filter.
+      return assertionValue2SubstringFilter(string, attributeDescription,
+          startIndex, endIndex);
+    }
     else
     {
-      // Either an equality or substring filter.
-      ByteString assertionValue = valueOfAssertionValue(string,
+      // equality filter.
+      final ByteString assertionValue = valueOfAssertionValue(string,
           startIndex, endIndex);
-
-      ByteString initialString = null;
-      ByteString finalString = null;
-      LinkedList<ByteString> anyStrings = null;
-
-      int lastAsteriskIndex = -1;
-      int length = assertionValue.length();
-      for (int i = 0; i < length; i++)
-      {
-        if (assertionValue.byteAt(i) == '*')
-        {
-          if (lastAsteriskIndex == -1)
-          {
-            if (i > 0)
-            {
-              // Got an initial substring.
-              initialString = assertionValue.subSequence(0, i);
-            }
-            lastAsteriskIndex = i;
-          }
-          else
-          {
-            // Got an any substring.
-            if (anyStrings == null)
-            {
-              anyStrings = new LinkedList<ByteString>();
-            }
-
-            int s = lastAsteriskIndex + 1;
-            if (s == i)
-            {
-              // A zero length substring.
-              LocalizableMessage message = ERR_LDAP_FILTER_BAD_SUBSTRING
-                  .get(string, string.subSequence(startIndex, endIndex));
-              throw new LocalizedIllegalArgumentException(message);
-            }
-
-            anyStrings.add(assertionValue.subSequence(s, i));
-            lastAsteriskIndex = i;
-          }
-        }
-      }
-
-      if (lastAsteriskIndex >= 0 && lastAsteriskIndex < length - 1)
-      {
-        // Got a final substring.
-        finalString = assertionValue.subSequence(lastAsteriskIndex + 1,
-            length);
-      }
-
-      if ((initialString == null) && (anyStrings == null)
-          && (finalString == null))
-      {
-        return new Filter(new EqualityMatchImpl(attributeDescription,
-            assertionValue));
-      }
-      else
-      {
-        List<ByteString> tmp;
-
-        if (anyStrings == null)
-        {
-          tmp = Collections.emptyList();
-        }
-        else if (anyStrings.size() == 1)
-        {
-          tmp = Collections.singletonList(anyStrings.getFirst());
-        }
-        else
-        {
-          tmp = Collections.unmodifiableList(anyStrings);
-        }
-
-        return new Filter(new SubstringsImpl(attributeDescription,
-            initialString, tmp, finalString));
-      }
+      return new Filter(new EqualityMatchImpl(attributeDescription,
+          assertionValue));
     }
   }
 
 
 
   /**
-   * Appends a properly-cleaned version of the provided value to the
-   * given builder so that it can be safely used in string
-   * representations of this search filter. The formatting changes that
-   * may be performed will be in compliance with the specification in
-   * RFC 2254.
+   * Appends a properly-cleaned version of the provided value to the given
+   * builder so that it can be safely used in string representations of this
+   * search filter. The formatting changes that may be performed will be in
+   * compliance with the specification in RFC 2254.
    *
    * @param builder
-   *          The builder to which the "safe" version of the value will
-   *          be appended.
+   *          The builder to which the "safe" version of the value will be
+   *          appended.
    * @param value
    *          The value to be appended to the builder.
    */
-  private static void valueToFilterString(StringBuilder builder,
-      ByteString value)
+  private static void valueToFilterString(final StringBuilder builder,
+      final ByteString value)
   {
     // Get the binary representation of the value and iterate through
     // it to see if there are any unsafe characters. If there are,
@@ -1970,7 +2005,7 @@
     {
       // TODO: this is a bit overkill - it will escape all non-ascii
       // chars!
-      byte b = value.byteAt(i);
+      final byte b = value.byteAt(i);
       if (((b & 0x7F) != b) || // Not 7-bit clean
           (b <= 0x1F) || // Below the printable character range
           (b == 0x28) || // Open parenthesis
@@ -1995,7 +2030,7 @@
 
 
 
-  private Filter(Impl pimpl)
+  private Filter(final Impl pimpl)
   {
     this.pimpl = pimpl;
   }
@@ -2008,15 +2043,14 @@
    * @param <R>
    *          The return type of the visitor's methods.
    * @param <P>
-   *          The type of the additional parameters to the visitor's
-   *          methods.
+   *          The type of the additional parameters to the visitor's methods.
    * @param v
    *          The filter visitor.
    * @param p
    *          Optional additional visitor parameter.
    * @return A result as specified by the visitor.
    */
-  public <R, P> R accept(FilterVisitor<R, P> v, P p)
+  public <R, P> R accept(final FilterVisitor<R, P> v, final P p)
   {
     return pimpl.accept(v, p);
   }
@@ -2024,24 +2058,8 @@
 
 
   /**
-   * Returns a {@code Matcher} which can be used to compare this {@code
-   * Filter} against entries using the provided {@code Schema}.
-   *
-   * @param schema
-   *          The schema which the {@code Matcher} should use for
-   *          comparisons.
-   * @return The {@code Matcher}.
-   */
-  public Matcher matcher(Schema schema)
-  {
-    return new Matcher(this, schema);
-  }
-
-
-
-  /**
-   * Returns a {@code Matcher} which can be used to compare this {@code
-   * Filter} against entries using the default schema.
+   * Returns a {@code Matcher} which can be used to compare this {@code Filter}
+   * against entries using the default schema.
    *
    * @return The {@code Matcher}.
    */
@@ -2053,8 +2071,23 @@
 
 
   /**
-   * Indicates whether this {@code Filter} matches the provided {@code
-   * Entry} using the schema associated with the entry.
+   * Returns a {@code Matcher} which can be used to compare this {@code Filter}
+   * against entries using the provided {@code Schema}.
+   *
+   * @param schema
+   *          The schema which the {@code Matcher} should use for comparisons.
+   * @return The {@code Matcher}.
+   */
+  public Matcher matcher(final Schema schema)
+  {
+    return new Matcher(this, schema);
+  }
+
+
+
+  /**
+   * Indicates whether this {@code Filter} matches the provided {@code Entry}
+   * using the schema associated with the entry.
    * <p>
    * Calling this method is equivalent to the following:
    *
@@ -2064,10 +2097,10 @@
    *
    * @param entry
    *          The entry to be matched.
-   * @return {@code true} if this {@code Filter} matches the provided
-   *         {@code Entry}.
+   * @return {@code true} if this {@code Filter} matches the provided {@code
+   *         Entry}.
    */
-  public ConditionResult matches(Entry entry)
+  public ConditionResult matches(final Entry entry)
   {
     return matcher(Schema.getDefaultSchema()).matches(entry);
   }
@@ -2075,32 +2108,16 @@
 
 
   /**
-   * Returns a {@code String} whose contents is the LDAP string
-   * representation of this {@code Filter}.
+   * Returns a {@code String} whose contents is the LDAP string representation
+   * of this {@code Filter}.
    *
    * @return The LDAP string representation of this {@code Filter}.
    */
   @Override
   public String toString()
   {
-    StringBuilder builder = new StringBuilder();
-    return toString(builder).toString();
-  }
-
-
-
-  /**
-   * Appends the LDAP string representation of this {@code Filter} to
-   * the provided {@code StringBuilder}.
-   *
-   * @param builder
-   *          The {@code StringBuilder} to which the LDAP string
-   *          representation of this {@code Filter} should be appended.
-   * @return The updated {@code StringBuilder}.
-   */
-  public StringBuilder toString(StringBuilder builder)
-  {
-    return pimpl.accept(TO_STRING_VISITOR, builder);
+    final StringBuilder builder = new StringBuilder();
+    return pimpl.accept(TO_STRING_VISITOR, builder).toString();
   }
 
 }
diff --git a/sdk/src/org/opends/sdk/FilterVisitor.java b/sdk/src/org/opends/sdk/FilterVisitor.java
index 486318c..e8d56eb 100644
--- a/sdk/src/org/opends/sdk/FilterVisitor.java
+++ b/sdk/src/org/opends/sdk/FilterVisitor.java
@@ -34,21 +34,20 @@
 
 
 /**
- * A visitor of {@code Filter}s, in the style of the visitor design
- * pattern.
+ * A visitor of {@code Filter}s, in the style of the visitor design pattern.
  * <p>
- * Classes implementing this interface can query filters in a type-safe
- * manner. When a visitor is passed to a filter's accept method, the
- * corresponding visit method most applicable to that filter is invoked.
+ * Classes implementing this interface can query filters in a type-safe manner.
+ * When a visitor is passed to a filter's accept method, the corresponding visit
+ * method most applicable to that filter is invoked.
  *
  * @param <R>
  *          The return type of this visitor's methods. Use
- *          {@link java.lang.Void} for visitors that do not need to
- *          return results.
+ *          {@link java.lang.Void} for visitors that do not need to return
+ *          results.
  * @param <P>
- *          The type of the additional parameter to this visitor's
- *          methods. Use {@link java.lang.Void} for visitors that do not
- *          need an additional parameter.
+ *          The type of the additional parameter to this visitor's methods. Use
+ *          {@link java.lang.Void} for visitors that do not need an additional
+ *          parameter.
  */
 public interface FilterVisitor<R, P>
 {
@@ -57,8 +56,7 @@
    * Visits an {@code and} filter.
    * <p>
    * <b>Implementation note</b>: for the purposes of matching an empty
-   * sub-filter list should always evaluate to {@code true} as per RFC
-   * 4526.
+   * sub-filter list should always evaluate to {@code true} as per RFC 4526.
    *
    * @param p
    *          A visitor specified parameter.
@@ -174,8 +172,7 @@
    * Visits an {@code or} filter.
    * <p>
    * <b>Implementation note</b>: for the purposes of matching an empty
-   * sub-filter list should always evaluate to {@code false} as per RFC
-   * 4526.
+   * sub-filter list should always evaluate to {@code false} as per RFC 4526.
    *
    * @param p
    *          A visitor specified parameter.
@@ -234,4 +231,4 @@
    */
   R visitUnrecognizedFilter(P p, byte filterTag, ByteString filterBytes);
 
-}
\ No newline at end of file
+}
diff --git a/sdk/src/org/opends/sdk/FutureResult.java b/sdk/src/org/opends/sdk/FutureResult.java
index 3b9ff34..5211a20 100644
--- a/sdk/src/org/opends/sdk/FutureResult.java
+++ b/sdk/src/org/opends/sdk/FutureResult.java
@@ -36,8 +36,7 @@
 
 
 /**
- * A handle which can be used to retrieve the Result of an asynchronous
- * Request.
+ * A handle which can be used to retrieve the Result of an asynchronous Request.
  *
  * @param <S>
  *          The type of result returned by this future.
@@ -45,39 +44,37 @@
 public interface FutureResult<S> extends Future<S>
 {
   /**
-   * Attempts to cancel the request. This attempt will fail if the
-   * request has already completed or has already been cancelled. If
-   * successful, then cancellation results in an abandon or cancel
-   * request (if configured) being sent to the server.
+   * Attempts to cancel the request. This attempt will fail if the request has
+   * already completed or has already been cancelled. If successful, then
+   * cancellation results in an abandon or cancel request (if configured) being
+   * sent to the server.
    * <p>
-   * After this method returns, subsequent calls to {@link #isDone} will
-   * always return {@code true}. Subsequent calls to
-   * {@link #isCancelled} will always return {@code true} if this method
-   * returned {@code true}.
+   * After this method returns, subsequent calls to {@link #isDone} will always
+   * return {@code true}. Subsequent calls to {@link #isCancelled} will always
+   * return {@code true} if this method returned {@code true}.
    *
    * @param mayInterruptIfRunning
-   *          {@code true} if the thread executing executing the
-   *          response handler should be interrupted; otherwise,
-   *          in-progress response handlers are allowed to complete.
-   * @return {@code false} if the request could not be cancelled,
-   *         typically because it has already completed normally;
-   *         {@code true} otherwise.
+   *          {@code true} if the thread executing executing the response
+   *          handler should be interrupted; otherwise, in-progress response
+   *          handlers are allowed to complete.
+   * @return {@code false} if the request could not be cancelled, typically
+   *         because it has already completed normally; {@code true} otherwise.
    */
   boolean cancel(boolean mayInterruptIfRunning);
 
 
 
   /**
-   * Waits if necessary for the request to complete, and then returns
-   * the result if the request succeeded. If the request failed (i.e. a
-   * non-successful result code was obtained) then the result is thrown
-   * as an {@link ErrorResultException}.
+   * Waits if necessary for the request to complete, and then returns the result
+   * if the request succeeded. If the request failed (i.e. a non-successful
+   * result code was obtained) then the result is thrown as an
+   * {@link ErrorResultException}.
    *
-   * @return The result, but only if the result code indicates that the
-   *         request succeeded.
+   * @return The result, but only if the result code indicates that the request
+   *         succeeded.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    */
@@ -86,20 +83,20 @@
 
 
   /**
-   * Waits if necessary for at most the given time for the request to
-   * complete, and then returns the result if the request succeeded. If
-   * the request failed (i.e. a non-successful result code was obtained)
-   * then the result is thrown as an {@link ErrorResultException}.
+   * Waits if necessary for at most the given time for the request to complete,
+   * and then returns the result if the request succeeded. If the request failed
+   * (i.e. a non-successful result code was obtained) then the result is thrown
+   * as an {@link ErrorResultException}.
    *
    * @param timeout
    *          The maximum time to wait.
    * @param unit
    *          The time unit of the timeout argument.
-   * @return The result, but only if the result code indicates that the
-   *         request succeeded.
+   * @return The result, but only if the result code indicates that the request
+   *         succeeded.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws TimeoutException
    *           If the wait timed out.
    * @throws InterruptedException
@@ -120,11 +117,11 @@
 
 
   /**
-   * Returns {@code true} if the request was cancelled before it
-   * completed normally.
+   * Returns {@code true} if the request was cancelled before it completed
+   * normally.
    *
-   * @return {@code true} if the request was cancelled before it
-   *         completed normally, otherwise {@code false}.
+   * @return {@code true} if the request was cancelled before it completed
+   *         normally, otherwise {@code false}.
    */
   boolean isCancelled();
 
@@ -133,12 +130,10 @@
   /**
    * Returns {@code true} if the request has completed.
    * <p>
-   * Completion may be due to normal termination, an exception, or
-   * cancellation. In all of these cases, this method will return
-   * {@code true}.
+   * Completion may be due to normal termination, an exception, or cancellation.
+   * In all of these cases, this method will return {@code true}.
    *
-   * @return {@code true} if the request has completed, otherwise
-   *         {@code false}.
+   * @return {@code true} if the request has completed, otherwise {@code false}.
    */
   boolean isDone();
 }
diff --git a/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java b/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java
index 143f85b..e3fb48f 100644
--- a/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java
+++ b/sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java
@@ -43,89 +43,17 @@
 
 
 /**
- * An heart beat connection factory can be used to create connections
- * that sends a periodic search request to a Directory Server.
+ * An heart beat connection factory can be used to create connections that sends
+ * a periodic search request to a Directory Server.
  */
-final class HeartBeatConnectionFactory extends
-    AbstractConnectionFactory
+final class HeartBeatConnectionFactory extends AbstractConnectionFactory
 {
-  private final SearchRequest heartBeat;
-
-  private final long timeout;
-
-  private final TimeUnit unit;
-
-  private final List<AsynchronousConnectionImpl> activeConnections;
-
-  private final ConnectionFactory parentFactory;
-
-
-
-  // FIXME: use a single global scheduler?
-
-  /**
-   * Creates a new heart-beat connection factory which will create
-   * connections using the provided connection factory and periodically
-   * ping any created connections in order to detect that they are still
-   * alive.
-   *
-   * @param connectionFactory
-   *          The connection factory to use for creating connections.
-   * @param timeout
-   *          The time to wait between keepalive pings.
-   * @param unit
-   *          The time unit of the timeout argument.
-   */
-  HeartBeatConnectionFactory(ConnectionFactory connectionFactory,
-      long timeout, TimeUnit unit)
-  {
-    this(connectionFactory, timeout, unit, DEFAULT_SEARCH);
-  }
-
-
-
-  private static final SearchRequest DEFAULT_SEARCH = Requests
-      .newSearchRequest("", SearchScope.BASE_OBJECT, "(objectClass=*)",
-          "1.1");
-
-
-
-  /**
-   * Creates a new heart-beat connection factory which will create
-   * connections using the provided connection factory and periodically
-   * ping any created connections using the specified search request in
-   * order to detect that they are still alive.
-   *
-   * @param connectionFactory
-   *          The connection factory to use for creating connections.
-   * @param timeout
-   *          The time to wait between keepalive pings.
-   * @param unit
-   *          The time unit of the timeout argument.
-   * @param heartBeat
-   *          The search request to use when pinging connections.
-   */
-  HeartBeatConnectionFactory(ConnectionFactory connectionFactory,
-      long timeout, TimeUnit unit, SearchRequest heartBeat)
-  {
-    this.heartBeat = heartBeat;
-    this.timeout = timeout;
-    this.unit = unit;
-    this.activeConnections = new LinkedList<AsynchronousConnectionImpl>();
-    this.parentFactory = connectionFactory;
-
-    new HeartBeatThread().start();
-  }
-
-
-
   /**
    * An asynchronous connection that sends heart beats and supports all
    * operations.
    */
   private final class AsynchronousConnectionImpl implements
-      AsynchronousConnection, ConnectionEventListener,
-      ResultHandler<Result>
+      AsynchronousConnection, ConnectionEventListener, ResultHandler<Result>
   {
     private final AsynchronousConnection connection;
 
@@ -135,24 +63,24 @@
 
 
 
-    private AsynchronousConnectionImpl(AsynchronousConnection connection)
+    private AsynchronousConnectionImpl(final AsynchronousConnection connection)
     {
       this.connection = connection;
     }
 
 
 
-    public void abandon(AbandonRequest request)
+    public FutureResult<Void> abandon(final AbandonRequest request)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
-      connection.abandon(request);
+      return connection.abandon(request);
     }
 
 
 
-    public FutureResult<Result> add(AddRequest request,
-        ResultHandler<Result> handler)
+    public FutureResult<Result> add(final AddRequest request,
+        final ResultHandler<Result> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -161,8 +89,29 @@
 
 
 
-    public FutureResult<BindResult> bind(BindRequest request,
-        ResultHandler<? super BindResult> handler)
+    public FutureResult<Result> add(final AddRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection
+          .add(request, resultHandler, intermediateResponseHandler);
+    }
+
+
+
+    public void addConnectionEventListener(
+        final ConnectionEventListener listener) throws IllegalStateException,
+        NullPointerException
+    {
+      connection.addConnectionEventListener(listener);
+    }
+
+
+
+    public FutureResult<BindResult> bind(final BindRequest request,
+        final ResultHandler<? super BindResult> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -171,6 +120,18 @@
 
 
 
+    public FutureResult<BindResult> bind(final BindRequest request,
+        final ResultHandler<? super BindResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.bind(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
     public void close()
     {
       synchronized (activeConnections)
@@ -183,7 +144,7 @@
 
 
 
-    public void close(UnbindRequest request, String reason)
+    public void close(final UnbindRequest request, final String reason)
         throws NullPointerException
     {
       synchronized (activeConnections)
@@ -196,8 +157,8 @@
 
 
 
-    public FutureResult<CompareResult> compare(CompareRequest request,
-        ResultHandler<? super CompareResult> handler)
+    public FutureResult<CompareResult> compare(final CompareRequest request,
+        final ResultHandler<? super CompareResult> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -206,8 +167,47 @@
 
 
 
-    public FutureResult<Result> delete(DeleteRequest request,
-        ResultHandler<Result> handler)
+    public FutureResult<CompareResult> compare(final CompareRequest request,
+        final ResultHandler<? super CompareResult> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.compare(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public void connectionClosed()
+    {
+      // Ignore - we intercept close through the close method.
+    }
+
+
+
+    public void connectionErrorOccurred(final boolean isDisconnectNotification,
+        final ErrorResultException error)
+    {
+      synchronized (activeConnections)
+      {
+        connection.removeConnectionEventListener(this);
+        activeConnections.remove(this);
+      }
+    }
+
+
+
+    public void connectionReceivedUnsolicitedNotification(
+        final ExtendedResult notification)
+    {
+      // Do nothing
+    }
+
+
+
+    public FutureResult<Result> delete(final DeleteRequest request,
+        final ResultHandler<Result> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -216,8 +216,20 @@
 
 
 
-    public <R extends Result> FutureResult<R> extendedRequest(
-        ExtendedRequest<R> request, ResultHandler<? super R> handler)
+    public FutureResult<Result> delete(final DeleteRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.delete(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+        final ExtendedRequest<R> request, final ResultHandler<? super R> handler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
@@ -226,34 +238,15 @@
 
 
 
-    public FutureResult<Result> modify(ModifyRequest request,
-        ResultHandler<Result> handler)
+    public <R extends ExtendedResult> FutureResult<R> extendedRequest(
+        final ExtendedRequest<R> request,
+        final ResultHandler<? super R> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
         throws UnsupportedOperationException, IllegalStateException,
         NullPointerException
     {
-      return connection.modify(request, handler);
-    }
-
-
-
-    public FutureResult<Result> modifyDN(ModifyDNRequest request,
-        ResultHandler<Result> handler)
-        throws UnsupportedOperationException, IllegalStateException,
-        NullPointerException
-    {
-      return connection.modifyDN(request, handler);
-    }
-
-
-
-    public FutureResult<Result> search(SearchRequest request,
-        ResultHandler<Result> resultHandler,
-        SearchResultHandler searchResultHandler)
-        throws UnsupportedOperationException, IllegalStateException,
-        NullPointerException
-    {
-      return connection.search(request, resultHandler,
-          searchResultHandler);
+      return connection.extendedRequest(request, resultHandler,
+          intermediateResponseHandler);
     }
 
 
@@ -261,81 +254,24 @@
     /**
      * {@inheritDoc}
      */
-    public FutureResult<SearchResultEntry> readEntry(DN name,
-        Collection<String> attributeDescriptions,
-        ResultHandler<? super SearchResultEntry> resultHandler)
-        throws UnsupportedOperationException, IllegalStateException,
-        NullPointerException
+    public Connection getSynchronousConnection()
     {
-      return connection.readEntry(name, attributeDescriptions,
-          resultHandler);
+      return new SynchronousConnection(this);
     }
 
 
 
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<SearchResultEntry> searchSingleEntry(
-        SearchRequest request,
-        ResultHandler<? super SearchResultEntry> resultHandler)
-        throws UnsupportedOperationException, IllegalStateException,
-        NullPointerException
+    public void handleErrorResult(final ErrorResultException error)
     {
-      return connection.searchSingleEntry(request, resultHandler);
+      connection.close(Requests.newUnbindRequest(), "Heartbeat retured error: "
+          + error);
     }
 
 
 
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<RootDSE> readRootDSE(
-        ResultHandler<RootDSE> handler)
-        throws UnsupportedOperationException, IllegalStateException
+    public void handleResult(final Result result)
     {
-      return connection.readRootDSE(handler);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<Schema> readSchemaForEntry(DN name,
-        ResultHandler<Schema> handler)
-        throws UnsupportedOperationException, IllegalStateException
-    {
-      return connection.readSchemaForEntry(name, handler);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public FutureResult<Schema> readSchema(DN name,
-        ResultHandler<Schema> handler)
-        throws UnsupportedOperationException, IllegalStateException
-    {
-      return connection.readSchema(name, handler);
-    }
-
-
-
-    public void addConnectionEventListener(
-        ConnectionEventListener listener) throws IllegalStateException,
-        NullPointerException
-    {
-      connection.addConnectionEventListener(listener);
-    }
-
-
-
-    public void removeConnectionEventListener(
-        ConnectionEventListener listener) throws NullPointerException
-    {
-      connection.removeConnectionEventListener(listener);
+      lastSuccessfulPing = System.currentTimeMillis();
     }
 
 
@@ -362,38 +298,178 @@
 
 
 
-    public void connectionReceivedUnsolicitedNotification(
-        GenericExtendedResult notification)
+    public FutureResult<Result> modify(final ModifyRequest request,
+        final ResultHandler<Result> handler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
     {
-      // Do nothing
+      return connection.modify(request, handler);
     }
 
 
 
-    public void connectionErrorOccurred(
-        boolean isDisconnectNotification, ErrorResultException error)
+    public FutureResult<Result> modify(final ModifyRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
     {
+      return connection.modify(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+        final ResultHandler<Result> handler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.modifyDN(request, handler);
+    }
+
+
+
+    public FutureResult<Result> modifyDN(final ModifyDNRequest request,
+        final ResultHandler<Result> resultHandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.modifyDN(request, resultHandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<SearchResultEntry> readEntry(final DN name,
+        final Collection<String> attributeDescriptions,
+        final ResultHandler<? super SearchResultEntry> resultHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.readEntry(name, attributeDescriptions, resultHandler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<RootDSE> readRootDSE(
+        final ResultHandler<RootDSE> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      return connection.readRootDSE(handler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<Schema> readSchema(final DN name,
+        final ResultHandler<Schema> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      return connection.readSchema(name, handler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<Schema> readSchemaForEntry(final DN name,
+        final ResultHandler<Schema> handler)
+        throws UnsupportedOperationException, IllegalStateException
+    {
+      return connection.readSchemaForEntry(name, handler);
+    }
+
+
+
+    public void removeConnectionEventListener(
+        final ConnectionEventListener listener) throws NullPointerException
+    {
+      connection.removeConnectionEventListener(listener);
+    }
+
+
+
+    public FutureResult<Result> search(final SearchRequest request,
+        final ResultHandler<Result> resultHandler,
+        final SearchResultHandler searchResultHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.search(request, resultHandler, searchResultHandler);
+    }
+
+
+
+    public FutureResult<Result> search(final SearchRequest request,
+        final ResultHandler<Result> resultHandler,
+        final SearchResultHandler searchResulthandler,
+        final IntermediateResponseHandler intermediateResponseHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.search(request, resultHandler, searchResulthandler,
+          intermediateResponseHandler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public FutureResult<SearchResultEntry> searchSingleEntry(
+        final SearchRequest request,
+        final ResultHandler<? super SearchResultEntry> resultHandler)
+        throws UnsupportedOperationException, IllegalStateException,
+        NullPointerException
+    {
+      return connection.searchSingleEntry(request, resultHandler);
+    }
+  }
+
+
+
+  private final class FutureResultImpl extends
+      FutureResultTransformer<AsynchronousConnection, AsynchronousConnection>
+      implements FutureResult<AsynchronousConnection>,
+      ResultHandler<AsynchronousConnection>
+  {
+
+    private FutureResultImpl(
+        final ResultHandler<? super AsynchronousConnection> handler)
+    {
+      super(handler);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected AsynchronousConnection transformResult(
+        final AsynchronousConnection connection) throws ErrorResultException
+    {
+      final AsynchronousConnectionImpl heartBeatConnection = new AsynchronousConnectionImpl(
+          connection);
       synchronized (activeConnections)
       {
-        connection.removeConnectionEventListener(this);
-        activeConnections.remove(this);
+        connection.addConnectionEventListener(heartBeatConnection);
+        activeConnections.add(heartBeatConnection);
       }
+      return heartBeatConnection;
     }
 
-
-
-    public void handleErrorResult(ErrorResultException error)
-    {
-      connection.close(Requests.newUnbindRequest(),
-          "Heartbeat retured error: " + error);
-    }
-
-
-
-    public void handleResult(Result result)
-    {
-      lastSuccessfulPing = System.currentTimeMillis();
-    }
   }
 
 
@@ -408,6 +484,7 @@
 
 
 
+    @Override
     public void run()
     {
       long startTime;
@@ -416,7 +493,7 @@
         startTime = System.currentTimeMillis();
         synchronized (activeConnections)
         {
-          for (AsynchronousConnectionImpl connection : activeConnections)
+          for (final AsynchronousConnectionImpl connection : activeConnections)
           {
             if (connection.lastPingFuture == null
                 || connection.lastPingFuture.isDone())
@@ -428,10 +505,14 @@
         }
         try
         {
-          sleep(unit.toMillis(timeout)
-              - (System.currentTimeMillis() - startTime));
+          final long sleepTime = unit.toMillis(timeout)
+              - (System.currentTimeMillis() - startTime);
+          if (sleepTime > 0)
+          {
+            sleep(sleepTime);
+          }
         }
-        catch (InterruptedException e)
+        catch (final InterruptedException e)
         {
           // Ignore
         }
@@ -441,47 +522,78 @@
 
 
 
-  private final class FutureResultImpl
-      extends
-      FutureResultTransformer<AsynchronousConnection, AsynchronousConnection>
-      implements FutureResult<AsynchronousConnection>,
-      ResultHandler<AsynchronousConnection>
+  private final SearchRequest heartBeat;
+
+  private final long timeout;
+
+  // FIXME: use a single global scheduler?
+
+  private final TimeUnit unit;
+
+  private final List<AsynchronousConnectionImpl> activeConnections;
+
+  private final ConnectionFactory parentFactory;
+
+  private static final SearchRequest DEFAULT_SEARCH = Requests
+      .newSearchRequest("", SearchScope.BASE_OBJECT, "(objectClass=*)", "1.1");
+
+
+
+  /**
+   * Creates a new heart-beat connection factory which will create connections
+   * using the provided connection factory and periodically ping any created
+   * connections in order to detect that they are still alive.
+   *
+   * @param connectionFactory
+   *          The connection factory to use for creating connections.
+   * @param timeout
+   *          The time to wait between keepalive pings.
+   * @param unit
+   *          The time unit of the timeout argument.
+   */
+  HeartBeatConnectionFactory(final ConnectionFactory connectionFactory,
+      final long timeout, final TimeUnit unit)
   {
-
-    private FutureResultImpl(
-        ResultHandler<? super AsynchronousConnection> handler)
-    {
-      super(handler);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    protected AsynchronousConnection transformResult(
-        AsynchronousConnection connection) throws ErrorResultException
-    {
-      AsynchronousConnectionImpl heartBeatConnection = new AsynchronousConnectionImpl(
-          connection);
-      synchronized (activeConnections)
-      {
-        connection.addConnectionEventListener(heartBeatConnection);
-        activeConnections.add(heartBeatConnection);
-      }
-      return heartBeatConnection;
-    }
-
+    this(connectionFactory, timeout, unit, DEFAULT_SEARCH);
   }
 
 
 
-  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
-      ResultHandler<AsynchronousConnection> handler)
+  /**
+   * Creates a new heart-beat connection factory which will create connections
+   * using the provided connection factory and periodically ping any created
+   * connections using the specified search request in order to detect that they
+   * are still alive.
+   *
+   * @param connectionFactory
+   *          The connection factory to use for creating connections.
+   * @param timeout
+   *          The time to wait between keepalive pings.
+   * @param unit
+   *          The time unit of the timeout argument.
+   * @param heartBeat
+   *          The search request to use when pinging connections.
+   */
+  HeartBeatConnectionFactory(final ConnectionFactory connectionFactory,
+      final long timeout, final TimeUnit unit, final SearchRequest heartBeat)
   {
-    FutureResultImpl future = new FutureResultImpl(handler);
-    future.setFutureResult(parentFactory
-        .getAsynchronousConnection(future));
+    this.heartBeat = heartBeat;
+    this.timeout = timeout;
+    this.unit = unit;
+    this.activeConnections = new LinkedList<AsynchronousConnectionImpl>();
+    this.parentFactory = connectionFactory;
+
+    new HeartBeatThread().start();
+  }
+
+
+
+  @Override
+  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      final ResultHandler<AsynchronousConnection> handler)
+  {
+    final FutureResultImpl future = new FutureResultImpl(handler);
+    future.setFutureResult(parentFactory.getAsynchronousConnection(future));
     return future;
   }
 }
diff --git a/sdk/src/org/opends/sdk/IntermediateResponseHandler.java b/sdk/src/org/opends/sdk/IntermediateResponseHandler.java
new file mode 100644
index 0000000..43573da
--- /dev/null
+++ b/sdk/src/org/opends/sdk/IntermediateResponseHandler.java
@@ -0,0 +1,69 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import org.opends.sdk.responses.IntermediateResponse;
+
+
+
+/**
+ * A completion handler for consuming intermediate responses returned from
+ * extended operations, or other operations for which an appropriate control was
+ * sent.
+ * <p>
+ * {@link Connection} objects support intermediate responses for extended
+ * operations only via the {@link Connection#extendedRequest}
+ * method. {@link AsynchronousConnection} objects support intermediate responses
+ * for extended operations, and all other operation types for which appropriate
+ * controls were used. When no handler is provided any intermediate responses
+ * will be discarded.
+ * <p>
+ * The {@link #handleIntermediateResponse} method is invoked each time a
+ * Intermediate Response is returned from the Directory Server.
+ * <p>
+ * Implementations of these methods should complete in a timely manner so as to
+ * avoid keeping the invoking thread from dispatching to other completion
+ * handlers.
+ */
+public interface IntermediateResponseHandler
+{
+  /**
+   * Invoked each time an intermediate response is returned from the Directory
+   * Server.
+   *
+   * @param response
+   *          The intermediate response.
+   * @return {@code true} if this handler should continue to be notified of any
+   *         remaining intermediate responses, or {@code false} if the remaining
+   *         responses should be skipped for some reason (e.g. a client side
+   *         size limit has been reached).
+   */
+  boolean handleIntermediateResponse(IntermediateResponse response);
+}
diff --git a/sdk/src/org/opends/sdk/InternalConnectionFactory.java b/sdk/src/org/opends/sdk/InternalConnectionFactory.java
new file mode 100644
index 0000000..ba990db
--- /dev/null
+++ b/sdk/src/org/opends/sdk/InternalConnectionFactory.java
@@ -0,0 +1,88 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import com.sun.opends.sdk.ldap.InternalConnection;
+import com.sun.opends.sdk.util.CompletedFutureResult;
+
+
+
+/**
+ * A special {@code ConnectionFactory} that can be used to perform internal
+ * operations against a {@code ServerConnectionFactory} implementation.
+ *
+ * @param <C>
+ *          The type of client context.
+ */
+final class InternalConnectionFactory<C> extends AbstractConnectionFactory
+{
+
+  private final ServerConnectionFactory<C, Integer> factory;
+
+  private final C clientContext;
+
+
+
+  InternalConnectionFactory(final ServerConnectionFactory<C, Integer> factory,
+      final C clientContext)
+  {
+    this.factory = factory;
+    this.clientContext = clientContext;
+  }
+
+
+
+  @Override
+  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      final ResultHandler<AsynchronousConnection> handler)
+  {
+    final ServerConnection<Integer> serverConnection;
+    try
+    {
+      serverConnection = factory.accept(clientContext);
+    }
+    catch (final ErrorResultException e)
+    {
+      if (handler != null)
+      {
+        handler.handleErrorResult(e);
+      }
+      return new CompletedFutureResult<AsynchronousConnection>(e);
+    }
+
+    final InternalConnection connection = new InternalConnection(
+        serverConnection);
+    if (handler != null)
+    {
+      handler.handleResult(connection);
+    }
+    return new CompletedFutureResult<AsynchronousConnection>(connection);
+  }
+}
diff --git a/sdk/src/org/opends/sdk/KeyManagers.java b/sdk/src/org/opends/sdk/KeyManagers.java
new file mode 100644
index 0000000..ecd45ea
--- /dev/null
+++ b/sdk/src/org/opends/sdk/KeyManagers.java
@@ -0,0 +1,402 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.net.Socket;
+import java.security.*;
+import java.security.cert.X509Certificate;
+
+import javax.net.ssl.*;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * This class contains methods for creating common types of key manager.
+ */
+public final class KeyManagers
+{
+  /**
+   * This class implements an X.509 key manager that will be used to wrap an
+   * existing key manager and makes it possible to configure which
+   * certificate(s) should be used for client and/or server operations. The
+   * certificate selection will be based on the alias (also called the nickname)
+   * of the certificate.
+   */
+  private static final class SelectCertificate extends X509ExtendedKeyManager
+  {
+    private final String alias;
+    private final X509KeyManager keyManager;
+
+
+
+    private SelectCertificate(final X509KeyManager keyManager,
+        final String alias)
+    {
+      this.keyManager = keyManager;
+      this.alias = alias;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String chooseClientAlias(final String[] keyType,
+        final Principal[] issuers, final Socket socket)
+    {
+      for (final String type : keyType)
+      {
+        final String[] clientAliases = keyManager.getClientAliases(type,
+            issuers);
+        if (clientAliases != null)
+        {
+          for (final String clientAlias : clientAliases)
+          {
+            if (clientAlias.equals(alias))
+            {
+              return alias;
+            }
+          }
+        }
+      }
+
+      return null;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String chooseEngineClientAlias(final String[] keyType,
+        final Principal[] issuers, final SSLEngine engine)
+    {
+      for (final String type : keyType)
+      {
+        final String[] clientAliases = keyManager.getClientAliases(type,
+            issuers);
+        if (clientAliases != null)
+        {
+          for (final String clientAlias : clientAliases)
+          {
+            if (clientAlias.equals(alias))
+            {
+              return alias;
+            }
+          }
+        }
+      }
+
+      return null;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public String chooseEngineServerAlias(final String keyType,
+        final Principal[] issuers, final SSLEngine engine)
+    {
+      final String[] serverAliases = keyManager.getServerAliases(keyType,
+          issuers);
+      if (serverAliases != null)
+      {
+        for (final String serverAlias : serverAliases)
+        {
+          if (serverAlias.equalsIgnoreCase(alias))
+          {
+            return serverAlias;
+          }
+        }
+      }
+
+      return null;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String chooseServerAlias(final String keyType,
+        final Principal[] issuers, final Socket socket)
+    {
+      final String[] serverAliases = keyManager.getServerAliases(keyType,
+          issuers);
+      if (serverAliases != null)
+      {
+        for (final String serverAlias : serverAliases)
+        {
+          if (serverAlias.equals(alias))
+          {
+            return alias;
+          }
+        }
+      }
+
+      return null;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public X509Certificate[] getCertificateChain(final String alias)
+    {
+      return keyManager.getCertificateChain(alias);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String[] getClientAliases(final String keyType,
+        final Principal[] issuers)
+    {
+      return keyManager.getClientAliases(keyType, issuers);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public PrivateKey getPrivateKey(final String alias)
+    {
+      return keyManager.getPrivateKey(alias);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public String[] getServerAliases(final String keyType,
+        final Principal[] issuers)
+    {
+      return keyManager.getServerAliases(keyType, issuers);
+    }
+  }
+
+
+
+  /**
+   * Creates a new {@code X509KeyManager} which will use the named key store
+   * file for retrieving certificates. It will use the default key store format
+   * for the JVM (e.g. {@code JKS}) and will not use a password to open the key
+   * store.
+   *
+   * @param file
+   *          The key store file name.
+   * @return A new {@code X509KeyManager} which will use the named key store
+   *         file for retrieving certificates.
+   * @throws GeneralSecurityException
+   *           If the key store could not be loaded, perhaps due to incorrect
+   *           format, or missing algorithms.
+   * @throws IOException
+   *           If the key store file could not be found or could not be read.
+   * @throws NullPointerException
+   *           If {@code file} was {@code null}.
+   */
+  public static X509KeyManager useKeyStoreFile(final String file)
+      throws GeneralSecurityException, IOException, NullPointerException
+  {
+    return useKeyStoreFile(file, null, null);
+  }
+
+
+
+  /**
+   * Creates a new {@code X509KeyManager} which will use the named key store
+   * file for retrieving certificates. It will use the provided key store format
+   * and password.
+   *
+   * @param file
+   *          The key store file name.
+   * @param password
+   *          The key store password, which may be {@code null}.
+   * @param format
+   *          The key store format, which may be {@code null} to indicate that
+   *          the default key store format for the JVM (e.g. {@code JKS}) should
+   *          be used.
+   * @return A new {@code X509KeyManager} which will use the named key store
+   *         file for retrieving certificates.
+   * @throws GeneralSecurityException
+   *           If the key store could not be loaded, perhaps due to incorrect
+   *           format, or missing algorithms.
+   * @throws IOException
+   *           If the key store file could not be found or could not be read.
+   * @throws NullPointerException
+   *           If {@code file} was {@code null}.
+   */
+  public static X509KeyManager useKeyStoreFile(final String file,
+      final String password, final String format)
+      throws GeneralSecurityException, IOException, NullPointerException
+  {
+    Validator.ensureNotNull(file);
+
+    final File keyStoreFile = new File(file);
+    final char[] keyStorePassword = password != null ? password.toCharArray()
+        : null;
+    final String keyStoreFormat = format != null ? format : KeyStore
+        .getDefaultType();
+
+    final KeyStore keyStore = KeyStore.getInstance(keyStoreFormat);
+
+    FileInputStream fos = null;
+    try
+    {
+      fos = new FileInputStream(keyStoreFile);
+      keyStore.load(fos, keyStorePassword);
+    }
+    finally
+    {
+      if (fos != null)
+      {
+        try
+        {
+          fos.close();
+        }
+        catch (final IOException ignored)
+        {
+          // Ignore.
+        }
+      }
+    }
+
+    final KeyManagerFactory kmf = KeyManagerFactory
+        .getInstance(KeyManagerFactory.getDefaultAlgorithm());
+    kmf.init(keyStore, keyStorePassword);
+
+    X509KeyManager x509km = null;
+    for (final KeyManager km : kmf.getKeyManagers())
+    {
+      if (km instanceof X509KeyManager)
+      {
+        x509km = (X509KeyManager) km;
+        break;
+      }
+    }
+
+    if (x509km == null)
+    {
+      throw new NoSuchAlgorithmException();
+    }
+
+    return x509km;
+  }
+
+
+
+  /**
+   * Creates a new {@code X509KeyManager} which will use a PKCS#11 token for
+   * retrieving certificates.
+   *
+   * @param password
+   *          The password to use for accessing the PKCS#11 token, which may be
+   *          {@code null} if no password is required.
+   * @return A new {@code X509KeyManager} which will use a PKCS#11 token for
+   *         retrieving certificates.
+   * @throws GeneralSecurityException
+   *           If the PKCS#11 token could not be accessed, perhaps due to
+   *           incorrect password, or missing algorithms.
+   * @throws IOException
+   *           If the PKCS#11 token could not be found or could not be read.
+   */
+  public static X509KeyManager usePKCS11Token(final String password)
+      throws GeneralSecurityException, IOException
+  {
+    final char[] keyStorePassword = password != null ? password.toCharArray()
+        : null;
+    final KeyStore keyStore = KeyStore.getInstance("PKCS11");
+    keyStore.load(null, keyStorePassword);
+    final KeyManagerFactory kmf = KeyManagerFactory
+        .getInstance(KeyManagerFactory.getDefaultAlgorithm());
+    kmf.init(keyStore, keyStorePassword);
+
+    X509KeyManager x509km = null;
+    for (final KeyManager km : kmf.getKeyManagers())
+    {
+      if (km instanceof X509KeyManager)
+      {
+        x509km = (X509KeyManager) km;
+        break;
+      }
+    }
+
+    if (x509km == null)
+    {
+      throw new NoSuchAlgorithmException();
+    }
+
+    return x509km;
+  }
+
+
+
+  /**
+   * Returns a new {@code X509KeyManager} which selects the named certificate
+   * from the provided {@code X509KeyManager}.
+   *
+   * @param alias
+   *          The nickname of the certificate that should be selected for
+   *          operations involving this key manager.
+   * @param keyManager
+   *          The key manager to be filtered.
+   * @return The filtered key manager.
+   * @throws NullPointerException
+   *           If {@code keyManager} or {@code alias} was {@code null}.
+   */
+  public static X509KeyManager useSingleCertificate(final String alias,
+      final X509KeyManager keyManager) throws NullPointerException
+  {
+    Validator.ensureNotNull(alias, keyManager);
+    return new SelectCertificate(keyManager, alias);
+  }
+
+
+
+  // Prevent insantiation.
+  private KeyManagers()
+  {
+    // Nothing to do.
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/LDAPClientContext.java b/sdk/src/org/opends/sdk/LDAPClientContext.java
new file mode 100644
index 0000000..194c7c4
--- /dev/null
+++ b/sdk/src/org/opends/sdk/LDAPClientContext.java
@@ -0,0 +1,118 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.net.InetSocketAddress;
+
+import javax.net.ssl.SSLContext;
+
+import org.opends.sdk.responses.ExtendedResult;
+
+
+
+/**
+ * An LDAP client which has connected to a {@link ServerConnectionFactory}. The
+ * LDAP client context can be used to query information about the client's
+ * connection such as their network address, as well as managing the state of
+ * the connection.
+ */
+public interface LDAPClientContext
+{
+  /**
+   * Disconnects the client and optionally sends a disconnect notification.
+   *
+   * @param sendNotification
+   *          {@code true} to send a disconnect notification, or {@code false}
+   *          otherwise.
+   */
+  void disconnect(boolean sendNotification);
+
+
+
+  /**
+   * Returns the {@code InetSocketAddress} associated with the local system.
+   *
+   * @return The {@code InetSocketAddress} associated with the local system.
+   */
+  InetSocketAddress getLocalAddress();
+
+
+
+  /**
+   * Returns the {@code InetSocketAddress} associated with the remote system.
+   *
+   * @return The {@code InetSocketAddress} associated with the remote system.
+   */
+  InetSocketAddress getPeerAddress();
+
+
+
+  /**
+   * Returns the strongest cipher strength currently in use by the underlying
+   * connection.
+   *
+   * @return The strongest cipher strength currently in use by the underlying
+   *         connection.
+   */
+  int getSecurityStrengthFactor();
+
+
+
+  /**
+   * Sends an unsolicited notification to the client.
+   *
+   * @param notification
+   *          The notification to send.
+   */
+  void sendUnsolicitedNotification(ExtendedResult notification);
+
+
+
+  /**
+   * Starts the SASL integrity and/or confidentiality protection layer on the
+   * underlying connection if possible.
+   *
+   * @param bindContext
+   *          The negotiated bind context that can be used to encode and decode
+   *          data on the connection.
+   */
+  void startSASL(ConnectionSecurityLayer bindContext);
+
+
+
+  /**
+   * Starts the TLS/SSL security layer on the underlying connection if possible.
+   *
+   * @param sslContext
+   *          The {@code SSLContext} which should be used to secure the
+   *          connection.
+   */
+  void startTLS(SSLContext sslContext);
+}
diff --git a/sdk/src/org/opends/sdk/LDAPConnectionFactory.java b/sdk/src/org/opends/sdk/LDAPConnectionFactory.java
new file mode 100644
index 0000000..25a52e6
--- /dev/null
+++ b/sdk/src/org/opends/sdk/LDAPConnectionFactory.java
@@ -0,0 +1,152 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+import com.sun.opends.sdk.ldap.LDAPConnectionFactoryImpl;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * A factory class which can be used to obtain connections to an LDAP Directory
+ * Server.
+ */
+public final class LDAPConnectionFactory implements ConnectionFactory
+{
+  // We implement the factory using the pimpl idiom in order have
+  // cleaner Javadoc which does not expose implementation methods from
+  // AbstractConnectionFactory.
+
+  private final LDAPConnectionFactoryImpl impl;
+
+
+
+  /**
+   * Creates a new LDAP connection factory which can be used to create LDAP
+   * connections to the Directory Server at the provided address.
+   *
+   * @param address
+   *          The address of the Directory Server.
+   * @throws NullPointerException
+   *           If {@code address} was {@code null}.
+   */
+  public LDAPConnectionFactory(final SocketAddress address)
+      throws NullPointerException
+  {
+    this(address, new LDAPOptions());
+  }
+
+
+
+  /**
+   * Creates a new LDAP connection factory which can be used to create LDAP
+   * connections to the Directory Server at the provided address.
+   *
+   * @param address
+   *          The address of the Directory Server.
+   * @param options
+   *          The LDAP options to use when creating connections.
+   * @throws NullPointerException
+   *           If {@code address} or {@code options} was {@code null}.
+   */
+  public LDAPConnectionFactory(final SocketAddress address,
+      final LDAPOptions options) throws NullPointerException
+  {
+    Validator.ensureNotNull(address, options);
+    this.impl = new LDAPConnectionFactoryImpl(address, options);
+  }
+
+
+
+  /**
+   * Creates a new LDAP connection factory which can be used to create LDAP
+   * connections to the Directory Server at the provided host and port address.
+   *
+   * @param host
+   *          The host name.
+   * @param port
+   *          The port number.
+   * @throws NullPointerException
+   *           If {@code host} was {@code null}.
+   */
+  public LDAPConnectionFactory(final String host, final int port)
+      throws NullPointerException
+  {
+    this(host, port, new LDAPOptions());
+  }
+
+
+
+  /**
+   * Creates a new LDAP connection factory which can be used to create LDAP
+   * connections to the Directory Server at the provided host and port address.
+   *
+   * @param host
+   *          The host name.
+   * @param port
+   *          The port number.
+   * @param options
+   *          The LDAP options to use when creating connections.
+   * @throws NullPointerException
+   *           If {@code host} or {@code options} was {@code null}.
+   */
+  public LDAPConnectionFactory(final String host, final int port,
+      final LDAPOptions options) throws NullPointerException
+  {
+    Validator.ensureNotNull(host, options);
+    final SocketAddress address = new InetSocketAddress(host, port);
+    this.impl = new LDAPConnectionFactoryImpl(address, options);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      final ResultHandler<AsynchronousConnection> handler)
+  {
+    return impl.getAsynchronousConnection(handler);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Connection getConnection() throws ErrorResultException,
+      InterruptedException
+  {
+    return impl.getConnection();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/LDAPListener.java b/sdk/src/org/opends/sdk/LDAPListener.java
new file mode 100644
index 0000000..6038cba
--- /dev/null
+++ b/sdk/src/org/opends/sdk/LDAPListener.java
@@ -0,0 +1,281 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+
+import com.sun.opends.sdk.ldap.LDAPListenerImpl;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * An LDAP server connection listener which waits for LDAP connection requests
+ * to come in over the network and binds them to a {@link ServerConnection}.
+ * <p>
+ * The following code illustrates how to create a simple LDAP server:
+ *
+ * <pre>
+ * class MyClientConnection implements ServerConnection&lt;Integer&gt;
+ * {
+ *   private final LDAPClientContext clientContext;
+ *
+ *
+ *
+ *   private MyClientConnection(LDAPClientContext clientContext)
+ *   {
+ *     this.clientContext = clientContext;
+ *   }
+ *
+ *
+ *
+ *   public void add(Integer context, AddRequest request,
+ *       ResultHandler&lt;Result&gt; handler,
+ *       IntermediateResponseHandler intermediateResponseHandler)
+ *       throws UnsupportedOperationException
+ *   {
+ *     // ...
+ *   }
+ *
+ *   // ...
+ *
+ * }
+ *
+ *
+ *
+ * class MyServer implements ServerConnectionFactory&lt;LDAPClientContext, Integer&gt;
+ * {
+ *   public ServerConnection&lt;Integer&gt; accept(LDAPClientContext context)
+ *   {
+ *     System.out.println(&quot;Connection from: &quot; + context.getPeerAddress());
+ *     return new MyClientConnection(context);
+ *   }
+ * }
+ *
+ *
+ *
+ * public static void main(String[] args) throws Exception
+ * {
+ *   LDAPListener listener = new LDAPListener(1389, new MyServer());
+ *
+ *   // ...
+ *
+ *   listener.close();
+ * }
+ * </pre>
+ */
+public final class LDAPListener implements Closeable
+{
+  // We implement the factory using the pimpl idiom in order have
+  // cleaner Javadoc which does not expose implementation methods.
+
+  private final LDAPListenerImpl impl;
+
+
+
+  /**
+   * Creates a new LDAP listener implementation which will listen for LDAP
+   * client connections at the provided address.
+   *
+   * @param port
+   *          The port to listen on.
+   * @param factory
+   *          The server connection factory which will be used to create server
+   *          connections.
+   * @throws IOException
+   *           If an error occurred while trying to listen on the provided
+   *           address.
+   * @throws NullPointerException
+   *           If {code factory} was {@code null}.
+   */
+  public LDAPListener(final int port,
+      final ServerConnectionFactory<LDAPClientContext, Integer> factory)
+      throws IOException, NullPointerException
+  {
+    this(port, factory, new LDAPListenerOptions());
+  }
+
+
+
+  /**
+   * Creates a new LDAP listener implementation which will listen for LDAP
+   * client connections at the provided address.
+   *
+   * @param port
+   *          The port to listen on.
+   * @param factory
+   *          The server connection factory which will be used to create server
+   *          connections.
+   * @param options
+   *          The LDAP listener options.
+   * @throws IOException
+   *           If an error occurred while trying to listen on the provided
+   *           address.
+   * @throws NullPointerException
+   *           If {code factory} or {@code options} was {@code null}.
+   */
+  public LDAPListener(final int port,
+      final ServerConnectionFactory<LDAPClientContext, Integer> factory,
+      final LDAPListenerOptions options) throws IOException,
+      NullPointerException
+  {
+    Validator.ensureNotNull(factory, options);
+    final SocketAddress address = new InetSocketAddress(port);
+    this.impl = new LDAPListenerImpl(address, factory, options);
+  }
+
+
+
+  /**
+   * Creates a new LDAP listener implementation which will listen for LDAP
+   * client connections at the provided address.
+   *
+   * @param port
+   *          The port to listen on.
+   * @param host
+   *          The address to listen on.
+   * @param factory
+   *          The server connection factory which will be used to create server
+   *          connections.
+   * @throws IOException
+   *           If an error occurred while trying to listen on the provided
+   *           address.
+   * @throws NullPointerException
+   *           If {@code host} or {code factory} was {@code null}.
+   */
+  public LDAPListener(final int port, final String host,
+      final ServerConnectionFactory<LDAPClientContext, Integer> factory)
+      throws IOException, NullPointerException
+  {
+    this(port, host, factory, new LDAPListenerOptions());
+  }
+
+
+
+  /**
+   * Creates a new LDAP listener implementation which will listen for LDAP
+   * client connections at the provided address.
+   *
+   * @param port
+   *          The port to listen on.
+   * @param host
+   *          The address to listen on.
+   * @param factory
+   *          The server connection factory which will be used to create server
+   *          connections.
+   * @param options
+   *          The LDAP listener options.
+   * @throws IOException
+   *           If an error occurred while trying to listen on the provided
+   *           address.
+   * @throws NullPointerException
+   *           If {@code host}, {code factory}, or {@code options} was {@code
+   *           null}.
+   */
+  public LDAPListener(final int port, final String host,
+      final ServerConnectionFactory<LDAPClientContext, Integer> factory,
+      final LDAPListenerOptions options) throws IOException,
+      NullPointerException
+  {
+    Validator.ensureNotNull(host, factory, options);
+    final SocketAddress address = new InetSocketAddress(host, port);
+    this.impl = new LDAPListenerImpl(address, factory, options);
+  }
+
+
+
+  /**
+   * Creates a new LDAP listener implementation which will listen for LDAP
+   * client connections at the provided address.
+   *
+   * @param address
+   *          The address to listen on.
+   * @param factory
+   *          The server connection factory which will be used to create server
+   *          connections.
+   * @throws IOException
+   *           If an error occurred while trying to listen on the provided
+   *           address.
+   * @throws NullPointerException
+   *           If {@code address} or {code factory} was {@code null}.
+   */
+  public LDAPListener(final SocketAddress address,
+      final ServerConnectionFactory<LDAPClientContext, Integer> factory)
+      throws IOException, NullPointerException
+  {
+    this(address, factory, new LDAPListenerOptions());
+  }
+
+
+
+  /**
+   * Creates a new LDAP listener implementation which will listen for LDAP
+   * client connections at the provided address.
+   *
+   * @param address
+   *          The address to listen on.
+   * @param factory
+   *          The server connection factory which will be used to create server
+   *          connections.
+   * @param options
+   *          The LDAP listener options.
+   * @throws IOException
+   *           If an error occurred while trying to listen on the provided
+   *           address.
+   * @throws NullPointerException
+   *           If {@code address}, {code factory}, or {@code options} was
+   *           {@code null}.
+   */
+  public LDAPListener(final SocketAddress address,
+      final ServerConnectionFactory<LDAPClientContext, Integer> factory,
+      final LDAPListenerOptions options) throws IOException,
+      NullPointerException
+  {
+    Validator.ensureNotNull(address, factory, options);
+    this.impl = new LDAPListenerImpl(address, factory, options);
+  }
+
+
+
+  /**
+   * Closes this LDAP connection listener.
+   *
+   * @throws IOException
+   *           If an IO error occurred while closing this listener.
+   */
+  public void close() throws IOException
+  {
+    impl.close();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/LDAPListenerOptions.java b/sdk/src/org/opends/sdk/LDAPListenerOptions.java
new file mode 100644
index 0000000..472688d
--- /dev/null
+++ b/sdk/src/org/opends/sdk/LDAPListenerOptions.java
@@ -0,0 +1,183 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import javax.net.ssl.SSLContext;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * Common options for LDAP listeners.
+ */
+public class LDAPListenerOptions
+{
+
+  private SSLContext sslContext;
+
+  private DecodeOptions decodeOptions;
+
+  private int backlog;
+
+
+
+  /**
+   * Creates a new set of listener options with default settings. SSL will not
+   * be enabled, and a default set of decode options will be used.
+   */
+  public LDAPListenerOptions()
+  {
+    this.sslContext = null;
+    this.backlog = 0;
+    this.decodeOptions = new DecodeOptions();
+  }
+
+
+
+  /**
+   * Creates a new set of listener options having the same initial set of
+   * options as the provided set of listener options.
+   *
+   * @param options
+   *          The set of listener options to be copied.
+   */
+  public LDAPListenerOptions(final LDAPListenerOptions options)
+  {
+    this.sslContext = options.sslContext;
+    this.backlog = options.backlog;
+    this.decodeOptions = new DecodeOptions(options.decodeOptions);
+  }
+
+
+
+  /**
+   * Returns the maximum queue length for incoming connections requests. If a
+   * connection request arrives when the queue is full, the connection is
+   * refused. If the backlog is less than {@code 1} then a default value of
+   * {@code 50} will be used.
+   *
+   * @return The maximum queue length for incoming connections requests.
+   */
+  public final int getBacklog()
+  {
+    return backlog;
+  }
+
+
+
+  /**
+   * Returns the decoding options which will be used to control how requests and
+   * responses are decoded.
+   *
+   * @return The decoding options which will be used to control how requests and
+   *         responses are decoded (never {@code null}).
+   */
+  public final DecodeOptions getDecodeOptions()
+  {
+    return decodeOptions;
+  }
+
+
+
+  /**
+   * Returns the SSL context which will be used when initiating connections with
+   * the Directory Server. By default no SSL context will be used, indicating
+   * that connections will not be secured. If a non-{@code null} SSL context is
+   * returned then connections will be secured using either SSL or StartTLS.
+   *
+   * @return The SSL context which will be used when initiating secure
+   *         connections with the Directory Server, which may be {@code null}
+   *         indicating that connections will not be secured.
+   */
+  public final SSLContext getSSLContext()
+  {
+    return sslContext;
+  }
+
+
+
+  /**
+   * Sets the maximum queue length for incoming connections requests. If a
+   * connection request arrives when the queue is full, the connection is
+   * refused. If the backlog is less than {@code 1} then a default value of
+   * {@code 50} will be used.
+   *
+   * @param backlog
+   *          The maximum queue length for incoming connections requests.
+   * @return A reference to this LDAP listener options.
+   */
+  public final LDAPListenerOptions setBacklog(final int backlog)
+  {
+    this.backlog = backlog;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the decoding options which will be used to control how requests and
+   * responses are decoded.
+   *
+   * @param decodeOptions
+   *          The decoding options which will be used to control how requests
+   *          and responses are decoded (never {@code null}).
+   * @return A reference to this LDAP listener options.
+   * @throws NullPointerException
+   *           If {@code decodeOptions} was {@code null}.
+   */
+  public final LDAPListenerOptions setDecodeOptions(
+      final DecodeOptions decodeOptions) throws NullPointerException
+  {
+    Validator.ensureNotNull(decodeOptions);
+    this.decodeOptions = decodeOptions;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the SSL context which will be used when initiating connections with
+   * the Directory Server. By default no SSL context will be used, indicating
+   * that connections will not be secured. If a non-{@code null} SSL context is
+   * returned then connections will be secured using either SSL or StartTLS.
+   *
+   * @param sslContext
+   *          The SSL context which will be used when initiating secure
+   *          connections with the Directory Server, which may be {@code null}
+   *          indicating that connections will not be secured.
+   * @return A reference to this LDAP listener options.
+   */
+  public final LDAPListenerOptions setSSLContext(final SSLContext sslContext)
+  {
+    this.sslContext = sslContext;
+    return this;
+  }
+}
diff --git a/sdk/src/org/opends/sdk/LDAPOptions.java b/sdk/src/org/opends/sdk/LDAPOptions.java
new file mode 100644
index 0000000..0c17217
--- /dev/null
+++ b/sdk/src/org/opends/sdk/LDAPOptions.java
@@ -0,0 +1,227 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.util.concurrent.TimeUnit;
+
+import javax.net.ssl.SSLContext;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * Common options for LDAP client connections.
+ */
+public class LDAPOptions
+{
+  private SSLContext sslContext;
+
+  private boolean useStartTLS;
+
+  private long timeoutInMillis;
+
+  private DecodeOptions decodeOptions;
+
+
+
+  /**
+   * Creates a new set of connection options with default settings. SSL will not
+   * be enabled, and a default set of decode options will be used.
+   */
+  public LDAPOptions()
+  {
+    super();
+    this.sslContext = null;
+    this.timeoutInMillis = 0;
+    this.useStartTLS = false;
+    this.decodeOptions = new DecodeOptions();
+  }
+
+
+
+  /**
+   * Creates a new set of connection options having the same initial set of
+   * options as the provided set of connection options.
+   *
+   * @param options
+   *          The set of connection options to be copied.
+   */
+  public LDAPOptions(final LDAPOptions options)
+  {
+    this.sslContext = options.sslContext;
+    this.timeoutInMillis = options.timeoutInMillis;
+    this.useStartTLS = options.useStartTLS;
+    this.decodeOptions = new DecodeOptions(options.decodeOptions);
+  }
+
+
+
+  /**
+   * Returns the decoding options which will be used to control how requests and
+   * responses are decoded.
+   *
+   * @return The decoding options which will be used to control how requests and
+   *         responses are decoded (never {@code null}).
+   */
+  public final DecodeOptions getDecodeOptions()
+  {
+    return decodeOptions;
+  }
+
+
+
+  /**
+   * Returns the SSL context which will be used when initiating connections with
+   * the Directory Server. By default no SSL context will be used, indicating
+   * that connections will not be secured. If a non-{@code null} SSL context is
+   * returned then connections will be secured using either SSL or StartTLS
+   * depending on {@link #useStartTLS()}.
+   *
+   * @return The SSL context which will be used when initiating secure
+   *         connections with the Directory Server, which may be {@code null}
+   *         indicating that connections will not be secured.
+   */
+  public final SSLContext getSSLContext()
+  {
+    return sslContext;
+  }
+
+
+
+  /**
+   * Returns the operation timeout in the specified unit.
+   *
+   * @param unit
+   *          The time unit of use.
+   * @return The operation timeout.
+   */
+  public final long getTimeout(final TimeUnit unit)
+  {
+    return unit.convert(timeoutInMillis, TimeUnit.MILLISECONDS);
+  }
+
+
+
+  /**
+   * Sets the decoding options which will be used to control how requests and
+   * responses are decoded.
+   *
+   * @param decodeOptions
+   *          The decoding options which will be used to control how requests
+   *          and responses are decoded (never {@code null}).
+   * @return A reference to this LDAP connection options.
+   * @throws NullPointerException
+   *           If {@code decodeOptions} was {@code null}.
+   */
+  public final LDAPOptions setDecodeOptions(final DecodeOptions decodeOptions)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(decodeOptions);
+    this.decodeOptions = decodeOptions;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the SSL context which will be used when initiating connections with
+   * the Directory Server. By default no SSL context will be used, indicating
+   * that connections will not be secured. If a non-{@code null} SSL context is
+   * returned then connections will be secured using either SSL or StartTLS
+   * depending on {@link #useStartTLS()}.
+   *
+   * @param sslContext
+   *          The SSL context which will be used when initiating secure
+   *          connections with the Directory Server, which may be {@code null}
+   *          indicating that connections will not be secured.
+   * @return A reference to this LDAP connection options.
+   */
+  public final LDAPOptions setSSLContext(final SSLContext sslContext)
+  {
+    this.sslContext = sslContext;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the operation timeout. If the response is not received from the
+   * Directory Server in the timeout period, the operation will be abandoned and
+   * an error result returned. A timeout setting of 0 disables timeout limits.
+   *
+   * @param timeout
+   *          The operation timeout to use.
+   * @param unit
+   *          the time unit of the time argument.
+   * @return A reference to this LDAP connection options.
+   */
+  public final LDAPOptions setTimeout(final long timeout, final TimeUnit unit)
+  {
+    this.timeoutInMillis = unit.toMillis(timeout);
+    return this;
+  }
+
+
+
+  /**
+   * Specifies whether or not SSL or StartTLS should be used for securing
+   * connections when an SSL context is specified. By default SSL will be used
+   * in preference to StartTLS.
+   *
+   * @param useStartTLS
+   *          {@code true} if StartTLS should be used for securing connections
+   *          when an SSL context is specified, otherwise {@code false}
+   *          indicating that SSL should be used.
+   * @return A reference to this LDAP connection options.
+   */
+  public final LDAPOptions setUseStartTLS(final boolean useStartTLS)
+  {
+    this.useStartTLS = useStartTLS;
+    return this;
+  }
+
+
+
+  /**
+   * Indicates whether or not SSL or StartTLS should be used for securing
+   * connections when an SSL context is specified. By default SSL will be used
+   * in preference to StartTLS.
+   *
+   * @return {@code true} if StartTLS should be used for securing connections
+   *         when an SSL context is specified, otherwise {@code false}
+   *         indicating that SSL should be used.
+   */
+  public final boolean useStartTLS()
+  {
+    return useStartTLS;
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/LDAPUrl.java b/sdk/src/org/opends/sdk/LDAPUrl.java
new file mode 100644
index 0000000..d7a23fb
--- /dev/null
+++ b/sdk/src/org/opends/sdk/LDAPUrl.java
@@ -0,0 +1,978 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.*;
+
+import java.util.*;
+
+import org.opends.sdk.requests.Requests;
+import org.opends.sdk.requests.SearchRequest;
+import org.opends.sdk.schema.Schema;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * An LDAP URL as defined in RFC 4516. In addition, the secure ldap (ldaps://)
+ * is also supported. LDAP URLs have the following format:
+ *
+ * <PRE>
+ * "ldap[s]://" [ <I>hostName</I> [":" <I>portNumber</I>] ]
+ *          "/" <I>distinguishedName</I>
+ *          ["?" <I>attributeList</I>
+ *              ["?" <I>scope</I> "?" <I>filterString</I> ] ]
+ * </PRE>
+ *
+ * Where:
+ * <UL>
+ * <LI>all text within double-quotes are literal
+ * <LI><CODE><I>hostName</I></CODE> and <CODE><I>portNumber</I></CODE> identify
+ * the location of the LDAP server.
+ * <LI><CODE><I>distinguishedName</I></CODE> is the name of an entry within the
+ * given directory (the entry represents the starting point of the search).
+ * <LI><CODE><I>attributeList</I></CODE> contains a list of attributes to
+ * retrieve (if null, fetch all attributes). This is a comma-delimited list of
+ * attribute names.
+ * <LI><CODE><I>scope</I></CODE> is one of the following:
+ * <UL>
+ * <LI><CODE>base</CODE> indicates that this is a search only for the specified
+ * entry
+ * <LI><CODE>one</CODE> indicates that this is a search for matching entries one
+ * level under the specified entry (and not including the entry itself)
+ * <LI><CODE>sub</CODE> indicates that this is a search for matching entries at
+ * all levels under the specified entry (including the entry itself)
+ * <LI><CODE>subordinates</CODE> indicates that this is a search for matching
+ * entries all levels under the specified entry (excluding the entry itself)
+ * </UL>
+ * If not specified, <CODE><I>scope</I></CODE> is <CODE>base</CODE> by default.
+ * <LI><CODE><I>filterString</I></CODE> is a human-readable representation of
+ * the search criteria. If no filter is provided, then a default of "{@code
+ * (objectClass=*)}" should be assumed.
+ * </UL>
+ * The same encoding rules for other URLs (e.g. HTTP) apply for LDAP URLs.
+ * Specifically, any "illegal" characters are escaped with
+ * <CODE>%<I>HH</I></CODE>, where <CODE><I>HH</I></CODE> represent the two hex
+ * digits which correspond to the ASCII value of the character. This encoding is
+ * only legal (or necessary) on the DN and filter portions of the URL.
+ * <P>
+ * Note that this class does not implement extensions.
+ *
+ * @see <a href="http://www.ietf.org/rfc/rfc4516">RFC 4516 - Lightweight
+ *      Directory Access Protocol (LDAP): Uniform Resource Locator</a>
+ */
+public final class LDAPUrl
+{
+  /**
+   * The scheme corresponding to an LDAP URL. RFC 4516 mandates only ldap scheme
+   * but we support "ldaps" too.
+   */
+  private final boolean isSecured;
+
+  /**
+   * The host name corresponding to an LDAP URL.
+   */
+  private final String host;
+
+  /**
+   * The port number corresponding to an LDAP URL.
+   */
+  private final int port;
+
+  /**
+   * The distinguished name corresponding to an LDAP URL.
+   */
+  private final DN name;
+
+  /**
+   * The search scope corresponding to an LDAP URL.
+   */
+  private final SearchScope scope;
+
+  /**
+   * The search filter corresponding to an LDAP URL.
+   */
+  private final Filter filter;
+
+  /**
+   * The attributes that need to be searched.
+   */
+  private final List<String> attributes;
+
+  /**
+   * The String value of LDAP URL.
+   */
+  private final String urlString;
+
+  /**
+   * Normalized ldap URL.
+   */
+  private String normalizedURL;
+
+  /**
+   * The default scheme to be used with LDAP URL.
+   */
+  private static final String DEFAULT_URL_SCHEME = "ldap";
+
+  /**
+   * The SSL-based scheme allowed to be used with LDAP URL.
+   */
+  private static final String SSL_URL_SCHEME = "ldaps";
+
+  /**
+   * The default host.
+   */
+  private static final String DEFAULT_HOST = "localhost";
+
+  /**
+   * The default non-SSL port.
+   */
+  private static final int DEFAULT_PORT = 389;
+
+  /**
+   * The default SSL port.
+   */
+  private static final int DEFAULT_SSL_PORT = 636;
+
+  /**
+   * The default filter.
+   */
+  private static final Filter DEFAULT_FILTER = Filter
+      .getObjectClassPresentFilter();
+
+  /**
+   * The default search scope.
+   */
+  private static final SearchScope DEFAULT_SCOPE = SearchScope.BASE_OBJECT;
+
+  /**
+   * The default distinguished name.
+   */
+  private static final DN DEFAULT_DN = DN.rootDN();
+
+  /**
+   * The % encoding character.
+   */
+  private static final char PERCENT_ENCODING_CHAR = '%';
+
+  /**
+   * The ? character.
+   */
+  private static final char QUESTION_CHAR = '?';
+
+  /**
+   * The slash (/) character.
+   */
+  private static final char SLASH_CHAR = '/';
+
+  /**
+   * The comma (,) character.
+   */
+  private static final char COMMA_CHAR = ',';
+
+  /**
+   * The colon (:) character.
+   */
+  private static final char COLON_CHAR = ':';
+
+  /**
+   * Set containing characters that do not need to be encoded.
+   */
+  private static final Set<Character> VALID_CHARS = new HashSet<Character>();
+
+  static
+  {
+    // Refer to RFC 3986 for more details.
+    final char[] delims = { '!', '$', '&', '\'', '(', ')', '*', '+', ',', ';',
+        '=', '.', '-', '_', '~' };
+    for (final char c : delims)
+    {
+      VALID_CHARS.add(c);
+    }
+
+    for (char c = 'a'; c <= 'z'; c++)
+    {
+      VALID_CHARS.add(c);
+    }
+
+    for (char c = 'A'; c <= 'Z'; c++)
+    {
+      VALID_CHARS.add(c);
+    }
+
+    for (char c = '0'; c <= '9'; c++)
+    {
+      VALID_CHARS.add(c);
+    }
+  }
+
+
+
+  /**
+   * Parses the provided LDAP string representation of an LDAP URL using the
+   * default schema.
+   *
+   * @param url
+   *          The LDAP string representation of an LDAP URL.
+   * @return The parsed LDAP URL.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code url} is not a valid LDAP string representation of an
+   *           LDAP URL.
+   * @throws NullPointerException
+   *           If {@code url} was {@code null}.
+   */
+  public static LDAPUrl valueOf(final String url)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    return valueOf(url, Schema.getDefaultSchema());
+  }
+
+
+
+  /**
+   * Parses the provided LDAP string representation of an LDAP URL using the
+   * provided schema.
+   *
+   * @param url
+   *          The LDAP string representation of an LDAP URL.
+   * @param schema
+   *          The schema to use when parsing the LDAP URL.
+   * @return The parsed LDAP URL.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code url} is not a valid LDAP string representation of an
+   *           LDAP URL.
+   * @throws NullPointerException
+   *           If {@code url} or {@code schema} was {@code null}.
+   */
+  public static LDAPUrl valueOf(final String url, final Schema schema)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(url, schema);
+    return new LDAPUrl(url, schema);
+  }
+
+
+
+  private static int decodeHex(final String url, final int index,
+      final char hexChar) throws LocalizedIllegalArgumentException
+  {
+    if (hexChar >= '0' && hexChar <= '9')
+    {
+      return hexChar - '0';
+    }
+    else if (hexChar >= 'A' && hexChar <= 'F')
+    {
+      return hexChar - 'A' + 10;
+    }
+    else if (hexChar >= 'a' && hexChar <= 'f')
+    {
+      return hexChar - 'a' + 10;
+    }
+
+    final LocalizableMessage msg = ERR_LDAPURL_INVALID_HEX_BYTE.get(url, index);
+    throw new LocalizedIllegalArgumentException(msg);
+  }
+
+
+
+  private static void percentDecoder(final String urlString, final int index,
+      final String s, final StringBuilder decoded)
+      throws LocalizedIllegalArgumentException
+  {
+    Validator.ensureNotNull(s, decoded);
+    decoded.append(s);
+
+    int srcPos = 0, dstPos = 0;
+
+    while (srcPos < decoded.length())
+    {
+      if (decoded.charAt(srcPos) != '%')
+      {
+        if (srcPos != dstPos)
+        {
+          decoded.setCharAt(dstPos, decoded.charAt(srcPos));
+        }
+        srcPos++;
+        dstPos++;
+        continue;
+      }
+      decoded.setCharAt(dstPos, (char) ((decodeHex(urlString, index + srcPos
+          + 1, decoded.charAt(srcPos + 1)) << 4) | (decodeHex(urlString, index
+          + srcPos + 2, decoded.charAt(srcPos + 2)))));
+      dstPos++;
+      srcPos += 3;
+    }
+    decoded.setLength(dstPos);
+  }
+
+
+
+  /**
+   * This method performs the percent-encoding as defined in section 2.1 of RFC
+   * 3986.
+   *
+   * @param urlElement
+   *          The element of the URL that needs to be percent encoded.
+   * @param encodedBuffer
+   *          The buffer that contains the final percent encoded value.
+   */
+  private static void percentEncoder(final String urlElement,
+      final StringBuilder encodedBuffer)
+  {
+    Validator.ensureNotNull(urlElement);
+    for (int count = 0; count < urlElement.length(); count++)
+    {
+      final char c = urlElement.charAt(count);
+      if (VALID_CHARS.contains(c))
+      {
+        encodedBuffer.append(c);
+      }
+      else
+      {
+        encodedBuffer.append(PERCENT_ENCODING_CHAR);
+        encodedBuffer.append(Integer.toHexString(c));
+      }
+    }
+  }
+
+
+
+  /**
+   * Creates a new LDAP URL referring to a single entry on the specified server.
+   * The LDAP URL with have base object scope and the filter {@code
+   * (objectClass=*)}.
+   *
+   * @param isSecured
+   *          {@code true} if this LDAP URL should use LDAPS or {@code false} if
+   *          it should use LDAP.
+   * @param host
+   *          The name or IP address in dotted format of the LDAP server. For
+   *          example, {@code ldap.server1.com} or {@code 192.202.185.90}. Use
+   *          {@code null} for the local host.
+   * @param port
+   *          The port number of the LDAP server, or {@code null} to use the
+   *          default port (389 for LDAP and 636 for LDAPS).
+   * @param name
+   *          The distinguished name of the base entry relative to which the
+   *          search is to be performed, or {@code null} to specify the root
+   *          DSE.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code port} was less than 1 or greater than 65535.
+   */
+  public LDAPUrl(final boolean isSecured, final String host,
+      final Integer port, final DN name)
+      throws LocalizedIllegalArgumentException
+  {
+    this(isSecured, host, port, name, DEFAULT_SCOPE, DEFAULT_FILTER);
+  }
+
+
+
+  /**
+   * Creates a new LDAP URL including the full set of parameters for a search
+   * request.
+   *
+   * @param isSecured
+   *          {@code true} if this LDAP URL should use LDAPS or {@code false} if
+   *          it should use LDAP.
+   * @param host
+   *          The name or IP address in dotted format of the LDAP server. For
+   *          example, {@code ldap.server1.com} or {@code 192.202.185.90}. Use
+   *          {@code null} for the local host.
+   * @param port
+   *          The port number of the LDAP server, or {@code null} to use the
+   *          default port (389 for LDAP and 636 for LDAPS).
+   * @param name
+   *          The distinguished name of the base entry relative to which the
+   *          search is to be performed, or {@code null} to specify the root
+   *          DSE.
+   * @param scope
+   *          The search scope, or {@code null} to specify base scope.
+   * @param filter
+   *          The search filter, or {@code null} to specify the filter {@code
+   *          (objectClass=*)}.
+   * @param attributes
+   *          The list of attributes to be included in the search results.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code port} was less than 1 or greater than 65535.
+   */
+  public LDAPUrl(final boolean isSecured, final String host,
+      final Integer port, final DN name, final SearchScope scope,
+      final Filter filter, final String... attributes)
+      throws LocalizedIllegalArgumentException
+  {
+    // The buffer storing the encoded url.
+    final StringBuilder urlBuffer = new StringBuilder();
+
+    // build the scheme.
+    this.isSecured = isSecured;
+    if (this.isSecured)
+    {
+      urlBuffer.append(SSL_URL_SCHEME);
+    }
+    else
+    {
+      urlBuffer.append(DEFAULT_URL_SCHEME);
+    }
+    urlBuffer.append("://");
+
+    if (host == null)
+    {
+      this.host = DEFAULT_HOST;
+    }
+    else
+    {
+      this.host = host;
+      urlBuffer.append(this.host);
+    }
+
+    int listenPort = DEFAULT_PORT;
+    if (port == null)
+    {
+      listenPort = isSecured ? DEFAULT_SSL_PORT : DEFAULT_PORT;
+    }
+    else
+    {
+      listenPort = port.intValue();
+      if (listenPort < 1 && listenPort > Integer.MAX_VALUE)
+      {
+        final LocalizableMessage msg = ERR_LDAPURL_BAD_PORT.get(listenPort);
+        throw new LocalizedIllegalArgumentException(msg);
+      }
+      urlBuffer.append(COLON_CHAR);
+      urlBuffer.append(listenPort);
+    }
+
+    this.port = listenPort;
+
+    // We need a slash irrespective of dn is defined or not.
+    urlBuffer.append(SLASH_CHAR);
+    if (name != null)
+    {
+      this.name = name;
+      percentEncoder(name.toString(), urlBuffer);
+    }
+    else
+    {
+      this.name = DEFAULT_DN;
+    }
+
+    // Add attributes.
+    urlBuffer.append(QUESTION_CHAR);
+    switch (attributes.length)
+    {
+    case 0:
+      this.attributes = Collections.emptyList();
+      break;
+    case 1:
+      this.attributes = Collections.singletonList(attributes[0]);
+      urlBuffer.append(attributes[0]);
+      break;
+    default:
+      this.attributes = Collections.unmodifiableList(Arrays.asList(attributes));
+      urlBuffer.append(attributes[0]);
+      for (int i = 1; i < attributes.length; i++)
+      {
+        urlBuffer.append(COMMA_CHAR);
+        urlBuffer.append(attributes[i]);
+      }
+      break;
+    }
+
+    // Add the scope.
+    urlBuffer.append(QUESTION_CHAR);
+    if (scope != null)
+    {
+      this.scope = scope;
+      urlBuffer.append(scope);
+    }
+    else
+    {
+      this.scope = DEFAULT_SCOPE;
+    }
+
+    // Add the search filter.
+    urlBuffer.append(QUESTION_CHAR);
+    if (filter != null)
+    {
+      this.filter = filter;
+      urlBuffer.append(this.filter);
+    }
+    else
+    {
+      this.filter = DEFAULT_FILTER;
+    }
+
+    urlString = urlBuffer.toString();
+  }
+
+
+
+  private LDAPUrl(final String urlString, final Schema schema)
+      throws LocalizedIllegalArgumentException
+  {
+    this.urlString = urlString;
+
+    // Parse the url and build the LDAP URL.
+    final int schemeIdx = urlString.indexOf("://");
+    if (schemeIdx < 0)
+    {
+      final LocalizableMessage msg = ERR_LDAPURL_NO_SCHEME.get(urlString);
+      throw new LocalizedIllegalArgumentException(msg);
+    }
+    final String scheme = StaticUtils.toLowerCase(urlString.substring(0,
+        schemeIdx));
+
+    if (scheme.equalsIgnoreCase(DEFAULT_URL_SCHEME))
+    {
+      // Default ldap scheme.
+      isSecured = false;
+    }
+    else if (scheme.equalsIgnoreCase(SSL_URL_SCHEME))
+    {
+      isSecured = true;
+    }
+    else
+    {
+      final LocalizableMessage msg = ERR_LDAPURL_BAD_SCHEME.get(urlString,
+          scheme);
+      throw new LocalizedIllegalArgumentException(msg);
+    }
+
+    final int urlLength = urlString.length();
+    final int hostPortIdx = urlString.indexOf(SLASH_CHAR, schemeIdx + 3);
+    final StringBuilder builder = new StringBuilder();
+    if (hostPortIdx < 0)
+    {
+      // We got anything here like the host and port?
+      if (urlLength > (schemeIdx + 3))
+      {
+        final String hostAndPort = urlString
+            .substring(schemeIdx + 3, urlLength);
+        port = parseHostPort(urlString, hostAndPort, builder);
+        host = builder.toString();
+        builder.setLength(0);
+      }
+      else
+      {
+        // Nothing else is specified apart from the scheme.
+        // Use the default settings and return from here.
+        host = DEFAULT_HOST;
+        port = isSecured ? DEFAULT_SSL_PORT : DEFAULT_PORT;
+      }
+      name = DEFAULT_DN;
+      scope = DEFAULT_SCOPE;
+      filter = DEFAULT_FILTER;
+      attributes = Collections.emptyList();
+      return;
+    }
+
+    final String hostAndPort = urlString.substring(schemeIdx + 3, hostPortIdx);
+    // assign the host and port.
+    port = parseHostPort(urlString, hostAndPort, builder);
+    host = builder.toString();
+    builder.setLength(0);
+
+    // Parse the dn.
+    DN parsedDN = null;
+    final int dnIdx = urlString.indexOf(QUESTION_CHAR, hostPortIdx + 1);
+
+    if (dnIdx < 0)
+    {
+      // Whatever we have here is the dn.
+      final String dnStr = urlString.substring(hostPortIdx + 1, urlLength);
+      percentDecoder(urlString, hostPortIdx + 1, dnStr, builder);
+      try
+      {
+        parsedDN = DN.valueOf(builder.toString(), schema);
+      }
+      catch (final LocalizedIllegalArgumentException e)
+      {
+        final LocalizableMessage msg = ERR_LDAPURL_INVALID_DN.get(urlString, e
+            .getMessageObject());
+        throw new LocalizedIllegalArgumentException(msg);
+      }
+      builder.setLength(0);
+      name = parsedDN;
+      scope = DEFAULT_SCOPE;
+      filter = DEFAULT_FILTER;
+      attributes = Collections.emptyList();
+      return;
+    }
+
+    final String dnStr = urlString.substring(hostPortIdx + 1, dnIdx);
+    if (dnStr.length() == 0)
+    {
+      parsedDN = DEFAULT_DN;
+    }
+    else
+    {
+      percentDecoder(urlString, hostPortIdx + 1, dnStr, builder);
+      try
+      {
+        parsedDN = DN.valueOf(builder.toString(), schema);
+      }
+      catch (final LocalizedIllegalArgumentException e)
+      {
+        final LocalizableMessage msg = ERR_LDAPURL_INVALID_DN.get(urlString, e
+            .getMessageObject());
+        throw new LocalizedIllegalArgumentException(msg);
+      }
+      builder.setLength(0);
+    }
+    name = parsedDN;
+
+    // Find out the attributes.
+    final int attrIdx = urlString.indexOf(QUESTION_CHAR, dnIdx + 1);
+    if (attrIdx < 0)
+    {
+      attributes = Collections.emptyList();
+      scope = DEFAULT_SCOPE;
+      filter = DEFAULT_FILTER;
+      return;
+    }
+    else
+    {
+      final String attrDesc = urlString.substring(dnIdx + 1, attrIdx);
+      final StringTokenizer token = new StringTokenizer(attrDesc, String
+          .valueOf(COMMA_CHAR));
+      final List<String> parsedAttrs = new ArrayList<String>(token
+          .countTokens());
+      while (token.hasMoreElements())
+      {
+        parsedAttrs.add(token.nextToken());
+      }
+      attributes = Collections.unmodifiableList(parsedAttrs);
+    }
+
+    // Find the scope.
+    final int scopeIdx = urlString.indexOf(QUESTION_CHAR, attrIdx + 1);
+    SearchScope parsedScope = SearchScope.BASE_OBJECT;
+    if (scopeIdx < 0)
+    {
+      scope = DEFAULT_SCOPE;
+      filter = DEFAULT_FILTER;
+      return;
+    }
+    else
+    {
+      String scopeDef = urlString.substring(attrIdx + 1, scopeIdx);
+      scopeDef = StaticUtils.toLowerCase(scopeDef);
+      for (final SearchScope sscope : SearchScope.values())
+      {
+        if (sscope.toString().equals(scopeDef))
+        {
+          parsedScope = sscope;
+          break;
+        }
+      }
+    }
+    scope = parsedScope;
+
+    // Last one is filter.
+    final String parsedFilter = urlString.substring(scopeIdx + 1, urlLength);
+    if (parsedFilter.length() > 0)
+    {
+      // Clear what we already have.
+      builder.setLength(0);
+      percentDecoder(urlString, scopeIdx + 1, parsedFilter, builder);
+      try
+      {
+        this.filter = Filter.valueOf(builder.toString());
+      }
+      catch (final LocalizedIllegalArgumentException e)
+      {
+        final LocalizableMessage msg = ERR_LDAPURL_INVALID_FILTER.get(
+            urlString, e.getMessageObject());
+        throw new LocalizedIllegalArgumentException(msg);
+      }
+    }
+    else
+    {
+      this.filter = DEFAULT_FILTER;
+    }
+  }
+
+
+
+  /**
+   * Creates a new search request containing the parameters of this LDAP URL.
+   *
+   * @return A new search request containing the parameters of this LDAP URL.
+   */
+  public SearchRequest asSearchRequest()
+  {
+    final SearchRequest request = Requests
+        .newSearchRequest(name, scope, filter);
+    for (final String a : attributes)
+    {
+      request.addAttribute(a);
+    }
+    return request;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override()
+  public boolean equals(final Object o)
+  {
+    if (o == this)
+    {
+      return true;
+    }
+    else if (o instanceof LDAPUrl)
+    {
+      final String s1 = toNormalizedString();
+      final String s2 = ((LDAPUrl) o).toNormalizedString();
+      return s1.equals(s2);
+    }
+    else
+    {
+      return false;
+    }
+  }
+
+
+
+  /**
+   * Returns an unmodifiable list containing the attributes to be included with
+   * each entry that matches the search criteria. Attributes that are sub-types
+   * of listed attributes are implicitly included. If the returned list is empty
+   * then all user attributes will be included by default.
+   *
+   * @return An unmodifiable list containing the attributes to be included with
+   *         each entry that matches the search criteria.
+   */
+  public List<String> getAttributes()
+  {
+    return attributes;
+  }
+
+
+
+  /**
+   * Returns the search filter associated with this LDAP URL.
+   *
+   * @return The search filter associated with this LDAP URL.
+   */
+  public Filter getFilter()
+  {
+    return filter;
+  }
+
+
+
+  /**
+   * Returns the name or IP address in dotted format of the LDAP server
+   * referenced by this LDAP URL. For example, {@code ldap.server1.com} or
+   * {@code 192.202.185.90}. Use {@code null} for the local host.
+   *
+   * @return A name or IP address in dotted format of the LDAP server referenced
+   *         by this LDAP URL.
+   */
+  public String getHost()
+  {
+    return host;
+  }
+
+
+
+  /**
+   * Returns the distinguished name of the base entry relative to which the
+   * search is to be performed.
+   *
+   * @return The distinguished name of the base entry relative to which the
+   *         search is to be performed.
+   */
+  public DN getName()
+  {
+    return name;
+  }
+
+
+
+  /**
+   * Returns the port number of the LDAP server referenced by this LDAP URL.
+   *
+   * @return The port number of the LDAP server referenced by this LDAP URL.
+   */
+  public int getPort()
+  {
+    return port;
+  }
+
+
+
+  /**
+   * Returns the search scope associated with this LDAP URL.
+   *
+   * @return The search scope associated with this LDAP URL.
+   */
+  public SearchScope getScope()
+  {
+    return scope;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public int hashCode()
+  {
+    final String s = toNormalizedString();
+    return s.hashCode();
+  }
+
+
+
+  /**
+   * Returns {@code true} if this LDAP URL should use LDAPS or {@code false} if
+   * it should use LDAP.
+   *
+   * @return {@code true} if this LDAP URL should use LDAPS or {@code false} if
+   *         it should use LDAP.
+   */
+  public boolean isSecure()
+  {
+    return isSecured;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    return urlString;
+  }
+
+
+
+  private int parseHostPort(final String urlString, final String hostAndPort,
+      final StringBuilder host) throws LocalizedIllegalArgumentException
+  {
+    Validator.ensureNotNull(hostAndPort, port, host);
+    int urlPort = isSecured ? DEFAULT_SSL_PORT : DEFAULT_PORT;
+    if (hostAndPort.length() == 0)
+    {
+      host.append(DEFAULT_HOST);
+      return urlPort;
+    }
+    final int colonIdx = hostAndPort.indexOf(':');
+    if (colonIdx < 0)
+    {
+      // port is not specified.
+      host.append(hostAndPort);
+      return urlPort;
+    }
+    else
+    {
+      String s = hostAndPort.substring(0, colonIdx);
+      if (s.length() == 0)
+      {
+        // Use the default host as we allow only the port to be specified.
+        host.append(DEFAULT_HOST);
+      }
+      else
+      {
+        host.append(s);
+      }
+      s = hostAndPort.substring(colonIdx + 1, hostAndPort.length());
+      try
+      {
+        urlPort = Integer.parseInt(s);
+      }
+      catch (final NumberFormatException e)
+      {
+        final LocalizableMessage msg = ERR_LDAPURL_CANNOT_DECODE_PORT.get(
+            urlString, s);
+        throw new LocalizedIllegalArgumentException(msg);
+      }
+
+      // Check the validity of the port.
+      if (urlPort < 1 || urlPort > 65535)
+      {
+        final LocalizableMessage msg = ERR_LDAPURL_INVALID_PORT.get(urlString,
+            urlPort);
+        throw new LocalizedIllegalArgumentException(msg);
+      }
+    }
+    return urlPort;
+  }
+
+
+
+  private String toNormalizedString()
+  {
+    if (normalizedURL == null)
+    {
+      final StringBuilder builder = new StringBuilder();
+      if (this.isSecured)
+      {
+        builder.append(SSL_URL_SCHEME);
+      }
+      else
+      {
+        builder.append(DEFAULT_URL_SCHEME);
+      }
+      builder.append("://");
+      builder.append(host);
+      builder.append(COLON_CHAR);
+      builder.append(port);
+      builder.append(SLASH_CHAR);
+      percentEncoder(name.toString(), builder);
+      builder.append(QUESTION_CHAR);
+      final int sz = attributes.size();
+      for (int i = 0; i < sz; i++)
+      {
+        if (i > 0)
+        {
+          builder.append(COMMA_CHAR);
+        }
+        builder.append(attributes.get(i));
+      }
+      builder.append(QUESTION_CHAR);
+      builder.append(scope);
+      builder.append(QUESTION_CHAR);
+      percentEncoder(filter.toString(), builder);
+      normalizedURL = builder.toString();
+    }
+    return normalizedURL;
+  }
+}
diff --git a/sdk/src/org/opends/sdk/LinkedAttribute.java b/sdk/src/org/opends/sdk/LinkedAttribute.java
index 8198463..89ba995 100644
--- a/sdk/src/org/opends/sdk/LinkedAttribute.java
+++ b/sdk/src/org/opends/sdk/LinkedAttribute.java
@@ -39,17 +39,17 @@
  * An implementation of the {@code Attribute} interface with predictable
  * iteration order.
  * <p>
- * Internally, attribute values are stored in a linked list and it's
- * this list which defines the iteration ordering, which is the order in
- * which elements were inserted into the set (insertion-order). This
- * ordering is particularly useful in LDAP where clients generally
- * appreciate having things returned in the same order they were
- * presented.
+ * Internally, attribute values are stored in a linked list and it's this list
+ * which defines the iteration ordering, which is the order in which elements
+ * were inserted into the set (insertion-order). This ordering is particularly
+ * useful in LDAP where clients generally appreciate having things returned in
+ * the same order they were presented.
  * <p>
  * All operations are supported by this implementation.
  */
 public final class LinkedAttribute extends AbstractAttribute
 {
+
   private static abstract class Impl
   {
 
@@ -57,15 +57,15 @@
 
 
 
-    boolean addAll(LinkedAttribute attribute,
-        Collection<? extends ByteString> values,
-        Collection<? super ByteString> duplicateValues)
+    boolean addAll(final LinkedAttribute attribute,
+        final Collection<? extends ByteString> values,
+        final Collection<? super ByteString> duplicateValues)
         throws NullPointerException
     {
       // TODO: could optimize if values is a BasicAttribute.
       ensureCapacity(attribute, values.size());
       boolean modified = false;
-      for (ByteString value : values)
+      for (final ByteString value : values)
       {
         if (add(attribute, value))
         {
@@ -86,15 +86,15 @@
 
 
 
-    abstract boolean contains(LinkedAttribute attribute,
-        ByteString value);
+    abstract boolean contains(LinkedAttribute attribute, ByteString value);
 
 
 
-    boolean containsAll(LinkedAttribute attribute, Collection<?> values)
+    boolean containsAll(final LinkedAttribute attribute,
+        final Collection<?> values)
     {
       // TODO: could optimize if objects is a BasicAttribute.
-      for (Object value : values)
+      for (final Object value : values)
       {
         if (!contains(attribute, ByteString.valueOf(value)))
         {
@@ -123,12 +123,12 @@
 
 
 
-    <T> boolean removeAll(LinkedAttribute attribute,
-        Collection<T> values, Collection<? super T> missingValues)
+    <T> boolean removeAll(final LinkedAttribute attribute,
+        final Collection<T> values, final Collection<? super T> missingValues)
     {
       // TODO: could optimize if objects is a BasicAttribute.
       boolean modified = false;
-      for (T value : values)
+      for (final T value : values)
       {
         if (remove(attribute, ByteString.valueOf(value)))
         {
@@ -161,9 +161,10 @@
   private static final class MultiValueImpl extends Impl
   {
 
-    boolean add(LinkedAttribute attribute, ByteString value)
+    @Override
+    boolean add(final LinkedAttribute attribute, final ByteString value)
     {
-      ByteString normalizedValue = normalizeValue(attribute, value);
+      final ByteString normalizedValue = normalizeValue(attribute, value);
       if (attribute.multipleValues.put(normalizedValue, value) == null)
       {
         return true;
@@ -176,7 +177,8 @@
 
 
 
-    void clear(LinkedAttribute attribute)
+    @Override
+    void clear(final LinkedAttribute attribute)
     {
       attribute.multipleValues = null;
       attribute.pimpl = ZERO_VALUE_IMPL;
@@ -184,22 +186,25 @@
 
 
 
-    boolean contains(LinkedAttribute attribute, ByteString value)
+    @Override
+    boolean contains(final LinkedAttribute attribute, final ByteString value)
     {
-      return attribute.multipleValues.containsKey(normalizeValue(
-          attribute, value));
+      return attribute.multipleValues.containsKey(normalizeValue(attribute,
+          value));
     }
 
 
 
-    void ensureCapacity(LinkedAttribute attribute, int size)
+    @Override
+    void ensureCapacity(final LinkedAttribute attribute, final int size)
     {
       // Nothing to do.
     }
 
 
 
-    ByteString firstValue(LinkedAttribute attribute)
+    @Override
+    ByteString firstValue(final LinkedAttribute attribute)
         throws NoSuchElementException
     {
       return attribute.multipleValues.values().iterator().next();
@@ -207,6 +212,7 @@
 
 
 
+    @Override
     Iterator<ByteString> iterator(final LinkedAttribute attribute)
     {
       return new Iterator<ByteString>()
@@ -268,9 +274,10 @@
 
 
 
-    boolean remove(LinkedAttribute attribute, ByteString value)
+    @Override
+    boolean remove(final LinkedAttribute attribute, final ByteString value)
     {
-      ByteString normalizedValue = normalizeValue(attribute, value);
+      final ByteString normalizedValue = normalizeValue(attribute, value);
       if (attribute.multipleValues.remove(normalizedValue) != null)
       {
         resize(attribute);
@@ -284,7 +291,8 @@
 
 
 
-    void resize(LinkedAttribute attribute)
+    @Override
+    void resize(final LinkedAttribute attribute)
     {
       // May need to resize if initial size estimate was wrong (e.g. all
       // values in added collection were the same).
@@ -295,7 +303,7 @@
         attribute.pimpl = ZERO_VALUE_IMPL;
         break;
       case 1:
-        Map.Entry<ByteString, ByteString> e = attribute.multipleValues
+        final Map.Entry<ByteString, ByteString> e = attribute.multipleValues
             .entrySet().iterator().next();
         attribute.singleValue = e.getValue();
         attribute.normalizedSingleValue = e.getKey();
@@ -310,8 +318,9 @@
 
 
 
-    <T> boolean retainAll(LinkedAttribute attribute,
-        Collection<T> values, Collection<? super T> missingValues)
+    @Override
+    <T> boolean retainAll(final LinkedAttribute attribute,
+        final Collection<T> values, final Collection<? super T> missingValues)
     {
       // TODO: could optimize if objects is a BasicAttribute.
       if (values.isEmpty())
@@ -320,20 +329,20 @@
         return true;
       }
 
-      Map<ByteString, T> valuesToRetain = new HashMap<ByteString, T>(
+      final Map<ByteString, T> valuesToRetain = new HashMap<ByteString, T>(
           values.size());
-      for (T value : values)
+      for (final T value : values)
       {
-        valuesToRetain.put(normalizeValue(attribute, ByteString
-            .valueOf(value)), value);
+        valuesToRetain.put(
+            normalizeValue(attribute, ByteString.valueOf(value)), value);
       }
 
       boolean modified = false;
-      Iterator<ByteString> iterator = attribute.multipleValues.keySet()
+      final Iterator<ByteString> iterator = attribute.multipleValues.keySet()
           .iterator();
       while (iterator.hasNext())
       {
-        ByteString normalizedValue = iterator.next();
+        final ByteString normalizedValue = iterator.next();
         if (valuesToRetain.remove(normalizedValue) == null)
         {
           modified = true;
@@ -353,7 +362,8 @@
 
 
 
-    int size(LinkedAttribute attribute)
+    @Override
+    int size(final LinkedAttribute attribute)
     {
       return attribute.multipleValues.size();
     }
@@ -364,16 +374,16 @@
   private static final class SingleValueImpl extends Impl
   {
 
-    boolean add(LinkedAttribute attribute, ByteString value)
+    @Override
+    boolean add(final LinkedAttribute attribute, final ByteString value)
     {
-      ByteString normalizedValue = normalizeValue(attribute, value);
+      final ByteString normalizedValue = normalizeValue(attribute, value);
       if (attribute.normalizedSingleValue().equals(normalizedValue))
       {
         return false;
       }
 
-      attribute.multipleValues = new LinkedHashMap<ByteString, ByteString>(
-          2);
+      attribute.multipleValues = new LinkedHashMap<ByteString, ByteString>(2);
       attribute.multipleValues.put(attribute.normalizedSingleValue,
           attribute.singleValue);
       attribute.multipleValues.put(normalizedValue, value);
@@ -386,7 +396,8 @@
 
 
 
-    void clear(LinkedAttribute attribute)
+    @Override
+    void clear(final LinkedAttribute attribute)
     {
       attribute.singleValue = null;
       attribute.normalizedSingleValue = null;
@@ -395,15 +406,17 @@
 
 
 
-    boolean contains(LinkedAttribute attribute, ByteString value)
+    @Override
+    boolean contains(final LinkedAttribute attribute, final ByteString value)
     {
-      ByteString normalizedValue = normalizeValue(attribute, value);
+      final ByteString normalizedValue = normalizeValue(attribute, value);
       return attribute.normalizedSingleValue().equals(normalizedValue);
     }
 
 
 
-    void ensureCapacity(LinkedAttribute attribute, int size)
+    @Override
+    void ensureCapacity(final LinkedAttribute attribute, final int size)
     {
       if (size == 0)
       {
@@ -421,7 +434,8 @@
 
 
 
-    ByteString firstValue(LinkedAttribute attribute)
+    @Override
+    ByteString firstValue(final LinkedAttribute attribute)
         throws NoSuchElementException
     {
       if (attribute.singleValue != null)
@@ -436,6 +450,7 @@
 
 
 
+    @Override
     Iterator<ByteString> iterator(final LinkedAttribute attribute)
     {
       return new Iterator<ByteString>()
@@ -494,7 +509,8 @@
 
 
 
-    boolean remove(LinkedAttribute attribute, ByteString value)
+    @Override
+    boolean remove(final LinkedAttribute attribute, final ByteString value)
     {
       if (contains(attribute, value))
       {
@@ -509,15 +525,17 @@
 
 
 
-    void resize(LinkedAttribute attribute)
+    @Override
+    void resize(final LinkedAttribute attribute)
     {
       // Nothing to do.
     }
 
 
 
-    <T> boolean retainAll(LinkedAttribute attribute,
-        Collection<T> values, Collection<? super T> missingValues)
+    @Override
+    <T> boolean retainAll(final LinkedAttribute attribute,
+        final Collection<T> values, final Collection<? super T> missingValues)
     {
       // TODO: could optimize if objects is a BasicAttribute.
       if (values.isEmpty())
@@ -526,13 +544,13 @@
         return true;
       }
 
-      ByteString normalizedSingleValue = attribute
+      final ByteString normalizedSingleValue = attribute
           .normalizedSingleValue();
       boolean retained = false;
-      for (T value : values)
+      for (final T value : values)
       {
-        ByteString normalizedValue = normalizeValue(attribute,
-            ByteString.valueOf(value));
+        final ByteString normalizedValue = normalizeValue(attribute, ByteString
+            .valueOf(value));
         if (normalizedSingleValue.equals(normalizedValue))
         {
           if (missingValues == null)
@@ -561,7 +579,8 @@
 
 
 
-    int size(LinkedAttribute attribute)
+    @Override
+    int size(final LinkedAttribute attribute)
     {
       return 1;
     }
@@ -572,7 +591,8 @@
   private static final class ZeroValueImpl extends Impl
   {
 
-    boolean add(LinkedAttribute attribute, ByteString value)
+    @Override
+    boolean add(final LinkedAttribute attribute, final ByteString value)
     {
       attribute.singleValue = value;
       attribute.pimpl = SINGLE_VALUE_IMPL;
@@ -581,42 +601,47 @@
 
 
 
-    void clear(LinkedAttribute attribute)
+    @Override
+    void clear(final LinkedAttribute attribute)
     {
       // Nothing to do.
     }
 
 
 
-    boolean contains(LinkedAttribute attribute, ByteString value)
+    @Override
+    boolean contains(final LinkedAttribute attribute, final ByteString value)
     {
       return false;
     }
 
 
 
-    boolean containsAll(LinkedAttribute attribute, Collection<?> values)
+    @Override
+    boolean containsAll(final LinkedAttribute attribute,
+        final Collection<?> values)
     {
       return values.isEmpty();
     }
 
 
 
-    void ensureCapacity(LinkedAttribute attribute, int size)
+    @Override
+    void ensureCapacity(final LinkedAttribute attribute, final int size)
     {
       if (size < 2)
       {
         return;
       }
 
-      attribute.multipleValues = new LinkedHashMap<ByteString, ByteString>(
-          size);
+      attribute.multipleValues = new LinkedHashMap<ByteString, ByteString>(size);
       attribute.pimpl = MULTI_VALUE_IMPL;
     }
 
 
 
-    ByteString firstValue(LinkedAttribute attribute)
+    @Override
+    ByteString firstValue(final LinkedAttribute attribute)
         throws NoSuchElementException
     {
       throw new NoSuchElementException();
@@ -624,6 +649,7 @@
 
 
 
+    @Override
     Iterator<ByteString> iterator(final LinkedAttribute attribute)
     {
       return new Iterator<ByteString>()
@@ -666,22 +692,25 @@
 
 
 
-    boolean remove(LinkedAttribute attribute, ByteString value)
+    @Override
+    boolean remove(final LinkedAttribute attribute, final ByteString value)
     {
       return false;
     }
 
 
 
-    void resize(LinkedAttribute attribute)
+    @Override
+    void resize(final LinkedAttribute attribute)
     {
       // Nothing to do.
     }
 
 
 
-    <T> boolean retainAll(LinkedAttribute attribute,
-        Collection<T> values, Collection<? super T> missingValues)
+    @Override
+    <T> boolean retainAll(final LinkedAttribute attribute,
+        final Collection<T> values, final Collection<? super T> missingValues)
     {
       if (missingValues != null)
       {
@@ -692,7 +721,8 @@
 
 
 
-    int size(LinkedAttribute attribute)
+    @Override
+    int size(final LinkedAttribute attribute)
     {
       return 0;
     }
@@ -701,6 +731,19 @@
 
 
 
+  /**
+   * An attribute factory which can be used to create new linked attributes.
+   */
+  public static final AttributeFactory FACTORY = new AttributeFactory()
+  {
+    public Attribute newAttribute(
+        final AttributeDescription attributeDescription)
+        throws NullPointerException
+    {
+      return new LinkedAttribute(attributeDescription);
+    }
+  };
+
   private static final MultiValueImpl MULTI_VALUE_IMPL = new MultiValueImpl();
 
   private static final SingleValueImpl SINGLE_VALUE_IMPL = new SingleValueImpl();
@@ -720,22 +763,21 @@
 
 
   /**
-   * Creates a new attribute having the same attribute description and
-   * attribute values as {@code attribute}.
+   * Creates a new attribute having the same attribute description and attribute
+   * values as {@code attribute}.
    *
    * @param attribute
    *          The attribute to be copied.
    * @throws NullPointerException
    *           If {@code attribute} was {@code null}.
    */
-  public LinkedAttribute(Attribute attribute)
-      throws NullPointerException
+  public LinkedAttribute(final Attribute attribute) throws NullPointerException
   {
     this.attributeDescription = attribute.getAttributeDescription();
 
     if (attribute instanceof LinkedAttribute)
     {
-      LinkedAttribute other = (LinkedAttribute) attribute;
+      final LinkedAttribute other = (LinkedAttribute) attribute;
       this.pimpl = other.pimpl;
       this.singleValue = other.singleValue;
       this.normalizedSingleValue = other.normalizedSingleValue;
@@ -754,15 +796,15 @@
 
 
   /**
-   * Creates a new attribute having the specified attribute description
-   * and no attribute values.
+   * Creates a new attribute having the specified attribute description and no
+   * attribute values.
    *
    * @param attributeDescription
    *          The attribute description.
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
-  public LinkedAttribute(AttributeDescription attributeDescription)
+  public LinkedAttribute(final AttributeDescription attributeDescription)
       throws NullPointerException
   {
     Validator.ensureNotNull(attributeDescription);
@@ -772,40 +814,19 @@
 
 
   /**
-   * Creates a new attribute having the specified attribute description
-   * and no attribute values. The attribute description will be decoded
-   * using the default schema.
-   *
-   * @param attributeDescription
-   *          The attribute description.
-   * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the default schema.
-   * @throws NullPointerException
-   *           If {@code attributeDescription} was {@code null}.
-   */
-  public LinkedAttribute(String attributeDescription)
-      throws LocalizedIllegalArgumentException, NullPointerException
-  {
-    this(AttributeDescription.valueOf(attributeDescription));
-  }
-
-
-
-  /**
-   * Creates a new attribute having the specified attribute description
-   * and single attribute value.
+   * Creates a new attribute having the specified attribute description and
+   * single attribute value.
    *
    * @param attributeDescription
    *          The attribute description.
    * @param value
    *          The single attribute value.
    * @throws NullPointerException
-   *           If {@code attributeDescription} or {@code value} was
-   *           {@code null}.
+   *           If {@code attributeDescription} or {@code value} was {@code null}
+   *           .
    */
-  public LinkedAttribute(AttributeDescription attributeDescription,
-      ByteString value) throws NullPointerException
+  public LinkedAttribute(final AttributeDescription attributeDescription,
+      final ByteString value) throws NullPointerException
   {
     this(attributeDescription);
     add(value);
@@ -814,19 +835,19 @@
 
 
   /**
-   * Creates a new attribute having the specified attribute description
-   * and attribute values.
+   * Creates a new attribute having the specified attribute description and
+   * attribute values.
    *
    * @param attributeDescription
    *          The attribute description.
    * @param values
    *          The attribute values.
    * @throws NullPointerException
-   *           If {@code attributeDescription} or {@code values} was
-   *           {@code null}.
+   *           If {@code attributeDescription} or {@code values} was {@code
+   *           null}.
    */
-  public LinkedAttribute(AttributeDescription attributeDescription,
-      ByteString... values) throws NullPointerException
+  public LinkedAttribute(final AttributeDescription attributeDescription,
+      final ByteString... values) throws NullPointerException
   {
     this(attributeDescription);
     addAll(Arrays.asList(values));
@@ -835,19 +856,19 @@
 
 
   /**
-   * Creates a new attribute having the specified attribute description
-   * and attribute values.
+   * Creates a new attribute having the specified attribute description and
+   * attribute values.
    *
    * @param attributeDescription
    *          The attribute description.
    * @param values
    *          The attribute values.
    * @throws NullPointerException
-   *           If {@code attributeDescription} or {@code values} was
-   *           {@code null}.
+   *           If {@code attributeDescription} or {@code values} was {@code
+   *           null}.
    */
-  public LinkedAttribute(AttributeDescription attributeDescription,
-      Collection<ByteString> values) throws NullPointerException
+  public LinkedAttribute(final AttributeDescription attributeDescription,
+      final Collection<ByteString> values) throws NullPointerException
   {
     this(attributeDescription);
     addAll(values);
@@ -856,26 +877,46 @@
 
 
   /**
-   * Creates a new attribute having the specified attribute description
-   * and single attribute value. The attribute description will be
-   * decoded using the default schema.
+   * Creates a new attribute having the specified attribute description and no
+   * attribute values. The attribute description will be decoded using the
+   * default schema.
+   *
+   * @param attributeDescription
+   *          The attribute description.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code attributeDescription} could not be decoded using the
+   *           default schema.
+   * @throws NullPointerException
+   *           If {@code attributeDescription} was {@code null}.
+   */
+  public LinkedAttribute(final String attributeDescription)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    this(AttributeDescription.valueOf(attributeDescription));
+  }
+
+
+
+  /**
+   * Creates a new attribute having the specified attribute description and
+   * single attribute value. The attribute description will be decoded using the
+   * default schema.
    * <p>
-   * If {@code value} is not an instance of {@code ByteString} then it
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * If {@code value} is not an instance of {@code ByteString} then it will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param attributeDescription
    *          The attribute description.
    * @param value
    *          The single attribute value.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the default schema.
+   *           If {@code attributeDescription} could not be decoded using the
+   *           default schema.
    * @throws NullPointerException
-   *           If {@code attributeDescription} or {@code value} was
-   *           {@code null}.
+   *           If {@code attributeDescription} or {@code value} was {@code null}
+   *           .
    */
-  public LinkedAttribute(String attributeDescription, Object value)
+  public LinkedAttribute(final String attributeDescription, final Object value)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     this(attributeDescription);
@@ -885,30 +926,30 @@
 
 
   /**
-   * Creates a new attribute having the specified attribute description
-   * and attribute values. The attribute description will be decoded
-   * using the default schema.
+   * Creates a new attribute having the specified attribute description and
+   * attribute values. The attribute description will be decoded using the
+   * default schema.
    * <p>
-   * Any attribute values which are not instances of {@code ByteString}
-   * will be converted using the {@link ByteString#valueOf(Object)}
-   * method.
+   * Any attribute values which are not instances of {@code ByteString} will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param attributeDescription
    *          The attribute description.
    * @param values
    *          The attribute values.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the default schema.
+   *           If {@code attributeDescription} could not be decoded using the
+   *           default schema.
    * @throws NullPointerException
-   *           If {@code attributeDescription} or {@code values} was
-   *           {@code null}.
+   *           If {@code attributeDescription} or {@code values} was {@code
+   *           null}.
    */
-  public LinkedAttribute(String attributeDescription, Object... values)
-      throws LocalizedIllegalArgumentException, NullPointerException
+  public LinkedAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
+      NullPointerException
   {
     this(attributeDescription);
-    for (Object value : values)
+    for (final Object value : values)
     {
       add(ByteString.valueOf(value));
     }
@@ -919,7 +960,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean add(ByteString value) throws NullPointerException
+  @Override
+  public boolean add(final ByteString value) throws NullPointerException
   {
     Validator.ensureNotNull(value);
     return pimpl.add(this, value);
@@ -930,8 +972,9 @@
   /**
    * {@inheritDoc}
    */
-  public boolean addAll(Collection<? extends ByteString> values,
-      Collection<? super ByteString> duplicateValues)
+  @Override
+  public boolean addAll(final Collection<? extends ByteString> values,
+      final Collection<? super ByteString> duplicateValues)
       throws NullPointerException
   {
     Validator.ensureNotNull(values);
@@ -943,6 +986,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public void clear()
   {
     pimpl.clear(this);
@@ -953,7 +997,20 @@
   /**
    * {@inheritDoc}
    */
-  public boolean containsAll(Collection<?> values)
+  @Override
+  public boolean contains(final Object value) throws NullPointerException
+  {
+    Validator.ensureNotNull(value);
+    return pimpl.contains(this, ByteString.valueOf(value));
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean containsAll(final Collection<?> values)
       throws NullPointerException
   {
     Validator.ensureNotNull(values);
@@ -965,6 +1022,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public ByteString firstValue() throws NoSuchElementException
   {
     return pimpl.firstValue(this);
@@ -975,6 +1033,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public AttributeDescription getAttributeDescription()
   {
     return attributeDescription;
@@ -985,6 +1044,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public Iterator<ByteString> iterator()
   {
     return pimpl.iterator(this);
@@ -995,8 +1055,21 @@
   /**
    * {@inheritDoc}
    */
-  public <T> boolean removeAll(Collection<T> values,
-      Collection<? super T> missingValues) throws NullPointerException
+  @Override
+  public boolean remove(final Object value) throws NullPointerException
+  {
+    Validator.ensureNotNull(value);
+    return pimpl.remove(this, ByteString.valueOf(value));
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public <T> boolean removeAll(final Collection<T> values,
+      final Collection<? super T> missingValues) throws NullPointerException
   {
     Validator.ensureNotNull(values);
     return pimpl.removeAll(this, values, missingValues);
@@ -1007,8 +1080,9 @@
   /**
    * {@inheritDoc}
    */
-  public <T> boolean retainAll(Collection<T> values,
-      Collection<? super T> missingValues) throws NullPointerException
+  @Override
+  public <T> boolean retainAll(final Collection<T> values,
+      final Collection<? super T> missingValues) throws NullPointerException
   {
     Validator.ensureNotNull(values);
     return pimpl.retainAll(this, values, missingValues);
@@ -1019,6 +1093,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public int size()
   {
     return pimpl.size(this);
@@ -1026,28 +1101,6 @@
 
 
 
-  /**
-   * {@inheritDoc}
-   */
-  public boolean contains(Object value) throws NullPointerException
-  {
-    Validator.ensureNotNull(value);
-    return pimpl.contains(this, ByteString.valueOf(value));
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean remove(Object value) throws NullPointerException
-  {
-    Validator.ensureNotNull(value);
-    return pimpl.remove(this, ByteString.valueOf(value));
-  }
-
-
-
   // Lazily computes the normalized single value.
   private ByteString normalizedSingleValue()
   {
diff --git a/sdk/src/org/opends/sdk/LinkedHashMapEntry.java b/sdk/src/org/opends/sdk/LinkedHashMapEntry.java
new file mode 100644
index 0000000..2cee13a
--- /dev/null
+++ b/sdk/src/org/opends/sdk/LinkedHashMapEntry.java
@@ -0,0 +1,156 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.util.LinkedHashMap;
+
+import org.opends.sdk.requests.Requests;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * An implementation of the {@code Entry} interface which uses a {@code
+ * LinkedHashMap} for storing attributes. Attributes are returned in the same
+ * order that they were added to the entry. All operations are supported by this
+ * implementation.
+ * <p>
+ * A {@code LinkedHashMapEntry} stores references to attributes which have been
+ * added using the {@link #addAttribute} methods. Attributes sharing the same
+ * attribute description are merged by adding the values of the new attribute to
+ * the existing attribute. More specifically, the existing attribute must be
+ * modifiable for the merge to succeed. Similarly, the {@link #removeAttribute}
+ * methods remove the specified values from the existing attribute. The
+ * {@link #replaceAttribute} methods remove the existing attribute (if present)
+ * and store a reference to the new attribute - neither the new or existing
+ * attribute need to be modifiable in this case.
+ */
+public final class LinkedHashMapEntry extends AbstractMapEntry
+{
+  /**
+   * An entry factory which can be used to create new linked hash map entries.
+   */
+  public static final EntryFactory FACTORY = new EntryFactory()
+  {
+    public Entry newEntry(final DN name) throws NullPointerException
+    {
+      return new LinkedHashMapEntry(name);
+    }
+  };
+
+
+
+  /**
+   * Creates an entry with an empty (root) distinguished name and no attributes.
+   */
+  public LinkedHashMapEntry()
+  {
+    this(DN.rootDN());
+  }
+
+
+
+  /**
+   * Creates an empty entry using the provided distinguished name and no
+   * attributes.
+   *
+   * @param name
+   *          The distinguished name of this entry.
+   * @throws NullPointerException
+   *           If {@code name} was {@code null}.
+   */
+  public LinkedHashMapEntry(final DN name) throws NullPointerException
+  {
+    super(Validator.ensureNotNull(name),
+        new LinkedHashMap<AttributeDescription, Attribute>());
+  }
+
+
+
+  /**
+   * Creates an entry having the same distinguished name, attributes, and object
+   * classes of the provided entry.
+   *
+   * @param entry
+   *          The entry to be copied.
+   * @throws NullPointerException
+   *           If {@code entry} was {@code null}.
+   */
+  public LinkedHashMapEntry(final Entry entry) throws NullPointerException
+  {
+    this(entry.getName());
+    for (final Attribute attribute : entry.getAllAttributes())
+    {
+      addAttribute(attribute);
+    }
+  }
+
+
+
+  /**
+   * Creates an empty entry using the provided distinguished name decoded using
+   * the default schema.
+   *
+   * @param name
+   *          The distinguished name of this entry.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code name} could not be decoded using the default schema.
+   * @throws NullPointerException
+   *           If {@code name} was {@code null}.
+   */
+  public LinkedHashMapEntry(final String name)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    this(DN.valueOf(name));
+  }
+
+
+
+  /**
+   * Creates a new entry using the provided lines of LDIF decoded using the
+   * default schema.
+   *
+   * @param ldifLines
+   *          Lines of LDIF containing the an LDIF add change record or an LDIF
+   *          entry record.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code ldifLines} was empty, or contained invalid LDIF, or
+   *           could not be decoded using the default schema.
+   * @throws NullPointerException
+   *           If {@code ldifLines} was {@code null} .
+   */
+  public LinkedHashMapEntry(final String... ldifLines)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    this(Requests.newAddRequest(ldifLines));
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/LoadBalancingAlgorithm.java b/sdk/src/org/opends/sdk/LoadBalancingAlgorithm.java
index 439122a..6e9ffb0 100644
--- a/sdk/src/org/opends/sdk/LoadBalancingAlgorithm.java
+++ b/sdk/src/org/opends/sdk/LoadBalancingAlgorithm.java
@@ -27,21 +27,21 @@
 
 package org.opends.sdk;
 
+
+
 /**
- * A load balancing algorithm distributes connection requests across one
- * or more underlying connection factories in an implementation defined
- * manner.
+ * A load balancing algorithm distributes connection requests across one or more
+ * underlying connection factories in an implementation defined manner.
  */
 interface LoadBalancingAlgorithm
 {
   /**
-   * Returns the next connection factory which should be used in order
-   * to obtain a connection.
+   * Returns the next connection factory which should be used in order to obtain
+   * a connection.
    *
    * @return The next connection factory.
    * @throws ErrorResultException
    *           If no connection factories are available for use.
    */
-  ConnectionFactory getNextConnectionFactory()
-      throws ErrorResultException;
+  ConnectionFactory getNextConnectionFactory() throws ErrorResultException;
 }
diff --git a/sdk/src/org/opends/sdk/LoadBalancingConnectionFactory.java b/sdk/src/org/opends/sdk/LoadBalancingConnectionFactory.java
index 40d3717..5e416d7 100644
--- a/sdk/src/org/opends/sdk/LoadBalancingConnectionFactory.java
+++ b/sdk/src/org/opends/sdk/LoadBalancingConnectionFactory.java
@@ -35,17 +35,16 @@
 
 
 /**
- * A load balancing connection factory allocates connections using the
- * provided algorithm.
+ * A load balancing connection factory allocates connections using the provided
+ * algorithm.
  */
-final class LoadBalancingConnectionFactory extends
-    AbstractConnectionFactory
+final class LoadBalancingConnectionFactory extends AbstractConnectionFactory
 {
   private final LoadBalancingAlgorithm algorithm;
 
 
 
-  public LoadBalancingConnectionFactory(LoadBalancingAlgorithm algorithm)
+  public LoadBalancingConnectionFactory(final LoadBalancingAlgorithm algorithm)
   {
     Validator.ensureNotNull(algorithm);
     this.algorithm = algorithm;
@@ -53,8 +52,9 @@
 
 
 
+  @Override
   public FutureResult<AsynchronousConnection> getAsynchronousConnection(
-      ResultHandler<AsynchronousConnection> resultHandler)
+      final ResultHandler<AsynchronousConnection> resultHandler)
   {
     ConnectionFactory factory;
 
@@ -62,10 +62,10 @@
     {
       factory = algorithm.getNextConnectionFactory();
     }
-    catch (ErrorResultException e)
+    catch (final ErrorResultException e)
     {
-      AbstractFutureResult<AsynchronousConnection> future = new AbstractFutureResult<AsynchronousConnection>(
-          resultHandler)
+      final AbstractFutureResult<AsynchronousConnection> future =
+        new AbstractFutureResult<AsynchronousConnection>(resultHandler)
       {
         public int getRequestID()
         {
diff --git a/sdk/src/org/opends/sdk/LocalizableException.java b/sdk/src/org/opends/sdk/LocalizableException.java
index 2ea8568..85396b2 100644
--- a/sdk/src/org/opends/sdk/LocalizableException.java
+++ b/sdk/src/org/opends/sdk/LocalizableException.java
@@ -28,19 +28,15 @@
 
 
 
-
-
-
-
 /**
- * This interface should be implemented by any exception interfaces that
- * expose a localizable error message.
+ * This interface should be implemented by any exception interfaces that expose
+ * a localizable error message.
  */
 public interface LocalizableException
 {
   /**
    * Returns the message that explains the problem that occurred.
-   * 
+   *
    * @return The message that explains the problem that occurred.
    */
   LocalizableMessage getMessageObject();
diff --git a/sdk/src/org/opends/sdk/LocalizableMessage.java b/sdk/src/org/opends/sdk/LocalizableMessage.java
index 58fbf4b..d38f7ec 100755
--- a/sdk/src/org/opends/sdk/LocalizableMessage.java
+++ b/sdk/src/org/opends/sdk/LocalizableMessage.java
@@ -40,25 +40,24 @@
 
 
 /**
- * A localizable message whose {@code String} representation can be
- * retrieved in one or more locales. A message is localized each time it
- * is converted to a {@code String} using one of its {@link #toString}
- * methods.
+ * A localizable message whose {@code String} representation can be retrieved in
+ * one or more locales. A message is localized each time it is converted to a
+ * {@code String} using one of its {@link #toString} methods.
  * <p>
- * Localizable messages are particularly useful in situations where a
- * message a destined for multiple recipients, potentially in different
- * locales. For example, a server application may record a message in
- * its log file using its default locale, but also send the same message
- * to the client using the client's locale (if known).
+ * Localizable messages are particularly useful in situations where a message a
+ * destined for multiple recipients, potentially in different locales. For
+ * example, a server application may record a message in its log file using its
+ * default locale, but also send the same message to the client using the
+ * client's locale (if known).
  * <p>
- * In most cases messages are intended for use in a locale-sensitive
- * manner although this class defines convenience methods for creating
- * uninternationalized messages whose {@code String} representation is
- * always the same regardless of the requested locale.
+ * In most cases messages are intended for use in a locale-sensitive manner
+ * although this class defines convenience methods for creating
+ * uninternationalized messages whose {@code String} representation is always
+ * the same regardless of the requested locale.
  * <p>
- * This class implements {@code CharSequence} so that messages can be
- * supplied as arguments to other messages. This way messages can be
- * composed of fragments of other messages if necessary.
+ * This class implements {@code CharSequence} so that messages can be supplied
+ * as arguments to other messages. This way messages can be composed of
+ * fragments of other messages if necessary.
  *
  * @see LocalizableMessageBuilder
  */
@@ -67,11 +66,11 @@
 {
   static
   {
-    LocalizableMessageDescriptor.MESSAGE_FACTORY = new LocalizableMessageDescriptor.MessageFactory()
+    LocalizableMessageDescriptor.messageFactory = new LocalizableMessageDescriptor.MessageFactory()
     {
 
-      public LocalizableMessage newMessage(LocalizableMessageDescriptor descriptor,
-          Object... args)
+      public LocalizableMessage newMessage(
+          final LocalizableMessageDescriptor descriptor, final Object... args)
       {
         return new LocalizableMessage(descriptor, args);
       }
@@ -91,30 +90,28 @@
 
 
   /**
-   * Creates an uninternationalized message whose {@code String}
-   * representation is always the same regardless of the requested
-   * locale.
+   * Creates an uninternationalized message whose {@code String} representation
+   * is always the same regardless of the requested locale.
    * <p>
-   * Note that the types for {@code args} must be consistent with any
-   * argument specifiers appearing in {@code formatString} according to
-   * the rules of {@link java.util.Formatter}. A mismatch in type
-   * information will cause this message to render without argument
-   * substitution. Before using this method you should be sure that the
-   * message you are creating is not locale sensitive. If it is locale
-   * sensitive consider defining an appropriate
+   * Note that the types for {@code args} must be consistent with any argument
+   * specifiers appearing in {@code formatString} according to the rules of
+   * {@link java.util.Formatter}. A mismatch in type information will cause this
+   * message to render without argument substitution. Before using this method
+   * you should be sure that the message you are creating is not locale
+   * sensitive. If it is locale sensitive consider defining an appropriate
    * {@link LocalizableMessageDescriptor}.
    *
    * @param formatString
    *          The raw message format string.
    * @param args
    *          The raw message parameters.
-   * @return An uninternationalized messages whose {@code String}
-   *         representation is always the same regardless of the
-   *         requested locale.
+   * @return An uninternationalized messages whose {@code String} representation
+   *         is always the same regardless of the requested locale.
    * @throws NullPointerException
    *           If {@code formatString} was {@code null}.
    */
-  public static LocalizableMessage raw(CharSequence formatString, Object... args)
+  public static LocalizableMessage raw(final CharSequence formatString,
+      final Object... args) throws NullPointerException
   {
     Validator.ensureNotNull(formatString);
     return new LocalizableMessageDescriptor.Raw(formatString).get(args);
@@ -123,15 +120,14 @@
 
 
   /**
-   * Creates a new message whose content is the {@code String}
-   * representation of the provided {@code Object}.
+   * Creates a new message whose content is the {@code String} representation of
+   * the provided {@code Object}.
    *
    * @param object
-   *          The object to be converted to a message, may be {@code
-   *          null}.
+   *          The object to be converted to a message, may be {@code null}.
    * @return The new message.
    */
-  public static LocalizableMessage valueOf(Object object)
+  public static LocalizableMessage valueOf(final Object object)
   {
     if (object instanceof LocalizableMessage)
     {
@@ -152,8 +148,8 @@
   /**
    * Returns whether we are running post 1.5 on AIX or not.
    *
-   * @return {@code true} if we are running post 1.5 on AIX and {@code
-   *         false} otherwise.
+   * @return {@code true} if we are running post 1.5 on AIX and {@code false}
+   *         otherwise.
    */
   private static boolean isAIXPost5()
   {
@@ -169,8 +165,7 @@
     {
       System.err.println("Cannot get the java version: " + t);
     }
-    final boolean isAIX = "aix".equalsIgnoreCase(System
-        .getProperty("os.name"));
+    final boolean isAIX = "aix".equalsIgnoreCase(System.getProperty("os.name"));
     return !isJDK15 && isAIX;
   }
 
@@ -185,15 +180,16 @@
 
 
   /**
-   * Creates a new parameterized message instance. See the class header
-   * for instructions on how to create messages outside of this package.
+   * Creates a new parameterized message instance. See the class header for
+   * instructions on how to create messages outside of this package.
    *
    * @param descriptor
    *          The message descriptor.
    * @param args
    *          The message parameters.
    */
-  private LocalizableMessage(LocalizableMessageDescriptor descriptor, Object... args)
+  private LocalizableMessage(final LocalizableMessageDescriptor descriptor,
+      final Object... args)
   {
     this.descriptor = descriptor;
     this.args = args;
@@ -202,18 +198,17 @@
 
 
   /**
-   * Returns the {@code char} value at the specified index of the
-   * {@code String} representation of this message in the default
-   * locale.
+   * Returns the {@code char} value at the specified index of the {@code String}
+   * representation of this message in the default locale.
    *
    * @param index
    *          The index of the {@code char} value to be returned.
    * @return The specified {@code char} value.
    * @throws IndexOutOfBoundsException
-   *           If the {@code index} argument is negative or not less
-   *           than {@code length()}.
+   *           If the {@code index} argument is negative or not less than
+   *           {@code length()}.
    */
-  public char charAt(int index) throws IndexOutOfBoundsException
+  public char charAt(final int index) throws IndexOutOfBoundsException
   {
     return charAt(Locale.getDefault(), index);
   }
@@ -221,9 +216,8 @@
 
 
   /**
-   * Returns the {@code char} value at the specified index of the
-   * {@code String} representation of this message in the specified
-   * locale.
+   * Returns the {@code char} value at the specified index of the {@code String}
+   * representation of this message in the specified locale.
    *
    * @param locale
    *          The locale.
@@ -231,12 +225,12 @@
    *          The index of the {@code char} value to be returned.
    * @return The specified {@code char} value.
    * @throws IndexOutOfBoundsException
-   *           If the {@code index} argument is negative or not less
-   *           than {@code length()}.
+   *           If the {@code index} argument is negative or not less than
+   *           {@code length()}.
    * @throws NullPointerException
    *           If {@code locale} was {@code null}.
    */
-  public char charAt(Locale locale, int index)
+  public char charAt(final Locale locale, final int index)
       throws IndexOutOfBoundsException, NullPointerException
   {
     return toString(locale).charAt(index);
@@ -245,18 +239,16 @@
 
 
   /**
-   * Compares this message with the specified message for order in the
-   * default locale. Returns a negative integer, zero, or a positive
-   * integer as this object is less than, equal to, or greater than the
-   * specified object.
+   * Compares this message with the specified message for order in the default
+   * locale. Returns a negative integer, zero, or a positive integer as this
+   * object is less than, equal to, or greater than the specified object.
    *
    * @param message
    *          The message to be compared.
-   * @return A negative integer, zero, or a positive integer as this
-   *         object is less than, equal to, or greater than the
-   *         specified object.
+   * @return A negative integer, zero, or a positive integer as this object is
+   *         less than, equal to, or greater than the specified object.
    */
-  public int compareTo(LocalizableMessage message)
+  public int compareTo(final LocalizableMessage message)
   {
     return toString().compareTo(message.toString());
   }
@@ -264,16 +256,17 @@
 
 
   /**
-   * Returns {@code true} if the provided object is a message whose
-   * {@code String} representation is equal to the {@code String}
-   * representation of this message in the default locale.
+   * Returns {@code true} if the provided object is a message whose {@code
+   * String} representation is equal to the {@code String} representation of
+   * this message in the default locale.
    *
    * @param o
    *          The object to be compared for equality with this message.
-   * @return {@code true} if this message is the equal to {@code o},
-   *         otherwise {@code false}.
+   * @return {@code true} if this message is the equal to {@code o}, otherwise
+   *         {@code false}.
    */
-  public boolean equals(Object o)
+  @Override
+  public boolean equals(final Object o)
   {
     if (this == o)
     {
@@ -298,38 +291,35 @@
    * @param formatter
    *          The {@link Formatter}.
    * @param flags
-   *          The flags modify the output format. The value is
-   *          interpreted as a bitmask. Any combination of the following
-   *          flags may be set:
+   *          The flags modify the output format. The value is interpreted as a
+   *          bitmask. Any combination of the following flags may be set:
    *          {@link java.util.FormattableFlags#LEFT_JUSTIFY},
    *          {@link java.util.FormattableFlags#UPPERCASE}, and
-   *          {@link java.util.FormattableFlags#ALTERNATE}. If no flags
-   *          are set, the default formatting of the implementing class
-   *          will apply.
+   *          {@link java.util.FormattableFlags#ALTERNATE}. If no flags are set,
+   *          the default formatting of the implementing class will apply.
    * @param width
-   *          The minimum number of characters to be written to the
-   *          output. If the length of the converted value is less than
-   *          the {@code width} then the output will be padded by white
-   *          space until the total number of characters equals width.
-   *          The padding is at the beginning by default. If the
-   *          {@link java.util.FormattableFlags#LEFT_JUSTIFY} flag is
-   *          set then the padding will be at the end. If {@code width}
+   *          The minimum number of characters to be written to the output. If
+   *          the length of the converted value is less than the {@code width}
+   *          then the output will be padded by white space until the total
+   *          number of characters equals width. The padding is at the beginning
+   *          by default. If the {@link java.util.FormattableFlags#LEFT_JUSTIFY}
+   *          flag is set then the padding will be at the end. If {@code width}
    *          is {@code -1} then there is no minimum.
    * @param precision
-   *          The maximum number of characters to be written to the
-   *          output. The precision is applied before the width, thus
-   *          the output will be truncated to {@code precision}
-   *          characters even if the {@code width} is greater than the
-   *          {@code precision}. If {@code precision} is {@code -1} then
-   *          there is no explicit limit on the number of characters.
+   *          The maximum number of characters to be written to the output. The
+   *          precision is applied before the width, thus the output will be
+   *          truncated to {@code precision} characters even if the {@code
+   *          width} is greater than the {@code precision}. If {@code precision}
+   *          is {@code -1} then there is no explicit limit on the number of
+   *          characters.
    * @throws IllegalFormatException
-   *           If any of the parameters are invalid. For specification
-   *           of all possible formatting errors, see the <a
-   *           href="../util/Formatter.html#detail">Details</a> section
-   *           of the formatter class specification.
+   *           If any of the parameters are invalid. For specification of all
+   *           possible formatting errors, see the <a
+   *           href="../util/Formatter.html#detail">Details</a> section of the
+   *           formatter class specification.
    */
-  public void formatTo(Formatter formatter, int flags, int width,
-      int precision) throws IllegalFormatException
+  public void formatTo(final Formatter formatter, final int flags,
+      final int width, final int precision) throws IllegalFormatException
   {
     // Ignores flags, width and precision for now.
     // see javadoc for Formattable
@@ -340,12 +330,12 @@
 
 
   /**
-   * Returns the hash code value for this message calculated using the
-   * hash code of the {@code String} representation of this message in
-   * the default locale.
+   * Returns the hash code value for this message calculated using the hash code
+   * of the {@code String} representation of this message in the default locale.
    *
    * @return The hash code value for this message.
    */
+  @Override
   public int hashCode()
   {
     return toString().hashCode();
@@ -354,11 +344,11 @@
 
 
   /**
-   * Returns the length of the {@code String} representation of this
-   * message in the default locale.
+   * Returns the length of the {@code String} representation of this message in
+   * the default locale.
    *
-   * @return The length of the {@code String} representation of this
-   *         message in the default locale.
+   * @return The length of the {@code String} representation of this message in
+   *         the default locale.
    */
   public int length()
   {
@@ -368,17 +358,17 @@
 
 
   /**
-   * Returns the length of the {@code String} representation of this
-   * message in the specified locale.
+   * Returns the length of the {@code String} representation of this message in
+   * the specified locale.
    *
    * @param locale
    *          The locale.
-   * @return The length of the {@code String} representation of this
-   *         message in the specified locale.
+   * @return The length of the {@code String} representation of this message in
+   *         the specified locale.
    * @throws NullPointerException
    *           If {@code locale} was {@code null}.
    */
-  public int length(Locale locale) throws NullPointerException
+  public int length(final Locale locale) throws NullPointerException
   {
     return toString(locale).length();
   }
@@ -386,13 +376,12 @@
 
 
   /**
-   * Returns a new {@code CharSequence} which is a subsequence of the
-   * {@code String} representation of this message in the default
-   * locale. The subsequence starts with the {@code char} value at the
-   * specified index and ends with the {@code char} value at index
-   * {@code end - 1} . The length (in {@code char}s) of the returned
-   * sequence is {@code end - start}, so if {@code start == end} then an
-   * empty sequence is returned.
+   * Returns a new {@code CharSequence} which is a subsequence of the {@code
+   * String} representation of this message in the default locale. The
+   * subsequence starts with the {@code char} value at the specified index and
+   * ends with the {@code char} value at index {@code end - 1} . The length (in
+   * {@code char}s) of the returned sequence is {@code end - start}, so if
+   * {@code start == end} then an empty sequence is returned.
    *
    * @param start
    *          The start index, inclusive.
@@ -400,11 +389,11 @@
    *          The end index, exclusive.
    * @return The specified subsequence.
    * @throws IndexOutOfBoundsException
-   *           If {@code start} or {@code end} are negative, if {@code
-   *           end} is greater than {@code length()}, or if {@code
-   *           start} is greater than {@code end}.
+   *           If {@code start} or {@code end} are negative, if {@code end} is
+   *           greater than {@code length()}, or if {@code start} is greater
+   *           than {@code end}.
    */
-  public CharSequence subSequence(int start, int end)
+  public CharSequence subSequence(final int start, final int end)
       throws IndexOutOfBoundsException
   {
     return subSequence(Locale.getDefault(), start, end);
@@ -413,13 +402,12 @@
 
 
   /**
-   * Returns a new {@code CharSequence} which is a subsequence of the
-   * {@code String} representation of this message in the specified
-   * locale. The subsequence starts with the {@code char} value at the
-   * specified index and ends with the {@code char} value at index
-   * {@code end - 1} . The length (in {@code char}s) of the returned
-   * sequence is {@code end - start}, so if {@code start == end} then an
-   * empty sequence is returned.
+   * Returns a new {@code CharSequence} which is a subsequence of the {@code
+   * String} representation of this message in the specified locale. The
+   * subsequence starts with the {@code char} value at the specified index and
+   * ends with the {@code char} value at index {@code end - 1} . The length (in
+   * {@code char}s) of the returned sequence is {@code end - start}, so if
+   * {@code start == end} then an empty sequence is returned.
    *
    * @param locale
    *          The locale.
@@ -429,14 +417,14 @@
    *          The end index, exclusive.
    * @return The specified subsequence.
    * @throws IndexOutOfBoundsException
-   *           If {@code start} or {@code end} are negative, if {@code
-   *           end} is greater than {@code length()}, or if {@code
-   *           start} is greater than {@code end}.
+   *           If {@code start} or {@code end} are negative, if {@code end} is
+   *           greater than {@code length()}, or if {@code start} is greater
+   *           than {@code end}.
    * @throws NullPointerException
    *           If {@code locale} was {@code null}.
    */
-  public CharSequence subSequence(Locale locale, int start, int end)
-      throws IndexOutOfBoundsException, NullPointerException
+  public CharSequence subSequence(final Locale locale, final int start,
+      final int end) throws IndexOutOfBoundsException, NullPointerException
   {
     return toString(locale).subSequence(start, end);
   }
@@ -444,11 +432,12 @@
 
 
   /**
-   * Returns the {@code String} representation of this message in the
-   * default locale.
+   * Returns the {@code String} representation of this message in the default
+   * locale.
    *
    * @return The {@code String} representation of this message.
    */
+  @Override
   public String toString()
   {
     return toString(Locale.getDefault());
@@ -457,8 +446,8 @@
 
 
   /**
-   * Returns the {@code String} representation of this message in the
-   * specified locale.
+   * Returns the {@code String} representation of this message in the specified
+   * locale.
    *
    * @param locale
    *          The locale.
@@ -466,7 +455,7 @@
    * @throws NullPointerException
    *           If {@code locale} was {@code null}.
    */
-  public String toString(Locale locale) throws NullPointerException
+  public String toString(final Locale locale) throws NullPointerException
   {
     String s;
     final String fmt = descriptor.getFormatString(locale);
@@ -504,19 +493,16 @@
                 newArgs[i] = args[i];
               }
             }
-            s = new Formatter(locale).format(locale, fmt, newArgs)
-                .toString();
+            s = new Formatter(locale).format(locale, fmt, newArgs).toString();
           }
           else
           {
-            s = new Formatter(locale).format(locale, fmt, args)
-                .toString();
+            s = new Formatter(locale).format(locale, fmt, args).toString();
           }
         }
         else
         {
-          s = new Formatter(locale).format(locale, fmt, args)
-              .toString();
+          s = new Formatter(locale).format(locale, fmt, args).toString();
         }
       }
       catch (final IllegalFormatException e)
diff --git a/sdk/src/org/opends/sdk/LocalizableMessageBuilder.java b/sdk/src/org/opends/sdk/LocalizableMessageBuilder.java
index 97ea423..978c0bf 100755
--- a/sdk/src/org/opends/sdk/LocalizableMessageBuilder.java
+++ b/sdk/src/org/opends/sdk/LocalizableMessageBuilder.java
@@ -39,26 +39,24 @@
 
 
 /**
- * A mutable sequence of localizable messages and their parameters. As
- * messages are appended they are translated to their string
- * representation for storage using the locale specified in the
- * constructor.
+ * A mutable sequence of localizable messages and their parameters. As messages
+ * are appended they are translated to their string representation for storage
+ * using the locale specified in the constructor.
  * <p>
  * Note that before you use this class you should consider whether it is
- * appropriate. In general composing messages by appending message to
- * each other may not produce a message that is formatted appropriately
- * for all locales.
+ * appropriate. In general composing messages by appending message to each other
+ * may not produce a message that is formatted appropriately for all locales.
  * <p>
- * It is usually better to create messages by composition. In other
- * words you should create a base message that contains one or more
- * string argument specifiers (%s) and define other message objects to
- * use as replacement variables. In this way language translators have a
- * change to reformat the message for a particular locale if necessary.
+ * It is usually better to create messages by composition. In other words you
+ * should create a base message that contains one or more string argument
+ * specifiers (%s) and define other message objects to use as replacement
+ * variables. In this way language translators have a change to reformat the
+ * message for a particular locale if necessary.
  *
  * @see LocalizableMessage
  */
-public final class LocalizableMessageBuilder implements Appendable, CharSequence,
-    Serializable
+public final class LocalizableMessageBuilder implements Appendable,
+    CharSequence, Serializable
 {
 
   private static final long serialVersionUID = -3292823563904285315L;
@@ -79,15 +77,16 @@
 
 
   /**
-   * Creates a new message builder whose content is initially equal to
-   * the provided message.
+   * Creates a new message builder whose content is initially equal to the
+   * provided message.
    *
    * @param message
    *          The initial content of the message builder.
    * @throws NullPointerException
    *           If {@code message} was {@code null}.
    */
-  public LocalizableMessageBuilder(LocalizableMessage message) throws NullPointerException
+  public LocalizableMessageBuilder(final LocalizableMessage message)
+      throws NullPointerException
   {
     append(message);
   }
@@ -95,15 +94,16 @@
 
 
   /**
-   * Creates a new message builder whose content is initially equal to
-   * the provided message builder.
+   * Creates a new message builder whose content is initially equal to the
+   * provided message builder.
    *
    * @param builder
    *          The initial content of the message builder.
    * @throws NullPointerException
    *           If {@code builder} was {@code null}.
    */
-  public LocalizableMessageBuilder(LocalizableMessageBuilder builder)
+  public LocalizableMessageBuilder(final LocalizableMessageBuilder builder)
+      throws NullPointerException
   {
     for (final LocalizableMessage message : builder.messages)
     {
@@ -114,14 +114,13 @@
 
 
   /**
-   * Creates a new message builder whose content is initially equal to
-   * the {@code String} representation of the provided {@code Object}.
+   * Creates a new message builder whose content is initially equal to the
+   * {@code String} representation of the provided {@code Object}.
    *
    * @param object
-   *          The initial content of the message builder, may be {@code
-   *          null}.
+   *          The initial content of the message builder, may be {@code null}.
    */
-  public LocalizableMessageBuilder(Object object)
+  public LocalizableMessageBuilder(final Object object)
   {
     append(object);
   }
@@ -135,7 +134,7 @@
    *          The character to be appended.
    * @return A reference to this message builder.
    */
-  public LocalizableMessageBuilder append(char c)
+  public LocalizableMessageBuilder append(final char c)
   {
     return append(LocalizableMessage.valueOf(c));
   }
@@ -151,7 +150,7 @@
    * @throws NullPointerException
    *           If {@code cs} was {@code null}.
    */
-  public LocalizableMessageBuilder append(CharSequence cs)
+  public LocalizableMessageBuilder append(final CharSequence cs)
       throws NullPointerException
   {
     Validator.ensureNotNull(cs);
@@ -161,11 +160,11 @@
 
 
   /**
-   * Appends a subsequence of the provided character sequence to this
-   * message builder.
+   * Appends a subsequence of the provided character sequence to this message
+   * builder.
    * <p>
-   * An invocation of this method of the form {@code append(cs, start,
-   * end)}, behaves in exactly the same way as the invocation
+   * An invocation of this method of the form {@code append(cs, start, end)},
+   * behaves in exactly the same way as the invocation
    *
    * <pre>
    * append(cs.subSequence(start, end))
@@ -176,18 +175,19 @@
    * @param start
    *          The index of the first character in the subsequence.
    * @param end
-   *          The index of the character following the last character in
-   *          the subsequence.
+   *          The index of the character following the last character in the
+   *          subsequence.
    * @return A reference to this message builder.
    * @throws IndexOutOfBoundsException
-   *           If {@code start} or {@code end} are negative, {@code
-   *           start} is greater than {@code end}, or {@code end} is
-   *           greater than {@code csq.length()}.
+   *           If {@code start} or {@code end} are negative, {@code start} is
+   *           greater than {@code end}, or {@code end} is greater than {@code
+   *           csq.length()}.
    * @throws NullPointerException
    *           If {@code cs} was {@code null}.
    */
-  public LocalizableMessageBuilder append(CharSequence cs, int start, int end)
-      throws IndexOutOfBoundsException, NullPointerException
+  public LocalizableMessageBuilder append(final CharSequence cs,
+      final int start, final int end) throws IndexOutOfBoundsException,
+      NullPointerException
   {
     return append(cs.subSequence(start, end));
   }
@@ -201,7 +201,7 @@
    *          The integer to be appended.
    * @return A reference to this message builder.
    */
-  public LocalizableMessageBuilder append(int value)
+  public LocalizableMessageBuilder append(final int value)
   {
     return append(LocalizableMessage.valueOf(value));
   }
@@ -217,7 +217,7 @@
    * @throws NullPointerException
    *           If {@code message} was {@code null}.
    */
-  public LocalizableMessageBuilder append(LocalizableMessage message)
+  public LocalizableMessageBuilder append(final LocalizableMessage message)
       throws NullPointerException
   {
     Validator.ensureNotNull(message);
@@ -228,14 +228,14 @@
 
 
   /**
-   * Appends the {@code String} representation of the provided {@code
-   * Object} to this message builder.
+   * Appends the {@code String} representation of the provided {@code Object} to
+   * this message builder.
    *
    * @param object
    *          The object to be appended, may be {@code null}.
    * @return A reference to this message builder.
    */
-  public LocalizableMessageBuilder append(Object object)
+  public LocalizableMessageBuilder append(final Object object)
   {
     return append(LocalizableMessage.valueOf(object));
   }
@@ -243,18 +243,17 @@
 
 
   /**
-   * Returns the {@code char} value at the specified index of the
-   * {@code String} representation of this message builder in the
-   * default locale.
+   * Returns the {@code char} value at the specified index of the {@code String}
+   * representation of this message builder in the default locale.
    *
    * @param index
    *          The index of the {@code char} value to be returned.
    * @return The specified {@code char} value.
    * @throws IndexOutOfBoundsException
-   *           If the {@code index} argument is negative or not less
-   *           than {@code length()}.
+   *           If the {@code index} argument is negative or not less than
+   *           {@code length()}.
    */
-  public char charAt(int index) throws IndexOutOfBoundsException
+  public char charAt(final int index) throws IndexOutOfBoundsException
   {
     return charAt(Locale.getDefault(), index);
   }
@@ -262,9 +261,8 @@
 
 
   /**
-   * Returns the {@code char} value at the specified index of the
-   * {@code String} representation of this message builder in the
-   * specified locale.
+   * Returns the {@code char} value at the specified index of the {@code String}
+   * representation of this message builder in the specified locale.
    *
    * @param locale
    *          The locale.
@@ -272,12 +270,12 @@
    *          The index of the {@code char} value to be returned.
    * @return The specified {@code char} value.
    * @throws IndexOutOfBoundsException
-   *           If the {@code index} argument is negative or not less
-   *           than {@code length()}.
+   *           If the {@code index} argument is negative or not less than
+   *           {@code length()}.
    * @throws NullPointerException
    *           If {@code locale} was {@code null}.
    */
-  public char charAt(Locale locale, int index)
+  public char charAt(final Locale locale, final int index)
       throws IndexOutOfBoundsException, NullPointerException
   {
     return toString(locale).charAt(index);
@@ -286,11 +284,11 @@
 
 
   /**
-   * Returns the length of the {@code String} representation of this
-   * message builder in the default locale.
+   * Returns the length of the {@code String} representation of this message
+   * builder in the default locale.
    *
-   * @return The length of the {@code String} representation of this
-   *         message builder in the default locale.
+   * @return The length of the {@code String} representation of this message
+   *         builder in the default locale.
    */
   public int length()
   {
@@ -300,17 +298,17 @@
 
 
   /**
-   * Returns the length of the {@code String} representation of this
-   * message builder in the specified locale.
+   * Returns the length of the {@code String} representation of this message
+   * builder in the specified locale.
    *
    * @param locale
    *          The locale.
-   * @return The length of the {@code String} representation of this
-   *         message builder in the specified locale.
+   * @return The length of the {@code String} representation of this message
+   *         builder in the specified locale.
    * @throws NullPointerException
    *           If {@code locale} was {@code null}.
    */
-  public int length(Locale locale) throws NullPointerException
+  public int length(final Locale locale) throws NullPointerException
   {
     return toString(locale).length();
   }
@@ -318,13 +316,12 @@
 
 
   /**
-   * Returns a new {@code CharSequence} which is a subsequence of the
-   * {@code String} representation of this message builder in the
-   * default locale. The subsequence starts with the {@code char} value
-   * at the specified index and ends with the {@code char} value at
-   * index {@code end - 1} . The length (in {@code char}s) of the
-   * returned sequence is {@code end - start}, so if {@code start ==
-   * end} then an empty sequence is returned.
+   * Returns a new {@code CharSequence} which is a subsequence of the {@code
+   * String} representation of this message builder in the default locale. The
+   * subsequence starts with the {@code char} value at the specified index and
+   * ends with the {@code char} value at index {@code end - 1} . The length (in
+   * {@code char}s) of the returned sequence is {@code end - start}, so if
+   * {@code start == end} then an empty sequence is returned.
    *
    * @param start
    *          The start index, inclusive.
@@ -332,11 +329,11 @@
    *          The end index, exclusive.
    * @return The specified subsequence.
    * @throws IndexOutOfBoundsException
-   *           If {@code start} or {@code end} are negative, if {@code
-   *           end} is greater than {@code length()}, or if {@code
-   *           start} is greater than {@code end}.
+   *           If {@code start} or {@code end} are negative, if {@code end} is
+   *           greater than {@code length()}, or if {@code start} is greater
+   *           than {@code end}.
    */
-  public CharSequence subSequence(int start, int end)
+  public CharSequence subSequence(final int start, final int end)
       throws IndexOutOfBoundsException
   {
     return subSequence(Locale.getDefault(), start, end);
@@ -345,13 +342,12 @@
 
 
   /**
-   * Returns a new {@code CharSequence} which is a subsequence of the
-   * {@code String} representation of this message builder in the
-   * specified locale. The subsequence starts with the {@code char}
-   * value at the specified index and ends with the {@code char} value
-   * at index {@code end - 1} . The length (in {@code char}s) of the
-   * returned sequence is {@code end - start}, so if {@code start ==
-   * end} then an empty sequence is returned.
+   * Returns a new {@code CharSequence} which is a subsequence of the {@code
+   * String} representation of this message builder in the specified locale. The
+   * subsequence starts with the {@code char} value at the specified index and
+   * ends with the {@code char} value at index {@code end - 1} . The length (in
+   * {@code char}s) of the returned sequence is {@code end - start}, so if
+   * {@code start == end} then an empty sequence is returned.
    *
    * @param locale
    *          The locale.
@@ -361,14 +357,14 @@
    *          The end index, exclusive.
    * @return The specified subsequence.
    * @throws IndexOutOfBoundsException
-   *           If {@code start} or {@code end} are negative, if {@code
-   *           end} is greater than {@code length()}, or if {@code
-   *           start} is greater than {@code end}.
+   *           If {@code start} or {@code end} are negative, if {@code end} is
+   *           greater than {@code length()}, or if {@code start} is greater
+   *           than {@code end}.
    * @throws NullPointerException
    *           If {@code locale} was {@code null}.
    */
-  public CharSequence subSequence(Locale locale, int start, int end)
-      throws IndexOutOfBoundsException, NullPointerException
+  public CharSequence subSequence(final Locale locale, final int start,
+      final int end) throws IndexOutOfBoundsException, NullPointerException
   {
     return toString(locale).subSequence(start, end);
   }
@@ -376,11 +372,12 @@
 
 
   /**
-   * Returns the {@link LocalizableMessage} representation of this message builder.
-   * Subsequent changes to this message builder will not modify the
+   * Returns the {@link LocalizableMessage} representation of this message
+   * builder. Subsequent changes to this message builder will not modify the
    * returned {@code LocalizableMessage}.
    *
-   * @return The {@code LocalizableMessage} representation of this message builder.
+   * @return The {@code LocalizableMessage} representation of this message
+   *         builder.
    */
   public LocalizableMessage toMessage()
   {
@@ -402,11 +399,12 @@
 
 
   /**
-   * Returns the {@code String} representation of this message builder
-   * in the default locale.
+   * Returns the {@code String} representation of this message builder in the
+   * default locale.
    *
    * @return The {@code String} representation of this message builder.
    */
+  @Override
   public String toString()
   {
     return toString(Locale.getDefault());
@@ -415,8 +413,8 @@
 
 
   /**
-   * Returns the {@code String} representation of this message builder
-   * in the specified locale.
+   * Returns the {@code String} representation of this message builder in the
+   * specified locale.
    *
    * @param locale
    *          The locale.
@@ -424,7 +422,7 @@
    * @throws NullPointerException
    *           If {@code locale} was {@code null}.
    */
-  public String toString(Locale locale)
+  public String toString(final Locale locale) throws NullPointerException
   {
     final StringBuilder builder = new StringBuilder();
     for (final LocalizableMessage message : messages)
diff --git a/sdk/src/org/opends/sdk/LocalizedIllegalArgumentException.java b/sdk/src/org/opends/sdk/LocalizedIllegalArgumentException.java
index 8ab18d8..799d3f0 100644
--- a/sdk/src/org/opends/sdk/LocalizedIllegalArgumentException.java
+++ b/sdk/src/org/opends/sdk/LocalizedIllegalArgumentException.java
@@ -29,26 +29,21 @@
 
 
 
-
-
-
-
 /**
- * Thrown to indicate that a method has been passed an illegal or
- * inappropriate argument.
+ * Thrown to indicate that a method has been passed an illegal or inappropriate
+ * argument.
  * <p>
- * A {@code LocalizedIllegalArgumentException} contains a localized
- * error message which maybe used to provide the user with detailed
- * diagnosis information. The localized message can be retrieved using
- * the {@link #getMessageObject} method.
+ * A {@code LocalizedIllegalArgumentException} contains a localized error
+ * message which maybe used to provide the user with detailed diagnosis
+ * information. The localized message can be retrieved using the
+ * {@link #getMessageObject} method.
  * <p>
- * A {@code LocalizedIllegalArgumentException} is typically used to
- * indicate problems parsing values such as distinguished names and
- * filters.
+ * A {@code LocalizedIllegalArgumentException} is typically used to indicate
+ * problems parsing values such as distinguished names and filters.
  */
 @SuppressWarnings("serial")
-public class LocalizedIllegalArgumentException extends
-    IllegalArgumentException implements LocalizableException
+public class LocalizedIllegalArgumentException extends IllegalArgumentException
+    implements LocalizableException
 {
   // The I18N message associated with this exception.
   private final LocalizableMessage message;
@@ -56,13 +51,13 @@
 
 
   /**
-   * Creates a new localized illegal argument exception with the
-   * provided message.
+   * Creates a new localized illegal argument exception with the provided
+   * message.
    *
    * @param message
    *          The message that explains the problem that occurred.
    */
-  public LocalizedIllegalArgumentException(LocalizableMessage message)
+  public LocalizedIllegalArgumentException(final LocalizableMessage message)
   {
     super(String.valueOf(message));
     this.message = message;
@@ -71,19 +66,18 @@
 
 
   /**
-   * Creates a new localized illegal argument exception with the
-   * provided message and cause.
+   * Creates a new localized illegal argument exception with the provided
+   * message and cause.
    *
    * @param message
    *          The message that explains the problem that occurred.
    * @param cause
-   *          The cause which may be later retrieved by the
-   *          {@link #getCause} method. A {@code null} value is
-   *          permitted, and indicates that the cause is nonexistent or
-   *          unknown.
+   *          The cause which may be later retrieved by the {@link #getCause}
+   *          method. A {@code null} value is permitted, and indicates that the
+   *          cause is nonexistent or unknown.
    */
-  public LocalizedIllegalArgumentException(LocalizableMessage message,
-      Throwable cause)
+  public LocalizedIllegalArgumentException(final LocalizableMessage message,
+      final Throwable cause)
   {
     super(String.valueOf(message), cause);
     this.message = message;
diff --git a/sdk/src/org/opends/sdk/Matcher.java b/sdk/src/org/opends/sdk/Matcher.java
index 4d99111..5145c71 100644
--- a/sdk/src/org/opends/sdk/Matcher.java
+++ b/sdk/src/org/opends/sdk/Matcher.java
@@ -29,7 +29,7 @@
 
 
 
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.util.StaticUtils.DEBUG_LOG;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -49,13 +49,13 @@
  */
 public final class Matcher
 {
-  private static class AndMatcherImpl extends MatcherImpl
+  private static final class AndMatcherImpl extends MatcherImpl
   {
     private final List<MatcherImpl> subMatchers;
 
 
 
-    private AndMatcherImpl(List<MatcherImpl> subMatchers)
+    private AndMatcherImpl(final List<MatcherImpl> subMatchers)
     {
       this.subMatchers = subMatchers;
     }
@@ -63,7 +63,7 @@
 
 
     @Override
-    public ConditionResult matches(Entry entry)
+    public ConditionResult matches(final Entry entry)
     {
       ConditionResult r = ConditionResult.TRUE;
       for (final MatcherImpl m : subMatchers)
@@ -81,7 +81,7 @@
 
 
 
-  private static class AssertionMatcherImpl extends MatcherImpl
+  private static final class AssertionMatcherImpl extends MatcherImpl
   {
     private final Assertion assertion;
 
@@ -96,9 +96,9 @@
 
 
     private AssertionMatcherImpl(
-        AttributeDescription attributeDescription, MatchingRule rule,
-        MatchingRuleUse ruleUse, Assertion assertion,
-        boolean dnAttributes)
+        final AttributeDescription attributeDescription,
+        final MatchingRule rule, final MatchingRuleUse ruleUse,
+        final Assertion assertion, final boolean dnAttributes)
     {
       this.attributeDescription = attributeDescription;
       this.rule = rule;
@@ -110,7 +110,7 @@
 
 
     @Override
-    public ConditionResult matches(Entry entry)
+    public ConditionResult matches(final Entry entry)
     {
       ConditionResult r = ConditionResult.FALSE;
       if (attributeDescription != null)
@@ -135,13 +135,12 @@
         // If the type field is absent and the matchingRule is present,
         // the matchValue is compared against all attributes in an entry
         // that support that matchingRule.
-        for (final Attribute a : entry.getAttributes())
+        for (final Attribute a : entry.getAllAttributes())
         {
           if (ruleUse.hasAttribute(a.getAttributeDescription()
               .getAttributeType()))
           {
-            final ConditionResult p = Matcher.matches(a, rule,
-                assertion);
+            final ConditionResult p = Matcher.matches(a, rule, assertion);
             if (p == ConditionResult.TRUE)
             {
               return p;
@@ -162,12 +161,12 @@
         final DN dn = entry.getName();
         for (final RDN rdn : dn)
         {
-          for (final RDN.AVA ava : rdn)
+          for (final AVA ava : rdn)
           {
             if (ruleUse.hasAttribute(ava.getAttributeType()))
             {
-              final ConditionResult p = Matcher.matches(ava
-                  .getAttributeValue(), rule, assertion);
+              final ConditionResult p = Matcher.matches(
+                  ava.getAttributeValue(), rule, assertion);
               if (p == ConditionResult.TRUE)
               {
                 return p;
@@ -186,7 +185,7 @@
   private static class FalseMatcherImpl extends MatcherImpl
   {
     @Override
-    public ConditionResult matches(Entry entry)
+    public ConditionResult matches(final Entry entry)
     {
       return ConditionResult.FALSE;
     }
@@ -201,13 +200,13 @@
 
 
 
-  private static class NotMatcherImpl extends MatcherImpl
+  private static final class NotMatcherImpl extends MatcherImpl
   {
     private final MatcherImpl subFilter;
 
 
 
-    private NotMatcherImpl(MatcherImpl subFilter)
+    private NotMatcherImpl(final MatcherImpl subFilter)
     {
       this.subFilter = subFilter;
     }
@@ -215,7 +214,7 @@
 
 
     @Override
-    public ConditionResult matches(Entry entry)
+    public ConditionResult matches(final Entry entry)
     {
       return ConditionResult.not(subFilter.matches(entry));
     }
@@ -223,13 +222,13 @@
 
 
 
-  private static class OrMatcherImpl extends MatcherImpl
+  private static final class OrMatcherImpl extends MatcherImpl
   {
     private final List<MatcherImpl> subMatchers;
 
 
 
-    private OrMatcherImpl(List<MatcherImpl> subMatchers)
+    private OrMatcherImpl(final List<MatcherImpl> subMatchers)
     {
       this.subMatchers = subMatchers;
     }
@@ -237,7 +236,7 @@
 
 
     @Override
-    public ConditionResult matches(Entry entry)
+    public ConditionResult matches(final Entry entry)
     {
       ConditionResult r = ConditionResult.FALSE;
       for (final MatcherImpl m : subMatchers)
@@ -255,13 +254,13 @@
 
 
 
-  private static class PresentMatcherImpl extends MatcherImpl
+  private static final class PresentMatcherImpl extends MatcherImpl
   {
     private final AttributeDescription attribute;
 
 
 
-    private PresentMatcherImpl(AttributeDescription attribute)
+    private PresentMatcherImpl(final AttributeDescription attribute)
     {
       this.attribute = attribute;
     }
@@ -269,7 +268,7 @@
 
 
     @Override
-    public ConditionResult matches(Entry entry)
+    public ConditionResult matches(final Entry entry)
     {
       return entry.getAttribute(attribute) == null ? ConditionResult.FALSE
           : ConditionResult.TRUE;
@@ -281,7 +280,7 @@
   private static class TrueMatcherImpl extends MatcherImpl
   {
     @Override
-    public ConditionResult matches(Entry entry)
+    public ConditionResult matches(final Entry entry)
     {
       return ConditionResult.TRUE;
     }
@@ -292,7 +291,7 @@
   private static class UndefinedMatcherImpl extends MatcherImpl
   {
     @Override
-    public ConditionResult matches(Entry entry)
+    public ConditionResult matches(final Entry entry)
     {
       return ConditionResult.UNDEFINED;
     }
@@ -306,8 +305,8 @@
   private static final class Visitor implements
       FilterVisitor<MatcherImpl, Schema>
   {
-    public MatcherImpl visitAndFilter(Schema schema,
-        List<Filter> subFilters)
+    public MatcherImpl visitAndFilter(final Schema schema,
+        final List<Filter> subFilters)
     {
       if (subFilters.isEmpty())
       {
@@ -330,8 +329,8 @@
 
 
 
-    public MatcherImpl visitApproxMatchFilter(Schema schema,
-        String attributeDescription, ByteString assertionValue)
+    public MatcherImpl visitApproxMatchFilter(final Schema schema,
+        final String attributeDescription, final ByteString assertionValue)
     {
       AttributeDescription ad;
       MatchingRule rule;
@@ -345,9 +344,8 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("Attribute description "
-              + attributeDescription + " is not recognized: "
-              + e.toString());
+          DEBUG_LOG.warning("Attribute description " + attributeDescription
+              + " is not recognized: " + e.toString());
         }
         return UNDEFINED;
       }
@@ -356,8 +354,7 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("The attribute type "
-              + attributeDescription
+          DEBUG_LOG.warning("The attribute type " + attributeDescription
               + " does not define an approximate matching rule");
         }
         return UNDEFINED;
@@ -381,8 +378,8 @@
 
 
 
-    public MatcherImpl visitEqualityMatchFilter(Schema schema,
-        String attributeDescription, ByteString assertionValue)
+    public MatcherImpl visitEqualityMatchFilter(final Schema schema,
+        final String attributeDescription, final ByteString assertionValue)
     {
       AttributeDescription ad;
       MatchingRule rule;
@@ -396,9 +393,8 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("Attribute description "
-              + attributeDescription + " is not recognized: "
-              + e.toString());
+          DEBUG_LOG.warning("Attribute description " + attributeDescription
+              + " is not recognized: " + e.toString());
         }
         return UNDEFINED;
       }
@@ -407,8 +403,7 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("The attribute type "
-              + attributeDescription
+          DEBUG_LOG.warning("The attribute type " + attributeDescription
               + " does not define an equality matching rule");
         }
         return UNDEFINED;
@@ -432,9 +427,9 @@
 
 
 
-    public MatcherImpl visitExtensibleMatchFilter(Schema schema,
-        String matchingRule, String attributeDescription,
-        ByteString assertionValue, boolean dnAttributes)
+    public MatcherImpl visitExtensibleMatchFilter(final Schema schema,
+        final String matchingRule, final String attributeDescription,
+        final ByteString assertionValue, final boolean dnAttributes)
     {
       AttributeDescription ad = null;
       MatchingRule rule = null;
@@ -462,16 +457,14 @@
       {
         try
         {
-          ad = AttributeDescription.valueOf(attributeDescription,
-              schema);
+          ad = AttributeDescription.valueOf(attributeDescription, schema);
         }
         catch (final LocalizedIllegalArgumentException e)
         {
           if (DEBUG_LOG.isLoggable(Level.WARNING))
           {
-            DEBUG_LOG.warning("Attribute description "
-                + attributeDescription + " is not recognized: "
-                + e.toString());
+            DEBUG_LOG.warning("Attribute description " + attributeDescription
+                + " is not recognized: " + e.toString());
           }
           return UNDEFINED;
         }
@@ -482,8 +475,7 @@
           {
             if (DEBUG_LOG.isLoggable(Level.WARNING))
             {
-              DEBUG_LOG.warning("The attribute type "
-                  + attributeDescription
+              DEBUG_LOG.warning("The attribute type " + attributeDescription
                   + " does not define an equality matching rule");
             }
             return UNDEFINED;
@@ -509,8 +501,7 @@
             if (DEBUG_LOG.isLoggable(Level.WARNING))
             {
               DEBUG_LOG.warning("The matching rule " + matchingRule
-                  + " is not valid for attribute type "
-                  + attributeDescription);
+                  + " is not valid for attribute type " + attributeDescription);
             }
             return UNDEFINED;
           }
@@ -552,8 +543,8 @@
 
 
 
-    public MatcherImpl visitGreaterOrEqualFilter(Schema schema,
-        String attributeDescription, ByteString assertionValue)
+    public MatcherImpl visitGreaterOrEqualFilter(final Schema schema,
+        final String attributeDescription, final ByteString assertionValue)
     {
       AttributeDescription ad;
       MatchingRule rule;
@@ -567,9 +558,8 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("Attribute description "
-              + attributeDescription + " is not recognized: "
-              + e.toString());
+          DEBUG_LOG.warning("Attribute description " + attributeDescription
+              + " is not recognized: " + e.toString());
         }
         return UNDEFINED;
       }
@@ -578,8 +568,7 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("The attribute type "
-              + attributeDescription
+          DEBUG_LOG.warning("The attribute type " + attributeDescription
               + " does not define an ordering matching rule");
         }
         return UNDEFINED;
@@ -603,8 +592,8 @@
 
 
 
-    public MatcherImpl visitLessOrEqualFilter(Schema schema,
-        String attributeDescription, ByteString assertionValue)
+    public MatcherImpl visitLessOrEqualFilter(final Schema schema,
+        final String attributeDescription, final ByteString assertionValue)
     {
       AttributeDescription ad;
       MatchingRule rule;
@@ -618,9 +607,8 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("Attribute description "
-              + attributeDescription + " is not recognized: "
-              + e.toString());
+          DEBUG_LOG.warning("Attribute description " + attributeDescription
+              + " is not recognized: " + e.toString());
         }
         return UNDEFINED;
       }
@@ -629,8 +617,7 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("The attribute type "
-              + attributeDescription
+          DEBUG_LOG.warning("The attribute type " + attributeDescription
               + " does not define an ordering matching rule");
         }
         return UNDEFINED;
@@ -654,7 +641,8 @@
 
 
 
-    public MatcherImpl visitNotFilter(Schema schema, Filter subFilter)
+    public MatcherImpl visitNotFilter(final Schema schema,
+        final Filter subFilter)
     {
       final MatcherImpl subMatcher = subFilter.accept(this, schema);
       return new NotMatcherImpl(subMatcher);
@@ -662,8 +650,8 @@
 
 
 
-    public MatcherImpl visitOrFilter(Schema schema,
-        List<Filter> subFilters)
+    public MatcherImpl visitOrFilter(final Schema schema,
+        final List<Filter> subFilters)
     {
       if (subFilters.isEmpty())
       {
@@ -686,8 +674,8 @@
 
 
 
-    public MatcherImpl visitPresentFilter(Schema schema,
-        String attributeDescription)
+    public MatcherImpl visitPresentFilter(final Schema schema,
+        final String attributeDescription)
     {
       AttributeDescription ad;
       try
@@ -698,9 +686,8 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("Attribute description "
-              + attributeDescription + " is not recognized: "
-              + e.toString());
+          DEBUG_LOG.warning("Attribute description " + attributeDescription
+              + " is not recognized: " + e.toString());
         }
         return UNDEFINED;
       }
@@ -710,9 +697,9 @@
 
 
 
-    public MatcherImpl visitSubstringsFilter(Schema schema,
-        String attributeDescription, ByteString initialSubstring,
-        List<ByteString> anySubstrings, ByteString finalSubstring)
+    public MatcherImpl visitSubstringsFilter(final Schema schema,
+        final String attributeDescription, final ByteString initialSubstring,
+        final List<ByteString> anySubstrings, final ByteString finalSubstring)
     {
       AttributeDescription ad;
       MatchingRule rule;
@@ -726,9 +713,8 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("Attribute description "
-              + attributeDescription + " is not recognized: "
-              + e.toString());
+          DEBUG_LOG.warning("Attribute description " + attributeDescription
+              + " is not recognized: " + e.toString());
         }
         return UNDEFINED;
       }
@@ -737,8 +723,7 @@
       {
         if (DEBUG_LOG.isLoggable(Level.WARNING))
         {
-          DEBUG_LOG.warning("The attribute type "
-              + attributeDescription
+          DEBUG_LOG.warning("The attribute type " + attributeDescription
               + " does not define an substring matching rule");
         }
         return UNDEFINED;
@@ -764,8 +749,8 @@
 
 
 
-    public MatcherImpl visitUnrecognizedFilter(Schema schema,
-        byte filterTag, ByteString filterBytes)
+    public MatcherImpl visitUnrecognizedFilter(final Schema schema,
+        final byte filterTag, final ByteString filterBytes)
     {
       if (DEBUG_LOG.isLoggable(Level.WARNING))
       {
@@ -788,8 +773,8 @@
 
 
 
-  private static ConditionResult matches(Attribute a,
-      MatchingRule rule, Assertion assertion)
+  private static ConditionResult matches(final Attribute a,
+      final MatchingRule rule, final Assertion assertion)
   {
 
     ConditionResult r = ConditionResult.FALSE;
@@ -811,23 +796,21 @@
 
 
 
-  private static ConditionResult matches(ByteString v,
-      MatchingRule rule, Assertion assertion)
+  private static ConditionResult matches(final ByteString v,
+      final MatchingRule rule, final Assertion assertion)
   {
     try
     {
-      final ByteString normalizedValue = rule
-          .normalizeAttributeValue(v);
+      final ByteString normalizedValue = rule.normalizeAttributeValue(v);
       return assertion.matches(normalizedValue);
     }
     catch (final DecodeException de)
     {
       if (DEBUG_LOG.isLoggable(Level.WARNING))
       {
-        DEBUG_LOG.warning("The attribute value " + v.toString()
-            + " is " + "invalid for matching rule "
-            + rule.getNameOrOID() + ". Possible schema error? : "
-            + de.toString());
+        DEBUG_LOG.warning("The attribute value " + v.toString() + " is "
+            + "invalid for matching rule " + rule.getNameOrOID()
+            + ". Possible schema error? : " + de.toString());
       }
       return ConditionResult.UNDEFINED;
     }
@@ -839,7 +822,7 @@
 
 
 
-  Matcher(Filter filter, Schema schema)
+  Matcher(final Filter filter, final Schema schema)
   {
     this.impl = filter.accept(VISITOR, schema);
   }
@@ -847,15 +830,15 @@
 
 
   /**
-   * Indicates whether this filter {@code Matcher} matches the provided
-   * {@code Entry}.
+   * Indicates whether this filter {@code Matcher} matches the provided {@code
+   * Entry}.
    *
    * @param entry
    *          The entry to be matched.
-   * @return {@code true} if this filter {@code Matcher} matches the
-   *         provided {@code Entry}.
+   * @return {@code true} if this filter {@code Matcher} matches the provided
+   *         {@code Entry}.
    */
-  public ConditionResult matches(Entry entry)
+  public ConditionResult matches(final Entry entry)
   {
     return impl.matches(entry);
   }
diff --git a/sdk/src/org/opends/sdk/Change.java b/sdk/src/org/opends/sdk/Modification.java
similarity index 74%
rename from sdk/src/org/opends/sdk/Change.java
rename to sdk/src/org/opends/sdk/Modification.java
index 3fdc37b..e0fe1f0 100644
--- a/sdk/src/org/opends/sdk/Change.java
+++ b/sdk/src/org/opends/sdk/Modification.java
@@ -29,7 +29,6 @@
 
 
 
-
 import com.sun.opends.sdk.util.Validator;
 
 
@@ -39,7 +38,7 @@
  * <p>
  * TODO: other constructors.
  */
-public final class Change
+public final class Modification
 {
   private final ModificationType modificationType;
 
@@ -48,23 +47,24 @@
 
 
   /**
-   * Creates a new modification having the provided modification type
-   * and attribute values to be updated. Note that while the returned
-   * {@code Change} is immutable, the underlying attribute may not be.
-   * The following code ensures that the returned {@code Change} is
-   * fully immutable:
+   * Creates a new modification having the provided modification type and
+   * attribute values to be updated. Note that while the returned {@code
+   * Modification} is immutable, the underlying attribute may not be. The
+   * following code ensures that the returned {@code Modification} is fully
+   * immutable:
    *
    * <pre>
-   * Change change =
-   *     new Change(modificationType, Types.unmodifiableAttribute(attribute));
+   * Modification change = new Modification(modificationType, Types
+   *     .unmodifiableAttribute(attribute));
    * </pre>
    *
    * @param modificationType
-   *          The type of change to be performed.
+   *          The type of modification to be performed.
    * @param attribute
    *          The the attribute containing the values to be modified.
    */
-  public Change(ModificationType modificationType, Attribute attribute)
+  public Modification(final ModificationType modificationType,
+      final Attribute attribute)
   {
     Validator.ensureNotNull(modificationType, attribute);
 
@@ -75,18 +75,6 @@
 
 
   /**
-   * Returns the type of change to be performed.
-   *
-   * @return The type of change to be performed.
-   */
-  public ModificationType getModificationType()
-  {
-    return modificationType;
-  }
-
-
-
-  /**
    * Returns the attribute containing the values to be modified.
    *
    * @return The the attribute containing the values to be modified.
@@ -99,18 +87,31 @@
 
 
   /**
+   * Returns the type of modification to be performed.
+   *
+   * @return The type of modification to be performed.
+   */
+  public ModificationType getModificationType()
+  {
+    return modificationType;
+  }
+
+
+
+  /**
    * {@inheritDoc}
    */
+  @Override
   public String toString()
   {
-    StringBuilder builder = new StringBuilder();
-    builder.append("Change(modificationType=");
+    final StringBuilder builder = new StringBuilder();
+    builder.append("Modification(modificationType=");
     builder.append(modificationType);
     builder.append(", attributeDescription=");
     builder.append(attribute.getAttributeDescriptionAsString());
     builder.append(", attributeValues={");
     boolean firstValue = true;
-    for (ByteString value : attribute)
+    for (final ByteString value : attribute)
     {
       if (!firstValue)
       {
diff --git a/sdk/src/org/opends/sdk/ModificationType.java b/sdk/src/org/opends/sdk/ModificationType.java
index 020fb17..1751094 100644
--- a/sdk/src/org/opends/sdk/ModificationType.java
+++ b/sdk/src/org/opends/sdk/ModificationType.java
@@ -36,16 +36,13 @@
 
 
 /**
- * A Modify operation change type as defined in RFC 4511 section 4.6 is
- * used to specify the type of modification being performed on an
- * attribute.
+ * A Modify operation change type as defined in RFC 4511 section 4.6 is used to
+ * specify the type of modification being performed on an attribute.
  *
- * @see <a href="http://tools.ietf.org/html/rfc4511#section-4.6">RFC
- *      4511 - Lightweight Directory Access Protocol (LDAP): The
- *      Protocol </a>
- * @see <a href="http://tools.ietf.org/html/rfc4525">RFC 4525 -
- *      Lightweight Directory Access Protocol (LDAP) Modify-Increment
- *      Extension </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4511#section-4.6">RFC 4511 -
+ *      Lightweight Directory Access Protocol (LDAP): The Protocol </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4525">RFC 4525 - Lightweight
+ *      Directory Access Protocol (LDAP) Modify-Increment Extension </a>
  */
 public final class ModificationType
 {
@@ -55,67 +52,44 @@
       .unmodifiableList(Arrays.asList(ELEMENTS));
 
   /**
-   * Add the values listed in the modification to the attribute,
-   * creating the attribute if necessary.
+   * Add the values listed in the modification to the attribute, creating the
+   * attribute if necessary.
    */
   public static final ModificationType ADD = register(0, "add");
 
   /**
-   * Delete the values listed in the modification from the attribute. If
-   * no values are listed, or if all current values of the attribute are
-   * listed, the entire attribute is removed.
+   * Delete the values listed in the modification from the attribute. If no
+   * values are listed, or if all current values of the attribute are listed,
+   * the entire attribute is removed.
    */
   public static final ModificationType DELETE = register(1, "delete");
 
   /**
-   * Replace all existing values of the attribute with the new values
-   * listed in the modification, creating the attribute if it did not
-   * already exist. A replace with no listed values will delete the
-   * entire attribute if it exists, and it is ignored if the attribute
-   * does not exist.
+   * Replace all existing values of the attribute with the new values listed in
+   * the modification, creating the attribute if it did not already exist. A
+   * replace with no listed values will delete the entire attribute if it
+   * exists, and it is ignored if the attribute does not exist.
    */
   public static final ModificationType REPLACE = register(2, "replace");
 
   /**
-   * Increment all existing values of the attribute by the amount
-   * specified in the modification value.
+   * Increment all existing values of the attribute by the amount specified in
+   * the modification value.
    */
-  public static final ModificationType INCREMENT = register(3,
-      "increment");
+  public static final ModificationType INCREMENT = register(3, "increment");
 
 
 
   /**
-   * Creates and registers a new modification change type with the
-   * application.
-   *
-   * @param intValue
-   *          The integer value of the modification change type as
-   *          defined in RFC 4511 section 4.6.
-   * @param name
-   *          The name of the modification change type.
-   * @return The new modification change type.
-   */
-  private static ModificationType register(int intValue, String name)
-  {
-    ModificationType t = new ModificationType(intValue, name);
-    ELEMENTS[intValue] = t;
-    return t;
-  }
-
-
-
-  /**
-   * Returns the modification change type having the specified integer
-   * value as defined in RFC 4511 section 4.6.
+   * Returns the modification change type having the specified integer value as
+   * defined in RFC 4511 section 4.6.
    *
    * @param intValue
    *          The integer value of the modification change type.
-   * @return The modification change type, or {@code null} if there was
-   *         no modification change type associated with {@code
-   *         intValue}.
+   * @return The modification change type, or {@code null} if there was no
+   *         modification change type associated with {@code intValue}.
    */
-  public static ModificationType valueOf(int intValue)
+  public static ModificationType valueOf(final int intValue)
   {
     if (intValue < 0 || intValue >= ELEMENTS.length)
     {
@@ -127,12 +101,12 @@
 
 
   /**
-   * Returns an unmodifiable list containing the set of available
-   * modification change types indexed on their integer value as defined
-   * in RFC 4511 section 4.6.
+   * Returns an unmodifiable list containing the set of available modification
+   * change types indexed on their integer value as defined in RFC 4511 section
+   * 4.6.
    *
-   * @return An unmodifiable list containing the set of available
-   *         modification change types.
+   * @return An unmodifiable list containing the set of available modification
+   *         change types.
    */
   public static List<ModificationType> values()
   {
@@ -141,6 +115,25 @@
 
 
 
+  /**
+   * Creates and registers a new modification change type with the application.
+   *
+   * @param intValue
+   *          The integer value of the modification change type as defined in
+   *          RFC 4511 section 4.6.
+   * @param name
+   *          The name of the modification change type.
+   * @return The new modification change type.
+   */
+  private static ModificationType register(final int intValue, final String name)
+  {
+    final ModificationType t = new ModificationType(intValue, name);
+    ELEMENTS[intValue] = t;
+    return t;
+  }
+
+
+
   private final int intValue;
 
   private final String name;
@@ -148,7 +141,7 @@
 
 
   // Prevent direct instantiation.
-  private ModificationType(int intValue, String name)
+  private ModificationType(final int intValue, final String name)
   {
     this.intValue = intValue;
     this.name = name;
@@ -159,7 +152,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean equals(Object obj)
+  @Override
+  public boolean equals(final Object obj)
   {
     if (this == obj)
     {
@@ -180,6 +174,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public int hashCode()
   {
     return intValue;
@@ -188,8 +183,8 @@
 
 
   /**
-   * Returns the integer value of this modification change type as
-   * defined in RFC 4511 section 4.6.
+   * Returns the integer value of this modification change type as defined in
+   * RFC 4511 section 4.6.
    *
    * @return The integer value of this modification change type.
    */
@@ -205,6 +200,7 @@
    *
    * @return The string representation of this modification change type.
    */
+  @Override
   public String toString()
   {
     return name;
diff --git a/sdk/src/org/opends/sdk/MultipleEntriesFoundException.java b/sdk/src/org/opends/sdk/MultipleEntriesFoundException.java
index 17f4f3c..cf7e736 100644
--- a/sdk/src/org/opends/sdk/MultipleEntriesFoundException.java
+++ b/sdk/src/org/opends/sdk/MultipleEntriesFoundException.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
@@ -34,18 +34,17 @@
 
 
 /**
- * Thrown when the result code returned in a Result indicates that the
- * requested single entry search operation or read operation failed
- * because the Directory Server returned multiple matching entries (or
- * search references) when only a single matching entry was expected.
- * More specifically, this exception is used for the
- * {@link ResultCode#CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED} error
- * result codes.
+ * Thrown when the result code returned in a Result indicates that the requested
+ * single entry search operation or read operation failed because the Directory
+ * Server returned multiple matching entries (or search references) when only a
+ * single matching entry was expected. More specifically, this exception is used
+ * for the {@link ResultCode#CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED
+ * CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED} error result codes.
  */
 @SuppressWarnings("serial")
 public class MultipleEntriesFoundException extends ErrorResultException
 {
-  MultipleEntriesFoundException(Result result)
+  MultipleEntriesFoundException(final Result result)
   {
     super(result);
   }
diff --git a/sdk/src/org/opends/sdk/RDN.java b/sdk/src/org/opends/sdk/RDN.java
index c5b840a..458965f 100644
--- a/sdk/src/org/opends/sdk/RDN.java
+++ b/sdk/src/org/opends/sdk/RDN.java
@@ -22,329 +22,72 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_RDN_TYPE_NOT_FOUND;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
 
-import org.opends.sdk.schema.*;
+import org.opends.sdk.schema.AttributeType;
+import org.opends.sdk.schema.Schema;
+import org.opends.sdk.schema.UnknownSchemaElementException;
 
-import com.sun.opends.sdk.util.*;
+import com.sun.opends.sdk.util.Iterators;
+import com.sun.opends.sdk.util.SubstringReader;
 
 
 
 /**
- * A relative distinguished name (RDN) as defined in RFC 4512 section
- * 2.3 is the name of an entry relative to its immediate superior. An
- * RDN is composed of an unordered set of one or more attribute value
- * assertions (AVA) consisting of an attribute description with zero
- * options and an attribute value. These AVAs are chosen to match
- * attribute values (each a distinguished value) of the entry.
+ * A relative distinguished name (RDN) as defined in RFC 4512 section 2.3 is the
+ * name of an entry relative to its immediate superior. An RDN is composed of an
+ * unordered set of one or more attribute value assertions (AVA) consisting of
+ * an attribute description with zero options and an attribute value. These AVAs
+ * are chosen to match attribute values (each a distinguished value) of the
+ * entry.
  * <p>
- * An entry's relative distinguished name must be unique among all
- * immediate subordinates of the entry's immediate superior (i.e. all
- * siblings).
+ * An entry's relative distinguished name must be unique among all immediate
+ * subordinates of the entry's immediate superior (i.e. all siblings).
  * <p>
  * The following are examples of string representations of RDNs:
- * 
+ *
  * <pre>
  * uid=12345
  * ou=Engineering
  * cn=Kurt Zeilenga+L=Redwood Shores
  * </pre>
- * 
- * The last is an example of a multi-valued RDN; that is, an RDN
- * composed of multiple AVAs.
- * 
- * @see <a href="http://tools.ietf.org/html/rfc4512#section-2.3">RFC
- *      4512 - Lightweight Directory Access Protocol (LDAP): Directory
- *      Information Models </a>
+ *
+ * The last is an example of a multi-valued RDN; that is, an RDN composed of
+ * multiple AVAs.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4512#section-2.3">RFC 4512 -
+ *      Lightweight Directory Access Protocol (LDAP): Directory Information
+ *      Models </a>
  */
-public final class RDN implements Iterable<RDN.AVA>, Comparable<RDN>
+public final class RDN implements Iterable<AVA>, Comparable<RDN>
 {
   /**
-   * An attribute value assertion (AVA) as defined in RFC 4512 section
-   * 2.3 consists of an attribute description with zero options and an
-   * attribute value.
-   */
-  public static final class AVA implements Comparable<AVA>
-  {
-    private final AttributeType attributeType;
-
-    private final ByteString attributeValue;
-
-
-
-    /**
-     * Creates a new attribute value assertion (AVA) using the provided
-     * attribute type and value.
-     * 
-     * @param attributeType
-     *          The attribute type.
-     * @param attributeValue
-     *          The attribute value.
-     * @throws NullPointerException
-     *           If {@code attributeType} or {@code attributeValue} was
-     *           {@code null}.
-     */
-    public AVA(AttributeType attributeType, ByteString attributeValue)
-        throws NullPointerException
-    {
-      Validator.ensureNotNull(attributeType, attributeValue);
-
-      this.attributeType = attributeType;
-      this.attributeValue = attributeValue;
-    }
-
-
-
-    /**
-     * Creates a new attribute value assertion (AVA) using the provided
-     * attribute type and value decoded using the default schema.
-     * <p>
-     * If {@code attributeValue} is not an instance of {@code
-     * ByteString} then it will be converted using the
-     * {@link ByteString#valueOf(Object)} method.
-     * 
-     * @param attributeType
-     *          The attribute type.
-     * @param attributeValue
-     *          The attribute value.
-     * @throws UnknownSchemaElementException
-     *           If {@code attributeType} was not found in the default
-     *           schema.
-     * @throws NullPointerException
-     *           If {@code attributeType} or {@code attributeValue} was
-     *           {@code null}.
-     */
-    public AVA(String attributeType, Object attributeValue)
-        throws UnknownSchemaElementException, NullPointerException
-    {
-      Validator.ensureNotNull(attributeType, attributeValue);
-
-      this.attributeType = Schema.getDefaultSchema().getAttributeType(
-          attributeType);
-      this.attributeValue = ByteString.valueOf(attributeValue);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public int compareTo(AVA ava)
-    {
-      int result = attributeType.compareTo(ava.attributeType);
-
-      if (result == 0)
-      {
-        final ByteString nv1 = getNormalizeValue();
-        final ByteString nv2 = ava.getNormalizeValue();
-        result = nv1.compareTo(nv2);
-      }
-
-      return result;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean equals(Object obj)
-    {
-      if (this == obj)
-      {
-        return true;
-      }
-      else if (obj instanceof AVA)
-      {
-        return compareTo((AVA) obj) == 0;
-      }
-      else
-      {
-        return false;
-      }
-    }
-
-
-
-    /**
-     * Returns the attribute type associated with this AVA.
-     * 
-     * @return The attribute type associated with this AVA.
-     */
-    public AttributeType getAttributeType()
-    {
-      return attributeType;
-    }
-
-
-
-    /**
-     * Returns the attribute value associated with this AVA.
-     * 
-     * @return The attribute value associated with this AVA.
-     */
-    public ByteString getAttributeValue()
-    {
-      return attributeValue;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public int hashCode()
-    {
-      return attributeType.hashCode() * 31
-          + getNormalizeValue().hashCode();
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String toString()
-    {
-      final StringBuilder builder = new StringBuilder();
-      return toString(builder).toString();
-    }
-
-
-
-    private ByteString getNormalizeValue()
-    {
-      final MatchingRule matchingRule = attributeType
-          .getEqualityMatchingRule();
-      if (matchingRule != null)
-      {
-        try
-        {
-          return matchingRule.normalizeAttributeValue(attributeValue);
-        }
-        catch (final DecodeException de)
-        {
-          // Ignore - we'll drop back to the user provided value.
-        }
-      }
-      return attributeValue;
-    }
-
-
-
-    private StringBuilder toNormalizedString(StringBuilder builder)
-    {
-      return toString(builder, true);
-    }
-
-
-
-    private StringBuilder toString(StringBuilder builder)
-    {
-      return toString(builder, false);
-    }
-
-
-
-    private StringBuilder toString(StringBuilder builder,
-        boolean normalize)
-    {
-      final ByteString value = normalize ? getNormalizeValue()
-          : attributeValue;
-
-      if (!attributeType.getNames().iterator().hasNext())
-      {
-        builder.append(attributeType.getOID());
-        builder.append("=#");
-        StaticUtils.toHex(value, builder);
-      }
-      else
-      {
-        final String name = attributeType.getNameOrOID();
-        if (normalize)
-        {
-          // Normalizing.
-          StaticUtils.toLowerCase(name, builder);
-        }
-        else
-        {
-          builder.append(name);
-        }
-
-        builder.append("=");
-
-        final Syntax syntax = attributeType.getSyntax();
-        if (!syntax.isHumanReadable())
-        {
-          builder.append("#");
-          StaticUtils.toHex(value, builder);
-        }
-        else
-        {
-          final String str = value.toString();
-          char c;
-          for (int si = 0; si < str.length(); si++)
-          {
-            c = str.charAt(si);
-            if (c == ' ' || c == '#' || c == '"' || c == '+'
-                || c == ',' || c == ';' || c == '<' || c == '='
-                || c == '>' || c == '\\' || c == '\u0000')
-            {
-              builder.append('\\');
-            }
-            builder.append(c);
-          }
-        }
-      }
-      return builder;
-    }
-  }
-
-
-
-  private static final char[] SPECIAL_CHARS = new char[] { '\"', '+',
-      ',', ';', '<', '>', ' ', '#', '=', '\\' };
-
-  private static final char[] DELIMITER_CHARS = new char[] { '+', ',',
-      ';' };
-
-  private static final char[] DQUOTE_CHAR = new char[] { '\"' };
-
-  private static final Comparator<AVA> ATV_COMPARATOR = new Comparator<AVA>()
-  {
-    public int compare(AVA o1, AVA o2)
-    {
-      return o1.getAttributeType().compareTo(o2.getAttributeType());
-    }
-  };
-
-
-
-  /**
-   * Parses the provided LDAP string representation of an RDN using the
-   * default schema.
-   * 
+   * Parses the provided LDAP string representation of an RDN using the default
+   * schema.
+   *
    * @param rdn
    *          The LDAP string representation of a RDN.
    * @return The parsed RDN.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code rdn} is not a valid LDAP string representation
-   *           of a RDN.
+   *           If {@code rdn} is not a valid LDAP string representation of a
+   *           RDN.
    * @throws NullPointerException
    *           If {@code rdn} was {@code null}.
    */
-  public static RDN valueOf(String rdn)
-      throws LocalizedIllegalArgumentException
+  public static RDN valueOf(final String rdn)
+      throws LocalizedIllegalArgumentException, NullPointerException
   {
     return valueOf(rdn, Schema.getDefaultSchema());
   }
@@ -352,22 +95,22 @@
 
 
   /**
-   * Parses the provided LDAP string representation of a RDN using the
-   * provided schema.
-   * 
+   * Parses the provided LDAP string representation of a RDN using the provided
+   * schema.
+   *
    * @param rdn
    *          The LDAP string representation of a RDN.
    * @param schema
    *          The schema to use when parsing the RDN.
    * @return The parsed RDN.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code rdn} is not a valid LDAP string representation
-   *           of a RDN.
+   *           If {@code rdn} is not a valid LDAP string representation of a
+   *           RDN.
    * @throws NullPointerException
    *           If {@code rdn} or {@code schema} was {@code null}.
    */
-  public static RDN valueOf(String rdn, Schema schema)
-      throws LocalizedIllegalArgumentException
+  public static RDN valueOf(final String rdn, final Schema schema)
+      throws LocalizedIllegalArgumentException, NullPointerException
   {
     final SubstringReader reader = new SubstringReader(rdn);
     try
@@ -384,285 +127,13 @@
 
 
 
-  private static AVA readAttributeTypeAndValue(SubstringReader reader,
-      Schema schema) throws LocalizedIllegalArgumentException,
-      UnknownSchemaElementException
-  {
-    // Skip over any spaces at the beginning.
-    reader.skipWhitespaces();
-
-    final AttributeType attribute = readDNAttributeName(reader, schema);
-
-    // Make sure that we're not at the end of the DN string because
-    // that would be invalid.
-    if (reader.remaining() == 0)
-    {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_END_WITH_ATTR_NAME
-          .get(reader.getString(), attribute.getNameOrOID());
-      throw new LocalizedIllegalArgumentException(message);
-    }
-
-    // The next character must be an equal sign. If it is not, then
-    // that's an error.
-    char c;
-    if ((c = reader.read()) != '=')
-    {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_NO_EQUAL.get(reader
-          .getString(), attribute.getNameOrOID(), c);
-      throw new LocalizedIllegalArgumentException(message);
-    }
-
-    // Skip over any spaces after the equal sign.
-    reader.skipWhitespaces();
-
-    // Parse the value for this RDN component.
-    final ByteString value = readDNAttributeValue(reader);
-
-    return new AVA(attribute, value);
-  }
-
-
-
-  private static AttributeType readDNAttributeName(
-      SubstringReader reader, Schema schema)
-      throws LocalizedIllegalArgumentException,
-      UnknownSchemaElementException
-  {
-    int length = 1;
-    reader.mark();
-
-    // The next character must be either numeric (for an OID) or
-    // alphabetic (for
-    // an attribute description).
-    char c = reader.read();
-    if (isDigit(c))
-    {
-      boolean lastWasPeriod = false;
-      do
-      {
-        if (c == '.')
-        {
-          if (lastWasPeriod)
-          {
-            final LocalizableMessage message = ERR_ATTR_SYNTAX_OID_CONSECUTIVE_PERIODS
-                .get(reader.getString(), reader.pos() - 1);
-            throw new LocalizedIllegalArgumentException(message);
-          }
-          else
-          {
-            lastWasPeriod = true;
-          }
-        }
-        else if (!isDigit(c))
-        {
-          // This must have been an illegal character.
-          final LocalizableMessage message = ERR_ATTR_SYNTAX_OID_ILLEGAL_CHARACTER
-              .get(reader.getString(), reader.pos() - 1);
-          throw new LocalizedIllegalArgumentException(message);
-        }
-        else
-        {
-          lastWasPeriod = false;
-        }
-        length++;
-      } while ((c = reader.read()) != '=');
-    }
-    if (isAlpha(c))
-    {
-      // This must be an attribute description. In this case, we will
-      // only
-      // accept alphabetic characters, numeric digits, and the hyphen.
-      while ((c = reader.read()) != '=')
-      {
-        if (length == 0 && !isAlpha(c))
-        {
-          // This is an illegal character.
-          final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR
-              .get(reader.getString(), c, reader.pos() - 1);
-          throw new LocalizedIllegalArgumentException(message);
-        }
-
-        if (!isAlpha(c) && !isDigit(c) && c != '-')
-        {
-          // This is an illegal character.
-          final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR
-              .get(reader.getString(), c, reader.pos() - 1);
-          throw new LocalizedIllegalArgumentException(message);
-        }
-
-        length++;
-      }
-    }
-    else
-    {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ATTR_ILLEGAL_CHAR.get(
-          reader.getString(), c, reader.pos() - 1);
-      throw new LocalizedIllegalArgumentException(message);
-    }
-
-    reader.reset();
-
-    // Return the position of the first non-space character after the
-    // token.
-
-    return schema.getAttributeType(reader.read(length));
-  }
-
-
-
-  private static ByteString readDNAttributeValue(SubstringReader reader)
-      throws LocalizedIllegalArgumentException
-  {
-    // All leading spaces have already been stripped so we can start
-    // reading the value. However, it may be empty so check for that.
-    if (reader.remaining() == 0)
-    {
-      return ByteString.empty();
-    }
-
-    reader.mark();
-
-    // Look at the first character. If it is an octothorpe (#), then
-    // that means that the value should be a hex string.
-    char c = reader.read();
-    int length = 0;
-    if (c == '#')
-    {
-      // The first two characters must be hex characters.
-      reader.mark();
-      if (reader.remaining() < 2)
-      {
-        final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_HEX_VALUE_TOO_SHORT
-            .get(reader.getString());
-        throw new LocalizedIllegalArgumentException(message);
-      }
-
-      for (int i = 0; i < 2; i++)
-      {
-        c = reader.read();
-        if (isHexDigit(c))
-        {
-          length++;
-        }
-        else
-        {
-          final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT
-              .get(reader.getString(), c);
-          throw new LocalizedIllegalArgumentException(message);
-        }
-      }
-
-      // The rest of the value must be a multiple of two hex
-      // characters. The end of the value may be designated by the
-      // end of the DN, a comma or semicolon, or a space.
-      while (reader.remaining() > 0)
-      {
-        c = reader.read();
-        if (isHexDigit(c))
-        {
-          length++;
-
-          if (reader.remaining() > 0)
-          {
-            c = reader.read();
-            if (isHexDigit(c))
-            {
-              length++;
-            }
-            else
-            {
-              final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT
-                  .get(reader.getString(), c);
-              throw new LocalizedIllegalArgumentException(message);
-            }
-          }
-          else
-          {
-            final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_HEX_VALUE_TOO_SHORT
-                .get(reader.getString());
-            throw new LocalizedIllegalArgumentException(message);
-          }
-        }
-        else if ((c == ' ') || (c == ',') || (c == ';'))
-        {
-          // This denotes the end of the value.
-          break;
-        }
-        else
-        {
-          final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_INVALID_HEX_DIGIT
-              .get(reader.getString(), c);
-          throw new LocalizedIllegalArgumentException(message);
-        }
-      }
-
-      // At this point, we should have a valid hex string. Convert it
-      // to a byte array and set that as the value of the provided
-      // octet string.
-      try
-      {
-        reader.reset();
-        return ByteString
-            .wrap(hexStringToByteArray(reader.read(length)));
-      }
-      catch (final Exception e)
-      {
-        final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_ATTR_VALUE_DECODE_FAILURE
-            .get(reader.getString(), String.valueOf(e));
-        throw new LocalizedIllegalArgumentException(message);
-      }
-    }
-
-    // If the first character is a quotation mark, then the value
-    // should continue until the corresponding closing quotation mark.
-    else if (c == '"')
-    {
-      try
-      {
-        return StaticUtils.evaluateEscapes(reader, DQUOTE_CHAR, false);
-      }
-      catch (final DecodeException e)
-      {
-        throw new LocalizedIllegalArgumentException(e
-            .getMessageObject());
-      }
-    }
-
-    // Otherwise, use general parsing to find the end of the value.
-    else
-    {
-      reader.reset();
-      ByteString bytes;
-      try
-      {
-        bytes = StaticUtils.evaluateEscapes(reader, SPECIAL_CHARS,
-            DELIMITER_CHARS, true);
-      }
-      catch (final DecodeException e)
-      {
-        throw new LocalizedIllegalArgumentException(e
-            .getMessageObject());
-      }
-      if (bytes.length() == 0)
-      {
-        // We don't allow an empty attribute value.
-        final LocalizableMessage message = ERR_ATTR_SYNTAX_DN_INVALID_REQUIRES_ESCAPE_CHAR
-            .get(reader.getString(), reader.pos());
-        throw new LocalizedIllegalArgumentException(message);
-      }
-      return bytes;
-    }
-  }
-
-
-
   // FIXME: ensure that the decoded RDN does not contain multiple AVAs
   // with the same type.
-  static RDN decode(String rdnString, SubstringReader reader,
-      Schema schema) throws LocalizedIllegalArgumentException,
+  static RDN decode(final String rdnString, final SubstringReader reader,
+      final Schema schema) throws LocalizedIllegalArgumentException,
       UnknownSchemaElementException
   {
-    final AVA firstAVA = readAttributeTypeAndValue(reader, schema);
+    final AVA firstAVA = AVA.decode(reader, schema);
 
     // Skip over any spaces that might be after the attribute value.
     reader.skipWhitespaces();
@@ -675,21 +146,22 @@
 
       do
       {
-        avas.add(readAttributeTypeAndValue(reader, schema));
+        avas.add(AVA.decode(reader, schema));
 
         // Skip over any spaces that might be after the attribute value.
         reader.skipWhitespaces();
 
         reader.mark();
-      } while (reader.read() == '+');
+      }
+      while (reader.remaining() > 0 && reader.read() == '+');
 
       reader.reset();
-      return new RDN(avas.toArray(new AVA[avas.size()]), rdnString);
+      return new RDN(avas.toArray(new AVA[avas.size()]), null);
     }
     else
     {
       reader.reset();
-      return new RDN(new AVA[] { firstAVA }, rdnString);
+      return new RDN(new AVA[] { firstAVA }, null);
     }
   }
 
@@ -706,16 +178,16 @@
 
   /**
    * Creates a new RDN using the provided attribute type and value.
-   * 
+   *
    * @param attributeType
    *          The attribute type.
    * @param attributeValue
    *          The attribute value.
    * @throws NullPointerException
-   *           If {@code attributeType} or {@code attributeValue} was
-   *           {@code null}.
+   *           If {@code attributeType} or {@code attributeValue} was {@code
+   *           null}.
    */
-  public RDN(AttributeType attributeType, ByteString attributeValue)
+  public RDN(final AttributeType attributeType, final ByteString attributeValue)
       throws NullPointerException
   {
     this.avas = new AVA[] { new AVA(attributeType, attributeValue) };
@@ -724,25 +196,23 @@
 
 
   /**
-   * Creates a new RDN using the provided attribute type and value
-   * decoded using the default schema.
+   * Creates a new RDN using the provided attribute type and value decoded using
+   * the default schema.
    * <p>
-   * If {@code attributeValue} is not an instance of {@code ByteString}
-   * then it will be converted using the
-   * {@link ByteString#valueOf(Object)} method.
-   * 
+   * If {@code attributeValue} is not an instance of {@code ByteString} then it
+   * will be converted using the {@link ByteString#valueOf(Object)} method.
+   *
    * @param attributeType
    *          The attribute type.
    * @param attributeValue
    *          The attribute value.
    * @throws UnknownSchemaElementException
-   *           If {@code attributeType} was not found in the default
-   *           schema.
+   *           If {@code attributeType} was not found in the default schema.
    * @throws NullPointerException
-   *           If {@code attributeType} or {@code attributeValue} was
-   *           {@code null}.
+   *           If {@code attributeType} or {@code attributeValue} was {@code
+   *           null}.
    */
-  public RDN(String attributeType, Object attributeValue)
+  public RDN(final String attributeType, final Object attributeValue)
       throws UnknownSchemaElementException, NullPointerException
   {
     this.avas = new AVA[] { new AVA(attributeType, attributeValue) };
@@ -750,7 +220,7 @@
 
 
 
-  private RDN(AVA[] avas, String stringValue)
+  private RDN(final AVA[] avas, final String stringValue)
   {
     this.avas = avas;
     this.stringValue = stringValue;
@@ -761,14 +231,14 @@
   /**
    * {@inheritDoc}
    */
-  public int compareTo(RDN rdn)
+  public int compareTo(final RDN rdn)
   {
     final int sz1 = avas.length;
     final int sz2 = rdn.avas.length;
 
     if (sz1 != sz2)
     {
-      return sz1 - sz2;
+      return sz1 - sz2 > 0 ? 1 : -1;
     }
 
     if (sz1 == 1)
@@ -779,11 +249,11 @@
     // Need to sort the AVAs before comparing.
     final AVA[] a1 = new AVA[sz1];
     System.arraycopy(avas, 0, a1, 0, sz1);
-    Arrays.sort(a1, ATV_COMPARATOR);
+    Arrays.sort(a1);
 
     final AVA[] a2 = new AVA[sz1];
     System.arraycopy(rdn.avas, 0, a2, 0, sz1);
-    Arrays.sort(a2, ATV_COMPARATOR);
+    Arrays.sort(a2);
 
     for (int i = 0; i < sz1; i++)
     {
@@ -802,7 +272,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean equals(Object obj)
+  @Override
+  public boolean equals(final Object obj)
   {
     if (this == obj)
     {
@@ -821,15 +292,15 @@
 
 
   /**
-   * Returns the attribute value contained in this RDN which is
-   * associated with the provided attribute type, or {@code null} if
-   * this RDN does not include such an attribute value.
-   * 
+   * Returns the attribute value contained in this RDN which is associated with
+   * the provided attribute type, or {@code null} if this RDN does not include
+   * such an attribute value.
+   *
    * @param attributeType
    *          The attribute type.
    * @return The attribute value.
    */
-  public ByteString getAttributeValue(AttributeType attributeType)
+  public ByteString getAttributeValue(final AttributeType attributeType)
   {
     for (final AVA ava : avas)
     {
@@ -845,7 +316,7 @@
 
   /**
    * Returns the first AVA contained in this RDN.
-   * 
+   *
    * @return The first AVA contained in this RDN.
    */
   public AVA getFirstAVA()
@@ -858,13 +329,14 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public int hashCode()
   {
     // Avoid an algorithm that requires the AVAs to be sorted.
     int hash = 0;
-    for (int i = 0; i < avas.length; i++)
+    for (final AVA ava : avas)
     {
-      hash += avas[i].hashCode();
+      hash += ava.hashCode();
     }
     return hash;
   }
@@ -873,9 +345,9 @@
 
   /**
    * Returns {@code true} if this RDN contains more than one AVA.
-   * 
-   * @return {@code true} if this RDN contains more than one AVA,
-   *         otherwise {@code false}.
+   *
+   * @return {@code true} if this RDN contains more than one AVA, otherwise
+   *         {@code false}.
    */
   public boolean isMultiValued()
   {
@@ -885,13 +357,13 @@
 
 
   /**
-   * Returns an iterator of the AVAs contained in this RDN. The AVAs
-   * will be returned in the user provided order.
+   * Returns an iterator of the AVAs contained in this RDN. The AVAs will be
+   * returned in the user provided order.
    * <p>
-   * Attempts to remove AVAs using an iterator's {@code remove()} method
-   * are not permitted and will result in an {@code
-   * UnsupportedOperationException} being thrown.
-   * 
+   * Attempts to remove AVAs using an iterator's {@code remove()} method are not
+   * permitted and will result in an {@code UnsupportedOperationException} being
+   * thrown.
+   *
    * @return An iterator of the AVAs contained in this RDN.
    */
   public Iterator<AVA> iterator()
@@ -903,7 +375,7 @@
 
   /**
    * Returns the number of AVAs in this RDN.
-   * 
+   *
    * @return The number of AVAs in this RDN.
    */
   public int size()
@@ -915,12 +387,13 @@
 
   /**
    * Returns the RFC 4514 string representation of this RDN.
-   * 
+   *
    * @return The RFC 4514 string representation of this RDN.
-   * @see <a href="http://tools.ietf.org/html/rfc4514">RFC 4514 -
-   *      Lightweight Directory Access Protocol (LDAP): String
-   *      Representation of Distinguished Names </a>
+   * @see <a href="http://tools.ietf.org/html/rfc4514">RFC 4514 - Lightweight
+   *      Directory Access Protocol (LDAP): String Representation of
+   *      Distinguished Names </a>
    */
+  @Override
   public String toString()
   {
     // We don't care about potential race conditions here.
@@ -930,7 +403,7 @@
       avas[0].toString(builder);
       for (int i = 1; i < avas.length; i++)
       {
-        builder.append(',');
+        builder.append('+');
         avas[i].toString(builder);
       }
       stringValue = builder.toString();
@@ -940,7 +413,7 @@
 
 
 
-  StringBuilder toNormalizedString(StringBuilder builder)
+  StringBuilder toNormalizedString(final StringBuilder builder)
   {
     final int sz = avas.length;
     if (sz == 1)
@@ -952,12 +425,12 @@
       // Need to sort the AVAs before comparing.
       final AVA[] a = new AVA[sz];
       System.arraycopy(avas, 0, a, 0, sz);
-      Arrays.sort(a, ATV_COMPARATOR);
-
-      a[0].toString(builder);
+      Arrays.sort(a);
+      // Normalize the first AVA.
+      a[0].toNormalizedString(builder);
       for (int i = 1; i < sz; i++)
       {
-        builder.append(',');
+        builder.append('+');
         a[i].toNormalizedString(builder);
       }
 
@@ -967,7 +440,7 @@
 
 
 
-  StringBuilder toString(StringBuilder builder)
+  StringBuilder toString(final StringBuilder builder)
   {
     return builder.append(toString());
   }
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/src/org/opends/sdk/ReferralException.java
similarity index 61%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/src/org/opends/sdk/ReferralException.java
index 62b3ae3..9174eb0 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/src/org/opends/sdk/ReferralException.java
@@ -22,21 +22,28 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package org.opends.sdk;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.opends.sdk.responses.Result;
 
 
 
 /**
- * Password call-back.
+ * Thrown when the result code returned in a Result indicates that the Request
+ * could not be processed by the Directory Server because the target entry is
+ * located on another server. More specifically, this exception is used for the
+ * {@link ResultCode#REFERRAL REFERRAL} result code.
  */
-public interface PasswordCallbackHandler
+@SuppressWarnings("serial")
+public class ReferralException extends EntryNotFoundException
 {
-  public boolean handle(PasswordCallback callback);
+  ReferralException(final Result result)
+  {
+    super(result);
+  }
 }
diff --git a/sdk/src/org/opends/sdk/ResultCode.java b/sdk/src/org/opends/sdk/ResultCode.java
index 33e4d8c..36f2720 100644
--- a/sdk/src/org/opends/sdk/ResultCode.java
+++ b/sdk/src/org/opends/sdk/ResultCode.java
@@ -38,16 +38,15 @@
 
 
 /**
- * An operation result code as defined in RFC 4511 section 4.1.9 is used
- * to indicate the final status of an operation. If a server detects
- * multiple errors for an operation, only one result code is returned.
- * The server should return the result code that best indicates the
- * nature of the error encountered. Servers may return substituted
- * result codes to prevent unauthorized disclosures.
+ * An operation result code as defined in RFC 4511 section 4.1.9 is used to
+ * indicate the final status of an operation. If a server detects multiple
+ * errors for an operation, only one result code is returned. The server should
+ * return the result code that best indicates the nature of the error
+ * encountered. Servers may return substituted result codes to prevent
+ * unauthorized disclosures.
  *
- * @see <a href="http://tools.ietf.org/html/rfc4511#section-4.1.9">RFC
- *      4511 - Lightweight Directory Access Protocol (LDAP): The
- *      Protocol </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4511#section-4.1.9">RFC 4511 -
+ *      Lightweight Directory Access Protocol (LDAP): The Protocol </a>
  */
 public final class ResultCode
 {
@@ -57,8 +56,7 @@
       .unmodifiableList(Arrays.asList(ELEMENTS));
 
   /**
-   * The result code that indicates that the operation completed
-   * successfully.
+   * The result code that indicates that the operation completed successfully.
    */
   public static final ResultCode SUCCESS = registerSuccessResultCode(0,
       INFO_RESULT_SUCCESS.get());
@@ -67,15 +65,15 @@
    * The result code that indicates that an internal error prevented the
    * operation from being processed properly.
    */
-  public static final ResultCode OPERATIONS_ERROR = registerErrorResultCode(
-      1, INFO_RESULT_OPERATIONS_ERROR.get());
+  public static final ResultCode OPERATIONS_ERROR = registerErrorResultCode(1,
+      INFO_RESULT_OPERATIONS_ERROR.get());
 
   /**
-   * The result code that indicates that the client sent a malformed or
-   * illegal request to the server.
+   * The result code that indicates that the client sent a malformed or illegal
+   * request to the server.
    */
-  public static final ResultCode PROTOCOL_ERROR = registerErrorResultCode(
-      2, INFO_RESULT_PROTOCOL_ERROR.get());
+  public static final ResultCode PROTOCOL_ERROR = registerErrorResultCode(2,
+      INFO_RESULT_PROTOCOL_ERROR.get());
 
   /**
    * The result code that indicates that a time limit was exceeded while
@@ -92,30 +90,30 @@
       4, INFO_RESULT_SIZE_LIMIT_EXCEEDED.get());
 
   /**
-   * The result code that indicates that the attribute value assertion
-   * included in a compare request did not match the targeted entry.
+   * The result code that indicates that the attribute value assertion included
+   * in a compare request did not match the targeted entry.
    */
-  public static final ResultCode COMPARE_FALSE = registerSuccessResultCode(
-      5, INFO_RESULT_COMPARE_FALSE.get());
+  public static final ResultCode COMPARE_FALSE = registerSuccessResultCode(5,
+      INFO_RESULT_COMPARE_FALSE.get());
 
   /**
-   * The result code that indicates that the attribute value assertion
-   * included in a compare request did match the targeted entry.
+   * The result code that indicates that the attribute value assertion included
+   * in a compare request did match the targeted entry.
    */
-  public static final ResultCode COMPARE_TRUE = registerSuccessResultCode(
-      6, INFO_RESULT_COMPARE_TRUE.get());
+  public static final ResultCode COMPARE_TRUE = registerSuccessResultCode(6,
+      INFO_RESULT_COMPARE_TRUE.get());
 
   /**
-   * The result code that indicates that the requested authentication
-   * attempt failed because it referenced an invalid SASL mechanism.
+   * The result code that indicates that the requested authentication attempt
+   * failed because it referenced an invalid SASL mechanism.
    */
   public static final ResultCode AUTH_METHOD_NOT_SUPPORTED = registerErrorResultCode(
       7, INFO_RESULT_AUTH_METHOD_NOT_SUPPORTED.get());
 
   /**
-   * The result code that indicates that the requested operation could
-   * not be processed because it requires that the client has completed
-   * a strong form of authentication.
+   * The result code that indicates that the requested operation could not be
+   * processed because it requires that the client has completed a strong form
+   * of authentication.
    */
   public static final ResultCode STRONG_AUTH_REQUIRED = registerErrorResultCode(
       8, INFO_RESULT_STRONG_AUTH_REQUIRED.get());
@@ -123,35 +121,34 @@
   /**
    * The result code that indicates that a referral was encountered.
    * <p>
-   * Strictly speaking this result code should not be exceptional since
-   * it is considered as a "success" response. However, referrals should
-   * occur rarely in practice and, when they do occur, should not be
-   * ignored since the application may believe that a request has
-   * succeeded when, in fact, nothing was done.
+   * Strictly speaking this result code should not be exceptional since it is
+   * considered as a "success" response. However, referrals should occur rarely
+   * in practice and, when they do occur, should not be ignored since the
+   * application may believe that a request has succeeded when, in fact, nothing
+   * was done.
    */
   public static final ResultCode REFERRAL = registerErrorResultCode(10,
       INFO_RESULT_REFERRAL.get());
 
   /**
-   * The result code that indicates that processing on the requested
-   * operation could not continue because an administrative limit was
-   * exceeded.
+   * The result code that indicates that processing on the requested operation
+   * could not continue because an administrative limit was exceeded.
    */
   public static final ResultCode ADMIN_LIMIT_EXCEEDED = registerErrorResultCode(
       11, INFO_RESULT_ADMIN_LIMIT_EXCEEDED.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it included a critical extension that is unsupported or
-   * inappropriate for that request.
+   * The result code that indicates that the requested operation failed because
+   * it included a critical extension that is unsupported or inappropriate for
+   * that request.
    */
   public static final ResultCode UNAVAILABLE_CRITICAL_EXTENSION = registerErrorResultCode(
       12, INFO_RESULT_UNAVAILABLE_CRITICAL_EXTENSION.get());
 
   /**
-   * The result code that indicates that the requested operation could
-   * not be processed because it requires confidentiality for the
-   * communication between the client and the server.
+   * The result code that indicates that the requested operation could not be
+   * processed because it requires confidentiality for the communication between
+   * the client and the server.
    */
   public static final ResultCode CONFIDENTIALITY_REQUIRED = registerErrorResultCode(
       13, INFO_RESULT_CONFIDENTIALITY_REQUIRED.get());
@@ -164,70 +161,67 @@
       14, INFO_RESULT_SASL_BIND_IN_PROGRESS.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it targeted an attribute or attribute value that did not
-   * exist in the specified entry.
+   * The result code that indicates that the requested operation failed because
+   * it targeted an attribute or attribute value that did not exist in the
+   * specified entry.
    */
   public static final ResultCode NO_SUCH_ATTRIBUTE = registerErrorResultCode(
       16, INFO_RESULT_NO_SUCH_ATTRIBUTE.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it referenced an attribute that is not defined in the
-   * server schema.
+   * The result code that indicates that the requested operation failed because
+   * it referenced an attribute that is not defined in the server schema.
    */
   public static final ResultCode UNDEFINED_ATTRIBUTE_TYPE = registerErrorResultCode(
       17, INFO_RESULT_UNDEFINED_ATTRIBUTE_TYPE.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it attempted to perform an inappropriate type of matching
-   * against an attribute.
+   * The result code that indicates that the requested operation failed because
+   * it attempted to perform an inappropriate type of matching against an
+   * attribute.
    */
   public static final ResultCode INAPPROPRIATE_MATCHING = registerErrorResultCode(
       18, INFO_RESULT_INAPPROPRIATE_MATCHING.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it would have violated some constraint defined in the
-   * server.
+   * The result code that indicates that the requested operation failed because
+   * it would have violated some constraint defined in the server.
    */
   public static final ResultCode CONSTRAINT_VIOLATION = registerErrorResultCode(
       19, INFO_RESULT_CONSTRAINT_VIOLATION.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it would have resulted in a conflict with an existing
-   * attribute or attribute value in the target entry.
+   * The result code that indicates that the requested operation failed because
+   * it would have resulted in a conflict with an existing attribute or
+   * attribute value in the target entry.
    */
   public static final ResultCode ATTRIBUTE_OR_VALUE_EXISTS = registerErrorResultCode(
       20, INFO_RESULT_ATTRIBUTE_OR_VALUE_EXISTS.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it violated the syntax for a specified attribute.
+   * The result code that indicates that the requested operation failed because
+   * it violated the syntax for a specified attribute.
    */
   public static final ResultCode INVALID_ATTRIBUTE_SYNTAX = registerErrorResultCode(
       21, INFO_RESULT_INVALID_ATTRIBUTE_SYNTAX.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it referenced an entry that does not exist.
+   * The result code that indicates that the requested operation failed because
+   * it referenced an entry that does not exist.
    */
-  public static final ResultCode NO_SUCH_OBJECT = registerErrorResultCode(
-      32, INFO_RESULT_NO_SUCH_OBJECT.get());
+  public static final ResultCode NO_SUCH_OBJECT = registerErrorResultCode(32,
+      INFO_RESULT_NO_SUCH_OBJECT.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it attempted to perform an illegal operation on an alias.
+   * The result code that indicates that the requested operation failed because
+   * it attempted to perform an illegal operation on an alias.
    */
-  public static final ResultCode ALIAS_PROBLEM = registerErrorResultCode(
-      33, INFO_RESULT_ALIAS_PROBLEM.get());
+  public static final ResultCode ALIAS_PROBLEM = registerErrorResultCode(33,
+      INFO_RESULT_ALIAS_PROBLEM.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it would have resulted in an entry with an invalid or
-   * malformed DN.
+   * The result code that indicates that the requested operation failed because
+   * it would have resulted in an entry with an invalid or malformed DN.
    */
   public static final ResultCode INVALID_DN_SYNTAX = registerErrorResultCode(
       34, INFO_RESULT_INVALID_DN_SYNTAX.get());
@@ -240,45 +234,44 @@
       36, INFO_RESULT_ALIAS_DEREFERENCING_PROBLEM.get());
 
   /**
-   * The result code that indicates that an authentication attempt
-   * failed because the requested type of authentication was not
-   * appropriate for the targeted entry.
+   * The result code that indicates that an authentication attempt failed
+   * because the requested type of authentication was not appropriate for the
+   * targeted entry.
    */
   public static final ResultCode INAPPROPRIATE_AUTHENTICATION = registerErrorResultCode(
       48, INFO_RESULT_INAPPROPRIATE_AUTHENTICATION.get());
 
   /**
-   * The result code that indicates that an authentication attempt
-   * failed because the user did not provide a valid set of credentials.
+   * The result code that indicates that an authentication attempt failed
+   * because the user did not provide a valid set of credentials.
    */
   public static final ResultCode INVALID_CREDENTIALS = registerErrorResultCode(
       49, INFO_RESULT_INVALID_CREDENTIALS.get());
 
   /**
-   * The result code that indicates that the client does not have
-   * sufficient permission to perform the requested operation.
+   * The result code that indicates that the client does not have sufficient
+   * permission to perform the requested operation.
    */
   public static final ResultCode INSUFFICIENT_ACCESS_RIGHTS = registerErrorResultCode(
       50, INFO_RESULT_INSUFFICIENT_ACCESS_RIGHTS.get());
 
   /**
-   * The result code that indicates that the server is too busy to
-   * process the requested operation.
+   * The result code that indicates that the server is too busy to process the
+   * requested operation.
    */
   public static final ResultCode BUSY = registerErrorResultCode(51,
       INFO_RESULT_BUSY.get());
 
   /**
-   * The result code that indicates that either the entire server or one
-   * or more required resources were not available for use in processing
-   * the request.
+   * The result code that indicates that either the entire server or one or more
+   * required resources were not available for use in processing the request.
    */
-  public static final ResultCode UNAVAILABLE = registerErrorResultCode(
-      52, INFO_RESULT_UNAVAILABLE.get());
+  public static final ResultCode UNAVAILABLE = registerErrorResultCode(52,
+      INFO_RESULT_UNAVAILABLE.get());
 
   /**
-   * The result code that indicates that the server is unwilling to
-   * perform the requested operation.
+   * The result code that indicates that the server is unwilling to perform the
+   * requested operation.
    */
   public static final ResultCode UNWILLING_TO_PERFORM = registerErrorResultCode(
       53, INFO_RESULT_UNWILLING_TO_PERFORM.get());
@@ -287,346 +280,295 @@
    * The result code that indicates that a referral or chaining loop was
    * detected while processing the request.
    */
-  public static final ResultCode LOOP_DETECT = registerErrorResultCode(
-      54, INFO_RESULT_LOOP_DETECT.get());
+  public static final ResultCode LOOP_DETECT = registerErrorResultCode(54,
+      INFO_RESULT_LOOP_DETECT.get());
 
   /**
-   * The result code that indicates that a search request included a VLV
-   * request control without a server-side sort control.
+   * The result code that indicates that a search request included a VLV request
+   * control without a server-side sort control.
    */
   public static final ResultCode SORT_CONTROL_MISSING = registerErrorResultCode(
       60, INFO_RESULT_SORT_CONTROL_MISSING.get());
 
   /**
-   * The result code that indicates that a search request included a VLV
-   * request control with an invalid offset.
+   * The result code that indicates that a search request included a VLV request
+   * control with an invalid offset.
    */
   public static final ResultCode OFFSET_RANGE_ERROR = registerErrorResultCode(
       61, INFO_RESULT_OFFSET_RANGE_ERROR.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it would have violated the server's naming configuration.
+   * The result code that indicates that the requested operation failed because
+   * it would have violated the server's naming configuration.
    */
-  public static final ResultCode NAMING_VIOLATION = registerErrorResultCode(
-      64, INFO_RESULT_NAMING_VIOLATION.get());
+  public static final ResultCode NAMING_VIOLATION = registerErrorResultCode(64,
+      INFO_RESULT_NAMING_VIOLATION.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it would have resulted in an entry that violated the server
-   * schema.
+   * The result code that indicates that the requested operation failed because
+   * it would have resulted in an entry that violated the server schema.
    */
   public static final ResultCode OBJECTCLASS_VIOLATION = registerErrorResultCode(
       65, INFO_RESULT_OBJECTCLASS_VIOLATION.get());
 
   /**
-   * The result code that indicates that the requested operation is not
-   * allowed for non-leaf entries.
+   * The result code that indicates that the requested operation is not allowed
+   * for non-leaf entries.
    */
   public static final ResultCode NOT_ALLOWED_ON_NONLEAF = registerErrorResultCode(
       66, INFO_RESULT_NOT_ALLOWED_ON_NONLEAF.get());
 
   /**
-   * The result code that indicates that the requested operation is not
-   * allowed on an RDN attribute.
+   * The result code that indicates that the requested operation is not allowed
+   * on an RDN attribute.
    */
   public static final ResultCode NOT_ALLOWED_ON_RDN = registerErrorResultCode(
       67, INFO_RESULT_NOT_ALLOWED_ON_RDN.get());
 
   /**
-   * The result code that indicates that the requested operation failed
-   * because it would have resulted in an entry that conflicts with an
-   * entry that already exists.
+   * The result code that indicates that the requested operation failed because
+   * it would have resulted in an entry that conflicts with an entry that
+   * already exists.
    */
   public static final ResultCode ENTRY_ALREADY_EXISTS = registerErrorResultCode(
       68, INFO_RESULT_ENTRY_ALREADY_EXISTS.get());
 
   /**
-   * The result code that indicates that the operation could not be
-   * processed because it would have modified the objectclasses
-   * associated with an entry in an illegal manner.
+   * The result code that indicates that the operation could not be processed
+   * because it would have modified the objectclasses associated with an entry
+   * in an illegal manner.
    */
   public static final ResultCode OBJECTCLASS_MODS_PROHIBITED = registerErrorResultCode(
       69, INFO_RESULT_OBJECTCLASS_MODS_PROHIBITED.get());
 
   /**
-   * The result code that indicates that the operation could not be
-   * processed because it would impact multiple DSAs or other
-   * repositories.
+   * The result code that indicates that the operation could not be processed
+   * because it would impact multiple DSAs or other repositories.
    */
   public static final ResultCode AFFECTS_MULTIPLE_DSAS = registerErrorResultCode(
       71, INFO_RESULT_AFFECTS_MULTIPLE_DSAS.get());
 
   /**
-   * The result code that indicates that the operation could not be
-   * processed because there was an error while processing the virtual
-   * list view control.
+   * The result code that indicates that the operation could not be processed
+   * because there was an error while processing the virtual list view control.
    */
   public static final ResultCode VIRTUAL_LIST_VIEW_ERROR = registerErrorResultCode(
       76, INFO_RESULT_VIRTUAL_LIST_VIEW_ERROR.get());
 
   /**
-   * The result code that should be used if no other result code is
-   * appropriate.
+   * The result code that should be used if no other result code is appropriate.
    */
   public static final ResultCode OTHER = registerErrorResultCode(80,
       INFO_RESULT_OTHER.get());
 
   /**
-   * The client-side result code that indicates that a
-   * previously-established connection to the server was lost. This is
-   * for client-side use only and should never be transferred over
-   * protocol.
+   * The client-side result code that indicates that a previously-established
+   * connection to the server was lost. This is for client-side use only and
+   * should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_SERVER_DOWN = registerErrorResultCode(
       81, INFO_RESULT_CLIENT_SIDE_SERVER_DOWN.get());
 
   /**
-   * The client-side result code that indicates that a local error
-   * occurred that had nothing to do with interaction with the server.
-   * This is for client-side use only and should never be transferred
-   * over protocol.
+   * The client-side result code that indicates that a local error occurred that
+   * had nothing to do with interaction with the server. This is for client-side
+   * use only and should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_LOCAL_ERROR = registerErrorResultCode(
       82, INFO_RESULT_CLIENT_SIDE_LOCAL_ERROR.get());
 
   /**
-   * The client-side result code that indicates that an error occurred
-   * while encoding a request to send to the server. This is for
-   * client-side use only and should never be transferred over protocol.
+   * The client-side result code that indicates that an error occurred while
+   * encoding a request to send to the server. This is for client-side use only
+   * and should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_ENCODING_ERROR = registerErrorResultCode(
       83, INFO_RESULT_CLIENT_SIDE_ENCODING_ERROR.get());
 
   /**
-   * The client-side result code that indicates that an error occurred
-   * while decoding a response from the server. This is for client-side
-   * use only and should never be transferred over protocol.
+   * The client-side result code that indicates that an error occurred while
+   * decoding a response from the server. This is for client-side use only and
+   * should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_DECODING_ERROR = registerErrorResultCode(
       84, INFO_RESULT_CLIENT_SIDE_DECODING_ERROR.get());
 
   /**
-   * The client-side result code that indicates that the client did not
-   * receive an expected response in a timely manner. This is for
-   * client-side use only and should never be transferred over protocol.
+   * The client-side result code that indicates that the client did not receive
+   * an expected response in a timely manner. This is for client-side use only
+   * and should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_TIMEOUT = registerErrorResultCode(
       85, INFO_RESULT_CLIENT_SIDE_TIMEOUT.get());
 
   /**
-   * The client-side result code that indicates that the user requested
-   * an unknown or unsupported authentication mechanism. This is for
-   * client-side use only and should never be transferred over protocol.
+   * The client-side result code that indicates that the user requested an
+   * unknown or unsupported authentication mechanism. This is for client-side
+   * use only and should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_AUTH_UNKNOWN = registerErrorResultCode(
       86, INFO_RESULT_CLIENT_SIDE_AUTH_UNKNOWN.get());
 
   /**
-   * The client-side result code that indicates that the filter provided
-   * by the user was malformed and could not be parsed. This is for
-   * client-side use only and should never be transferred over protocol.
+   * The client-side result code that indicates that the filter provided by the
+   * user was malformed and could not be parsed. This is for client-side use
+   * only and should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_FILTER_ERROR = registerErrorResultCode(
       87, INFO_RESULT_CLIENT_SIDE_FILTER_ERROR.get());
 
   /**
-   * The client-side result code that indicates that the user cancelled
-   * an operation. This is for client-side use only and should never be
-   * transferred over protocol.
+   * The client-side result code that indicates that the user cancelled an
+   * operation. This is for client-side use only and should never be transferred
+   * over protocol.
    */
   public static final ResultCode CLIENT_SIDE_USER_CANCELLED = registerErrorResultCode(
       88, INFO_RESULT_CLIENT_SIDE_USER_CANCELLED.get());
 
   /**
-   * The client-side result code that indicates that there was a problem
-   * with one or more of the parameters provided by the user. This is
-   * for client-side use only and should never be transferred over
-   * protocol.
+   * The client-side result code that indicates that there was a problem with
+   * one or more of the parameters provided by the user. This is for client-side
+   * use only and should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_PARAM_ERROR = registerErrorResultCode(
       89, INFO_RESULT_CLIENT_SIDE_PARAM_ERROR.get());
 
   /**
-   * The client-side result code that indicates that the client
-   * application was not able to allocate enough memory for the
-   * requested operation. This is for client-side use only and should
-   * never be transferred over protocol.
+   * The client-side result code that indicates that the client application was
+   * not able to allocate enough memory for the requested operation. This is for
+   * client-side use only and should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_NO_MEMORY = registerErrorResultCode(
       90, INFO_RESULT_CLIENT_SIDE_NO_MEMORY.get());
 
   /**
-   * The client-side result code that indicates that the client was not
-   * able to establish a connection to the server. This is for
-   * client-side use only and should never be transferred over protocol.
+   * The client-side result code that indicates that the client was not able to
+   * establish a connection to the server. This is for client-side use only and
+   * should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_CONNECT_ERROR = registerErrorResultCode(
       91, INFO_RESULT_CLIENT_SIDE_CONNECT_ERROR.get());
 
   /**
-   * The client-side result code that indicates that the user requested
-   * an operation that is not supported. This is for client-side use
-   * only and should never be transferred over protocol.
+   * The client-side result code that indicates that the user requested an
+   * operation that is not supported. This is for client-side use only and
+   * should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_NOT_SUPPORTED = registerErrorResultCode(
       92, INFO_RESULT_CLIENT_SIDE_NOT_SUPPORTED.get());
 
   /**
-   * The client-side result code that indicates that the client expected
-   * a control to be present in the response from the server but it was
-   * not included. This is for client-side use only and should never be
-   * transferred over protocol.
+   * The client-side result code that indicates that the client expected a
+   * control to be present in the response from the server but it was not
+   * included. This is for client-side use only and should never be transferred
+   * over protocol.
    */
   public static final ResultCode CLIENT_SIDE_CONTROL_NOT_FOUND = registerErrorResultCode(
       93, INFO_RESULT_CLIENT_SIDE_CONTROL_NOT_FOUND.get());
 
   /**
-   * The client-side result code that indicates that the requested
-   * single entry search operation or read operation failed because the
-   * Directory Server did not return any matching entries. This is for
-   * client-side use only and should never be transferred over protocol.
+   * The client-side result code that indicates that the requested single entry
+   * search operation or read operation failed because the Directory Server did
+   * not return any matching entries. This is for client-side use only and
+   * should never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_NO_RESULTS_RETURNED = registerErrorResultCode(
       94, INFO_RESULT_CLIENT_SIDE_NO_RESULTS_RETURNED.get());
 
   /**
    * The client-side result code that the requested single entry search
-   * operation or read operation failed because the Directory Server
-   * returned multiple matching entries (or search references) when only
-   * a single matching entry was expected. This is for client-side use
-   * only and should never be transferred over protocol.
+   * operation or read operation failed because the Directory Server returned
+   * multiple matching entries (or search references) when only a single
+   * matching entry was expected. This is for client-side use only and should
+   * never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED = registerErrorResultCode(
       95, INFO_RESULT_CLIENT_SIDE_UNEXPECTED_RESULTS_RETURNED.get());
 
   /**
-   * The client-side result code that indicates that the client detected
-   * a referral loop caused by servers referencing each other in a
-   * circular manner. This is for client-side use only and should never
-   * be transferred over protocol.
+   * The client-side result code that indicates that the client detected a
+   * referral loop caused by servers referencing each other in a circular
+   * manner. This is for client-side use only and should never be transferred
+   * over protocol.
    */
   public static final ResultCode CLIENT_SIDE_CLIENT_LOOP = registerErrorResultCode(
       96, INFO_RESULT_CLIENT_SIDE_CLIENT_LOOP.get());
 
   /**
-   * The client-side result code that indicates that the client reached
-   * the maximum number of hops allowed when attempting to follow a
-   * referral (i.e., following one referral resulted in another referral
-   * which resulted in another referral and so on). This is for
-   * client-side use only and should never be transferred over protocol.
+   * The client-side result code that indicates that the client reached the
+   * maximum number of hops allowed when attempting to follow a referral (i.e.,
+   * following one referral resulted in another referral which resulted in
+   * another referral and so on). This is for client-side use only and should
+   * never be transferred over protocol.
    */
   public static final ResultCode CLIENT_SIDE_REFERRAL_LIMIT_EXCEEDED = registerErrorResultCode(
       97, INFO_RESULT_CLIENT_SIDE_REFERRAL_LIMIT_EXCEEDED.get());
 
   /**
-   * The result code that indicates that a cancel request was
-   * successful, or that the specified operation was canceled.
+   * The result code that indicates that a cancel request was successful, or
+   * that the specified operation was canceled.
    */
-  public static final ResultCode CANCELLED = registerErrorResultCode(
-      118, INFO_RESULT_CANCELED.get());
+  public static final ResultCode CANCELLED = registerErrorResultCode(118,
+      INFO_RESULT_CANCELED.get());
 
   /**
-   * The result code that indicates that a cancel request was
-   * unsuccessful because the targeted operation did not exist or had
-   * already completed.
+   * The result code that indicates that a cancel request was unsuccessful
+   * because the targeted operation did not exist or had already completed.
    */
   public static final ResultCode NO_SUCH_OPERATION = registerErrorResultCode(
       119, INFO_RESULT_NO_SUCH_OPERATION.get());
 
   /**
-   * The result code that indicates that a cancel request was
-   * unsuccessful because processing on the targeted operation had
-   * already reached a point at which it could not be canceled.
+   * The result code that indicates that a cancel request was unsuccessful
+   * because processing on the targeted operation had already reached a point at
+   * which it could not be canceled.
    */
-  public static final ResultCode TOO_LATE = registerErrorResultCode(
-      120, INFO_RESULT_TOO_LATE.get());
+  public static final ResultCode TOO_LATE = registerErrorResultCode(120,
+      INFO_RESULT_TOO_LATE.get());
 
   /**
-   * The result code that indicates that a cancel request was
-   * unsuccessful because the targeted operation was one that could not
-   * be canceled.
+   * The result code that indicates that a cancel request was unsuccessful
+   * because the targeted operation was one that could not be canceled.
    */
-  public static final ResultCode CANNOT_CANCEL = registerErrorResultCode(
-      121, INFO_RESULT_CANNOT_CANCEL.get());
+  public static final ResultCode CANNOT_CANCEL = registerErrorResultCode(121,
+      INFO_RESULT_CANNOT_CANCEL.get());
 
   /**
-   * The result code that indicates that the filter contained in an
-   * assertion control failed to match the target entry.
+   * The result code that indicates that the filter contained in an assertion
+   * control failed to match the target entry.
    */
   public static final ResultCode ASSERTION_FAILED = registerErrorResultCode(
       122, INFO_RESULT_ASSERTION_FAILED.get());
 
   /**
-   * The result code that should be used if the server will not allow
-   * the client to use the requested authorization.
+   * The result code that should be used if the server will not allow the client
+   * to use the requested authorization.
    */
   public static final ResultCode AUTHORIZATION_DENIED = registerErrorResultCode(
       123, INFO_RESULT_AUTHORIZATION_DENIED.get());
 
   /**
-   * The result code that should be used if the server did not actually
-   * complete processing on the associated operation because the request
-   * included the LDAP No-Op control.
+   * The result code that should be used if the server did not actually complete
+   * processing on the associated operation because the request included the
+   * LDAP No-Op control.
    */
-  public static final ResultCode NO_OPERATION = registerErrorResultCode(
-      16654, INFO_RESULT_NO_OPERATION.get());
+  public static final ResultCode NO_OPERATION = registerErrorResultCode(16654,
+      INFO_RESULT_NO_OPERATION.get());
 
 
 
   /**
-   * Creates and registers a new error result code with the application.
-   *
-   * @param intValue
-   *          The integer value of the error result code as defined in
-   *          RFC 4511 section 4.1.9.
-   * @param name
-   *          The name of the error result code.
-   * @return The new error result code.
-   */
-  private static ResultCode registerErrorResultCode(int intValue,
-      LocalizableMessage name)
-  {
-    ResultCode t = new ResultCode(intValue, name, true);
-    ELEMENTS[intValue] = t;
-    return t;
-  }
-
-
-
-  /**
-   * Creates and registers a new success result code with the
-   * application.
-   *
-   * @param intValue
-   *          The integer value of the success result code as defined in
-   *          RFC 4511 section 4.1.9.
-   * @param name
-   *          The name of the success result code.
-   * @return The new success result code.
-   */
-  private static ResultCode registerSuccessResultCode(int intValue,
-      LocalizableMessage name)
-  {
-    ResultCode t = new ResultCode(intValue, name, false);
-    ELEMENTS[intValue] = t;
-    return t;
-  }
-
-
-
-  /**
-   * Returns the result code having the specified integer value as
-   * defined in RFC 4511 section 4.1.9. If there is no result code
-   * associated with the specified integer value then a temporary result
-   * code is automatically created in order to handle cases where
-   * unexpected result codes are returned from the server.
+   * Returns the result code having the specified integer value as defined in
+   * RFC 4511 section 4.1.9. If there is no result code associated with the
+   * specified integer value then a temporary result code is automatically
+   * created in order to handle cases where unexpected result codes are returned
+   * from the server.
    *
    * @param intValue
    *          The integer value of the result code.
    * @return The result code.
    */
-  public static ResultCode valueOf(int intValue)
+  public static ResultCode valueOf(final int intValue)
   {
     ResultCode resultCode = null;
 
@@ -637,8 +579,8 @@
 
     if (resultCode == null)
     {
-      resultCode = new ResultCode(intValue, LocalizableMessage
-          .raw("undefined(" + intValue + ")"), true);
+      resultCode = new ResultCode(intValue, LocalizableMessage.raw("undefined("
+          + intValue + ")"), true);
     }
 
     return resultCode;
@@ -647,12 +589,10 @@
 
 
   /**
-   * Returns an unmodifiable list containing the set of available result
-   * codes indexed on their integer value as defined in RFC 4511 section
-   * 4.1.9.
+   * Returns an unmodifiable list containing the set of available result codes
+   * indexed on their integer value as defined in RFC 4511 section 4.1.9.
    *
-   * @return An unmodifiable list containing the set of available result
-   *         codes.
+   * @return An unmodifiable list containing the set of available result codes.
    */
   public static List<ResultCode> values()
   {
@@ -661,6 +601,46 @@
 
 
 
+  /**
+   * Creates and registers a new error result code with the application.
+   *
+   * @param intValue
+   *          The integer value of the error result code as defined in RFC 4511
+   *          section 4.1.9.
+   * @param name
+   *          The name of the error result code.
+   * @return The new error result code.
+   */
+  private static ResultCode registerErrorResultCode(final int intValue,
+      final LocalizableMessage name)
+  {
+    final ResultCode t = new ResultCode(intValue, name, true);
+    ELEMENTS[intValue] = t;
+    return t;
+  }
+
+
+
+  /**
+   * Creates and registers a new success result code with the application.
+   *
+   * @param intValue
+   *          The integer value of the success result code as defined in RFC
+   *          4511 section 4.1.9.
+   * @param name
+   *          The name of the success result code.
+   * @return The new success result code.
+   */
+  private static ResultCode registerSuccessResultCode(final int intValue,
+      final LocalizableMessage name)
+  {
+    final ResultCode t = new ResultCode(intValue, name, false);
+    ELEMENTS[intValue] = t;
+    return t;
+  }
+
+
+
   private final int intValue;
 
   private final LocalizableMessage name;
@@ -670,8 +650,8 @@
 
 
   // Prevent direct instantiation.
-  private ResultCode(int intValue, LocalizableMessage name,
-      boolean exceptional)
+  private ResultCode(final int intValue, final LocalizableMessage name,
+      final boolean exceptional)
   {
     this.intValue = intValue;
     this.name = name;
@@ -681,17 +661,23 @@
 
 
   /**
-   * Indicates whether or not this result code represents an error
-   * result. In order to make it easier for application to detect
-   * referrals, the {@code REFERRAL} result code is treated as an error
-   * result (the LDAP RFCs treat referrals as a success response).
-   *
-   * @return {@code true} if this result code represents an error
-   *         result, otherwise {@code false}.
+   * {@inheritDoc}
    */
-  public boolean isExceptional()
+  @Override
+  public boolean equals(final Object obj)
   {
-    return exceptional;
+    if (this == obj)
+    {
+      return true;
+    }
+    else if (obj instanceof ResultCode)
+    {
+      return this.intValue == ((ResultCode) obj).intValue;
+    }
+    else
+    {
+      return false;
+    }
   }
 
 
@@ -711,27 +697,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean equals(Object obj)
-  {
-    if (this == obj)
-    {
-      return true;
-    }
-    else if (obj instanceof ResultCode)
-    {
-      return this.intValue == ((ResultCode) obj).intValue;
-    }
-    else
-    {
-      return false;
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
+  @Override
   public int hashCode()
   {
     return intValue;
@@ -752,10 +718,27 @@
 
 
   /**
+   * Indicates whether or not this result code represents an error result. In
+   * order to make it easier for application to detect referrals, the {@code
+   * REFERRAL} result code is treated as an error result (the LDAP RFCs treat
+   * referrals as a success response).
+   *
+   * @return {@code true} if this result code represents an error result,
+   *         otherwise {@code false}.
+   */
+  public boolean isExceptional()
+  {
+    return exceptional;
+  }
+
+
+
+  /**
    * Returns the string representation of this result code.
    *
    * @return The string representation of this result code.
    */
+  @Override
   public String toString()
   {
     return name.toString();
diff --git a/sdk/src/org/opends/sdk/ResultHandler.java b/sdk/src/org/opends/sdk/ResultHandler.java
index 0b885c4..62f3b89 100644
--- a/sdk/src/org/opends/sdk/ResultHandler.java
+++ b/sdk/src/org/opends/sdk/ResultHandler.java
@@ -27,19 +27,23 @@
 
 package org.opends.sdk;
 
+
+
 /**
- * A completion handler for consuming the result of an asynchronous
- * operation.
+ * A completion handler for consuming the result of an asynchronous operation or
+ * connection attempts.
  * <p>
- * {@link Connection} objects allow a result completion handler to be
- * specified when sending operation requests to a Directory Server. The
- * {@link #handleResult} method is invoked when the operation completes
- * successfully. The {@link #handleErrorResult} method is invoked if the
- * operation fails.
+ * A result completion handler may be specified when performing asynchronous
+ * operations using an {@link AsynchronousConnection} object or when connecting
+ * asynchronously to a remote Directory Server using an
+ * {@link ConnectionFactory}. The {@link #handleResult} method is invoked when
+ * the operation or connection attempt completes successfully. The
+ * {@link #handleErrorResult} method is invoked if the operation or connection
+ * attempt fails.
  * <p>
- * Implementations of these methods should complete in a timely manner
- * so as to avoid keeping the invoking thread from dispatching to other
- * completion handlers.
+ * Implementations of these methods should complete in a timely manner so as to
+ * avoid keeping the invoking thread from dispatching to other completion
+ * handlers.
  *
  * @param <S>
  *          The type of result handled by this result handler.
diff --git a/sdk/src/org/opends/sdk/RootDSE.java b/sdk/src/org/opends/sdk/RootDSE.java
index 613a8b9..9410450 100644
--- a/sdk/src/org/opends/sdk/RootDSE.java
+++ b/sdk/src/org/opends/sdk/RootDSE.java
@@ -42,12 +42,11 @@
 
 
 /**
- * The root DSE is a DSA-specific Entry (DSE) and not part of any naming
- * context (or any subtree), and which is uniquely identified by the
- * empty DN.
+ * The root DSE is a DSA-specific Entry (DSE) and not part of any naming context
+ * (or any subtree), and which is uniquely identified by the empty DN.
  * <p>
- * A Directory Server uses the root DSE to provide information about
- * itself using the following set of attributes:
+ * A Directory Server uses the root DSE to provide information about itself
+ * using the following set of attributes:
  * <ul>
  * <li>{@code altServer}: alternative Directory Servers
  * <li>{@code namingContexts}: naming contexts
@@ -57,74 +56,76 @@
  * <li>{@code supportedLDAPVersion}: LDAP versions supported
  * <li>{@code supportedSASLMechanisms}: recognized SASL authentication
  * mechanisms
- * <li>{@code supportedAuthPasswordSchemes}: recognized authentication
- * password schemes
- * <li>{@code subschemaSubentry}: the name of the subschema subentry
- * holding the schema controlling the Root DSE
+ * <li>{@code supportedAuthPasswordSchemes}: recognized authentication password
+ * schemes
+ * <li>{@code subschemaSubentry}: the name of the subschema subentry holding the
+ * schema controlling the Root DSE
  * <li>{@code vendorName}: the name of the Directory Server implementer
  * <li>{@code vendorVersion}: the version of the Directory Server
  * implementation.
  * </ul>
- * The values provided for these attributes may depend on session-
- * specific and other factors. For example, a server supporting the SASL
- * EXTERNAL mechanism might only list "EXTERNAL" when the client's
- * identity has been established by a lower level.
+ * The values provided for these attributes may depend on session- specific and
+ * other factors. For example, a server supporting the SASL EXTERNAL mechanism
+ * might only list "EXTERNAL" when the client's identity has been established by
+ * a lower level.
  * <p>
- * The root DSE may also include a {@code subschemaSubentry} attribute.
- * If it does, the attribute refers to the subschema (sub)entry holding
- * the schema controlling the root DSE. Clients SHOULD NOT assume that
- * this subschema (sub)entry controls other entries held by the server.
+ * The root DSE may also include a {@code subschemaSubentry} attribute. If it
+ * does, the attribute refers to the subschema (sub)entry holding the schema
+ * controlling the root DSE. Clients SHOULD NOT assume that this subschema
+ * (sub)entry controls other entries held by the server.
  *
- * @see <a href="http://tools.ietf.org/html/rfc4512">RFC 4512 -
- *      Lightweight Directory Access Protocol (LDAP): Directory
- *      Information Models </a>
- * @see <a href="http://tools.ietf.org/html/rfc3045">RFC 3045 - Storing
- *      Vendor Information in the LDAP Root DSE </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4512">RFC 4512 - Lightweight
+ *      Directory Access Protocol (LDAP): Directory Information Models </a>
+ * @see <a href="http://tools.ietf.org/html/rfc3045">RFC 3045 - Storing Vendor
+ *      Information in the LDAP Root DSE </a>
  * @see <a href="http://tools.ietf.org/html/rfc3112">RFC 3112 - LDAP
  *      Authentication Password Schema </a>
  */
 public final class RootDSE
 {
-  private static final AttributeDescription ATTR_ALT_SERVER = AttributeDescription
-      .create(CoreSchema.getAltServerAttributeType());
+  private static final AttributeDescription ATTR_ALT_SERVER =
+    AttributeDescription.create(CoreSchema.getAltServerAttributeType());
 
-  private static final AttributeDescription ATTR_NAMING_CONTEXTS = AttributeDescription
-      .create(CoreSchema.getNamingContextsAttributeType());
+  private static final AttributeDescription ATTR_NAMING_CONTEXTS =
+    AttributeDescription.create(CoreSchema.getNamingContextsAttributeType());
 
-  private static final AttributeDescription ATTR_SUPPORTED_CONTROL = AttributeDescription
-      .create(CoreSchema.getSupportedControlAttributeType());
+  private static final AttributeDescription ATTR_SUBSCHEMA_SUBENTRY =
+    AttributeDescription.create(CoreSchema.getSubschemaSubentryAttributeType());
 
-  private static final AttributeDescription ATTR_SUPPORTED_EXTENSION = AttributeDescription
-      .create(CoreSchema.getSupportedExtensionAttributeType());
+  private static final AttributeDescription ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES =
+    AttributeDescription.create(
+        CoreSchema.getSupportedAuthPasswordSchemesAttributeType());
 
-  private static final AttributeDescription ATTR_SUPPORTED_FEATURE = AttributeDescription
-      .create(CoreSchema.getSupportedFeaturesAttributeType());
+  private static final AttributeDescription ATTR_SUPPORTED_CONTROL =
+    AttributeDescription.create(CoreSchema.getSupportedControlAttributeType());
 
-  private static final AttributeDescription ATTR_SUPPORTED_LDAP_VERSION = AttributeDescription
-      .create(CoreSchema.getSupportedLDAPVersionAttributeType());
+  private static final AttributeDescription ATTR_SUPPORTED_EXTENSION =
+    AttributeDescription.create(
+        CoreSchema.getSupportedExtensionAttributeType());
 
-  private static final AttributeDescription ATTR_SUPPORTED_SASL_MECHANISMS = AttributeDescription
-      .create(CoreSchema.getSupportedSASLMechanismsAttributeType());
+  private static final AttributeDescription ATTR_SUPPORTED_FEATURE =
+    AttributeDescription.create(CoreSchema.getSupportedFeaturesAttributeType());
 
-  private static final AttributeDescription ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES = AttributeDescription
-      .create(CoreSchema.getSupportedAuthPasswordSchemesAttributeType());
+  private static final AttributeDescription ATTR_SUPPORTED_LDAP_VERSION =
+    AttributeDescription.create(
+        CoreSchema.getSupportedLDAPVersionAttributeType());
 
-  private static final AttributeDescription ATTR_SUBSCHEMA_SUBENTRY = AttributeDescription
-      .create(CoreSchema.getSubschemaSubentryAttributeType());
+  private static final AttributeDescription ATTR_SUPPORTED_SASL_MECHANISMS =
+    AttributeDescription.create(
+        CoreSchema.getSupportedSASLMechanismsAttributeType());
 
-  private static final AttributeDescription ATTR_VENDOR_NAME = AttributeDescription
-      .create(CoreSchema.getVendorNameAttributeType());
+  private static final AttributeDescription ATTR_VENDOR_NAME =
+    AttributeDescription.create(CoreSchema.getVendorNameAttributeType());
 
-  private static final AttributeDescription ATTR_VENDOR_VERSION = AttributeDescription
-      .create(CoreSchema.getVendorNameAttributeType());
+  private static final AttributeDescription ATTR_VENDOR_VERSION =
+    AttributeDescription.create(CoreSchema.getVendorNameAttributeType());
 
   private static final SearchRequest SEARCH_REQUEST = Requests
       .newSearchRequest(DN.rootDN(), SearchScope.BASE_OBJECT, Filter
           .getObjectClassPresentFilter(), ATTR_ALT_SERVER.toString(),
-          ATTR_NAMING_CONTEXTS.toString(), ATTR_SUPPORTED_CONTROL
-              .toString(), ATTR_SUPPORTED_EXTENSION.toString(),
-          ATTR_SUPPORTED_FEATURE.toString(),
-          ATTR_SUPPORTED_LDAP_VERSION.toString(),
+          ATTR_NAMING_CONTEXTS.toString(), ATTR_SUPPORTED_CONTROL.toString(),
+          ATTR_SUPPORTED_EXTENSION.toString(), ATTR_SUPPORTED_FEATURE
+              .toString(), ATTR_SUPPORTED_LDAP_VERSION.toString(),
           ATTR_SUPPORTED_SASL_MECHANISMS.toString(), ATTR_VENDOR_NAME
               .toString(), ATTR_VENDOR_VERSION.toString(),
           ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES.toString(),
@@ -133,32 +134,29 @@
 
 
   /**
-   * Reads the Root DSE from the Directory Server using the provided
-   * connection.
+   * Reads the Root DSE from the Directory Server using the provided connection.
    * <p>
-   * If the Root DSE is not returned by the Directory Server then the
-   * request will fail with an {@link EntryNotFoundException}. More
-   * specifically, the returned future will never return {@code null}.
+   * If the Root DSE is not returned by the Directory Server then the request
+   * will fail with an {@link EntryNotFoundException}. More specifically, the
+   * returned future will never return {@code null}.
    *
    * @param connection
-   *          A connection to the Directory Server whose Root DSE is to
-   *          be read.
+   *          A connection to the Directory Server whose Root DSE is to be read.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If the connection does not support search operations.
    * @throws IllegalStateException
-   *           If the connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If the connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If the {@code connection} was {@code null}.
    */
   public static FutureResult<RootDSE> readRootDSE(
-      AsynchronousConnection connection,
-      ResultHandler<RootDSE> handler)
+      final AsynchronousConnection connection,
+      final ResultHandler<RootDSE> handler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException
   {
@@ -166,7 +164,8 @@
       new FutureResultTransformer<SearchResultEntry, RootDSE>(handler)
     {
 
-      protected RootDSE transformResult(SearchResultEntry result)
+      @Override
+      protected RootDSE transformResult(final SearchResultEntry result)
           throws ErrorResultException
       {
         return new RootDSE(result);
@@ -174,7 +173,7 @@
 
     };
 
-    FutureResult<SearchResultEntry> innerFuture = connection
+    final FutureResult<SearchResultEntry> innerFuture = connection
         .searchSingleEntry(SEARCH_REQUEST, future);
     future.setFutureResult(innerFuture);
     return future;
@@ -183,31 +182,29 @@
 
 
   /**
-   * Reads the Root DSE from the Directory Server using the provided
-   * connection.
+   * Reads the Root DSE from the Directory Server using the provided connection.
    * <p>
-   * If the Root DSE is not returned by the Directory Server then the
-   * request will fail with an {@link EntryNotFoundException}. More
-   * specifically, this method will never return {@code null}.
+   * If the Root DSE is not returned by the Directory Server then the request
+   * will fail with an {@link EntryNotFoundException}. More specifically, this
+   * method will never return {@code null}.
    *
    * @param connection
-   *          A connection to the Directory Server whose Root DSE is to
-   *          be read.
+   *          A connection to the Directory Server whose Root DSE is to be read.
    * @return The Directory Server's Root DSE.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If the connection does not support search operations.
    * @throws IllegalStateException
-   *           If the connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If the connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
    *           If the {@code connection} was {@code null}.
    */
-  public static RootDSE readRootDSE(Connection connection)
+  public static RootDSE readRootDSE(final Connection connection)
       throws ErrorResultException, InterruptedException,
       UnsupportedOperationException, IllegalStateException,
       NullPointerException
@@ -223,18 +220,18 @@
 
 
   /**
-   * Creates a new Root DSE instance backed by the provided entry.
-   * Modifications made to {@code entry} will be reflected in the
-   * returned Root DSE. The returned Root DSE instance is unmodifiable
-   * and attempts to use modify any of the returned collections will
-   * result in a {@code UnsupportedOperationException}.
+   * Creates a new Root DSE instance backed by the provided entry. Modifications
+   * made to {@code entry} will be reflected in the returned Root DSE. The
+   * returned Root DSE instance is unmodifiable and attempts to use modify any
+   * of the returned collections will result in a {@code
+   * UnsupportedOperationException}.
    *
    * @param entry
    *          The Root DSE entry.
    * @throws NullPointerException
    *           If {@code entry} was {@code null} .
    */
-  public RootDSE(Entry entry) throws NullPointerException
+  public RootDSE(final Entry entry) throws NullPointerException
   {
     Validator.ensureNotNull(entry);
     this.entry = entry;
@@ -243,97 +240,107 @@
 
 
   /**
-   * Returns an unmodifiable list of URIs referring to alternative
-   * Directory Servers that may be contacted when the Directory Server
-   * becomes unavailable.
+   * Returns an unmodifiable list of URIs referring to alternative Directory
+   * Servers that may be contacted when the Directory Server becomes
+   * unavailable.
    * <p>
-   * URIs for Directory Servers implementing the LDAP protocol are
-   * written according to RFC 4516. Other kinds of URIs may be provided.
+   * URIs for Directory Servers implementing the LDAP protocol are written
+   * according to RFC 4516. Other kinds of URIs may be provided.
    * <p>
-   * If the Directory Server does not know of any other Directory
-   * Servers that could be used, the returned list will be empty.
+   * If the Directory Server does not know of any other Directory Servers that
+   * could be used, the returned list will be empty.
    *
-   * @return An unmodifiable list of URIs referring to alternative
-   *         Directory Servers, which may be empty.
-   * @see <a href="http://tools.ietf.org/html/rfc4516">RFC 4516 -
-   *      Lightweight Directory Access Protocol (LDAP): Uniform Resource
-   *      Locator </a>
+   * @return An unmodifiable list of URIs referring to alternative Directory
+   *         Servers, which may be empty.
+   * @see <a href="http://tools.ietf.org/html/rfc4516">RFC 4516 - Lightweight
+   *      Directory Access Protocol (LDAP): Uniform Resource Locator </a>
    */
   public Collection<String> getAlternativeServers()
   {
-    return getMultiValuedAttribute(ATTR_ALT_SERVER, Functions
-        .valueToString());
+    return getMultiValuedAttribute(ATTR_ALT_SERVER, Functions.valueToString());
   }
 
 
 
   /**
-   * Returns an unmodifiable list of DNs identifying the context
-   * prefixes of the naming contexts that the Directory Server masters
-   * or shadows (in part or in whole).
-   * <p>
-   * If the Directory Server does not master or shadow any naming
-   * contexts, the returned list will be empty.
+   * Returns the entry which backs this Root DSE instance. Modifications made to
+   * the returned entry will be reflected in this Root DSE.
    *
-   * @return An unmodifiable list of DNs identifying the context
-   *         prefixes of the naming contexts, which may be empty.
+   * @return The underlying Root DSE entry.
    */
-  public Collection<String> getNamingContexts()
+  public Entry getEntry()
   {
-    return getMultiValuedAttribute(
-        ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES, Functions.valueToString());
+    return entry;
   }
 
 
 
   /**
-   * Returns a string which represents the DN of the subschema subentry
-   * holding the schema controlling the Root DSE.
+   * Returns an unmodifiable list of DNs identifying the context prefixes of the
+   * naming contexts that the Directory Server masters or shadows (in part or in
+   * whole).
    * <p>
-   * Clients SHOULD NOT assume that this subschema (sub)entry controls
-   * other entries held by the Directory Server.
+   * If the Directory Server does not master or shadow any naming contexts, the
+   * returned list will be empty.
    *
-   * @return The DN of the subschema subentry holding the schema
-   *         controlling the Root DSE, or {@code null} if the DN is not
-   *         provided.
+   * @return An unmodifiable list of DNs identifying the context prefixes of the
+   *         naming contexts, which may be empty.
    */
-  public String getSubschemaSubentry()
+  public Collection<DN> getNamingContexts()
   {
-    return getSingleValuedAttribute(ATTR_SUBSCHEMA_SUBENTRY);
+    return getMultiValuedAttribute(ATTR_NAMING_CONTEXTS, Functions.valueToDN());
   }
 
 
 
   /**
-   * Returns an unmodifiable list of supported authentication password
-   * schemes which the Directory Server supports.
+   * Returns a string which represents the DN of the subschema subentry holding
+   * the schema controlling the Root DSE.
    * <p>
-   * If the Directory Server does not support any authentication
-   * password schemes, the returned list will be empty.
+   * Clients SHOULD NOT assume that this subschema (sub)entry controls other
+   * entries held by the Directory Server.
    *
-   * @return An unmodifiable list of supported authentication password
-   *         schemes, which may be empty.
+   * @return The DN of the subschema subentry holding the schema controlling the
+   *         Root DSE, or {@code null} if the DN is not provided.
+   */
+  public DN getSubschemaSubentry()
+  {
+    return getSingleValuedAttribute(ATTR_SUBSCHEMA_SUBENTRY, Functions
+        .valueToDN());
+  }
+
+
+
+  /**
+   * Returns an unmodifiable list of supported authentication password schemes
+   * which the Directory Server supports.
+   * <p>
+   * If the Directory Server does not support any authentication password
+   * schemes, the returned list will be empty.
+   *
+   * @return An unmodifiable list of supported authentication password schemes,
+   *         which may be empty.
    * @see <a href="http://tools.ietf.org/html/rfc3112">RFC 3112 - LDAP
    *      Authentication Password Schema </a>
    */
   public Collection<String> getSupportedAuthenticationPasswordSchemes()
   {
-    return getMultiValuedAttribute(
-        ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES, Functions.valueToString());
+    return getMultiValuedAttribute(ATTR_SUPPORTED_AUTH_PASSWORD_SCHEMES,
+        Functions.valueToString());
   }
 
 
 
   /**
-   * Returns an unmodifiable list of object identifiers identifying the
-   * request controls that the Directory Server supports.
+   * Returns an unmodifiable list of object identifiers identifying the request
+   * controls that the Directory Server supports.
    * <p>
-   * If the Directory Server does not support any request controls, the
-   * returned list will be empty. Object identifiers identifying
-   * response controls may not be listed.
+   * If the Directory Server does not support any request controls, the returned
+   * list will be empty. Object identifiers identifying response controls may
+   * not be listed.
    *
-   * @return An unmodifiable list of object identifiers identifying the
-   *         request controls, which may be empty.
+   * @return An unmodifiable list of object identifiers identifying the request
+   *         controls, which may be empty.
    */
   public Collection<String> getSupportedControls()
   {
@@ -344,21 +351,21 @@
 
 
   /**
-   * Returns an unmodifiable list of object identifiers identifying the
-   * extended operations that the Directory Server supports.
+   * Returns an unmodifiable list of object identifiers identifying the extended
+   * operations that the Directory Server supports.
    * <p>
-   * If the Directory Server does not support any extended operations,
-   * the returned list will be empty.
+   * If the Directory Server does not support any extended operations, the
+   * returned list will be empty.
    * <p>
-   * An extended operation generally consists of an extended request and
-   * an extended response but may also include other protocol data units
-   * (such as intermediate responses). The object identifier assigned to
-   * the extended request is used to identify the extended operation.
-   * Other object identifiers used in the extended operation may not be
-   * listed as values of this attribute.
+   * An extended operation generally consists of an extended request and an
+   * extended response but may also include other protocol data units (such as
+   * intermediate responses). The object identifier assigned to the extended
+   * request is used to identify the extended operation. Other object
+   * identifiers used in the extended operation may not be listed as values of
+   * this attribute.
    *
-   * @return An unmodifiable list of object identifiers identifying the
-   *         extended operations, which may be empty.
+   * @return An unmodifiable list of object identifiers identifying the extended
+   *         operations, which may be empty.
    */
   public Collection<String> getSupportedExtendedOperations()
   {
@@ -369,14 +376,14 @@
 
 
   /**
-   * Returns an unmodifiable list of object identifiers identifying
-   * elective features that the Directory Server supports.
+   * Returns an unmodifiable list of object identifiers identifying elective
+   * features that the Directory Server supports.
    * <p>
-   * If the server does not support any discoverable elective features,
-   * the returned list will be empty.
+   * If the server does not support any discoverable elective features, the
+   * returned list will be empty.
    *
-   * @return An unmodifiable list of object identifiers identifying the
-   *         elective features, which may be empty.
+   * @return An unmodifiable list of object identifiers identifying the elective
+   *         features, which may be empty.
    */
   public Collection<String> getSupportedFeatures()
   {
@@ -387,39 +394,38 @@
 
 
   /**
-   * Returns an unmodifiable list of the versions of LDAP that the
-   * Directory Server supports.
+   * Returns an unmodifiable list of the versions of LDAP that the Directory
+   * Server supports.
    *
    * @return An unmodifiable list of the versions.
    */
   public Collection<Integer> getSupportedLDAPVersions()
   {
-    return getMultiValuedAttribute(ATTR_SUPPORTED_LDAP_VERSION,
-        Functions.valueToInteger());
+    return getMultiValuedAttribute(ATTR_SUPPORTED_LDAP_VERSION, Functions
+        .valueToInteger());
   }
 
 
 
   /**
-   * Returns an unmodifiable list of the SASL mechanisms that the
-   * Directory Server recognizes and/or supports.
+   * Returns an unmodifiable list of the SASL mechanisms that the Directory
+   * Server recognizes and/or supports.
    * <p>
-   * The contents of the returned list may depend on the current session
-   * state and may be empty if the Directory Server does not support any
-   * SASL mechanisms.
+   * The contents of the returned list may depend on the current session state
+   * and may be empty if the Directory Server does not support any SASL
+   * mechanisms.
    *
-   * @return An unmodifiable list of the SASL mechanisms, which may be
-   *         empty.
-   * @see <a href="http://tools.ietf.org/html/rfc4513">RFC 4513 -
-   *      Lightweight Directory Access Protocol (LDAP): Authentication
-   *      Methods and Security Mechanisms </a>
+   * @return An unmodifiable list of the SASL mechanisms, which may be empty.
+   * @see <a href="http://tools.ietf.org/html/rfc4513">RFC 4513 - Lightweight
+   *      Directory Access Protocol (LDAP): Authentication Methods and Security
+   *      Mechanisms </a>
    * @see <a href="http://tools.ietf.org/html/rfc4422">RFC 4422 - Simple
    *      Authentication and Security Layer (SASL) </a>
    */
   public Collection<String> getSupportedSASLMechanisms()
   {
-    return getMultiValuedAttribute(ATTR_SUPPORTED_SASL_MECHANISMS,
-        Functions.valueToString());
+    return getMultiValuedAttribute(ATTR_SUPPORTED_SASL_MECHANISMS, Functions
+        .valueToString());
   }
 
 
@@ -428,43 +434,44 @@
    * Returns a string which represents the name of the Directory Server
    * implementer.
    *
-   * @return The name of the Directory Server implementer, or {@code
-   *         null} if the vendor name is not provided.
-   * @see <a href="http://tools.ietf.org/html/rfc3045">RFC 3045 -
-   *      Storing Vendor Information in the LDAP Root DSE </a>
+   * @return The name of the Directory Server implementer, or {@code null} if
+   *         the vendor name is not provided.
+   * @see <a href="http://tools.ietf.org/html/rfc3045">RFC 3045 - Storing Vendor
+   *      Information in the LDAP Root DSE </a>
    */
   public String getVendorName()
   {
-    return getSingleValuedAttribute(ATTR_VENDOR_NAME);
+    return getSingleValuedAttribute(ATTR_VENDOR_NAME, Functions.valueToString());
   }
 
 
 
   /**
-   * Returns a string which represents the version of the Directory
-   * Server implementation.
+   * Returns a string which represents the version of the Directory Server
+   * implementation.
    * <p>
-   * Note that this value is typically a release value comprised of a
-   * string and/or a string of numbers used by the developer of the LDAP
-   * server product. The returned string will be unique between two
-   * versions of the Directory Server, but there are no other syntactic
-   * restrictions on the value or the way it is formatted.
+   * Note that this value is typically a release value comprised of a string
+   * and/or a string of numbers used by the developer of the LDAP server
+   * product. The returned string will be unique between two versions of the
+   * Directory Server, but there are no other syntactic restrictions on the
+   * value or the way it is formatted.
    *
-   * @return The version of the Directory Server implementation, or
-   *         {@code null} if the vendor version is not provided.
-   * @see <a href="http://tools.ietf.org/html/rfc3045">RFC 3045 -
-   *      Storing Vendor Information in the LDAP Root DSE </a>
+   * @return The version of the Directory Server implementation, or {@code null}
+   *         if the vendor version is not provided.
+   * @see <a href="http://tools.ietf.org/html/rfc3045">RFC 3045 - Storing Vendor
+   *      Information in the LDAP Root DSE </a>
    */
   public String getVendorVersion()
   {
-    return getSingleValuedAttribute(ATTR_VENDOR_VERSION);
+    return getSingleValuedAttribute(ATTR_VENDOR_VERSION, Functions
+        .valueToString());
   }
 
 
 
   private <N> Collection<N> getMultiValuedAttribute(
-      AttributeDescription attributeDescription,
-      Function<ByteString, N, Void> function)
+      final AttributeDescription attributeDescription,
+      final Function<ByteString, N, Void> function)
   {
     // The returned collection is unmodifiable because we may need to
     // return an empty collection if the attribute does not exist in the
@@ -474,8 +481,8 @@
     final Attribute attr = entry.getAttribute(attributeDescription);
     if (attr != null)
     {
-      return Collections.unmodifiableCollection(Collections2.transform(
-          attr, function, Functions.objectToByteString()));
+      return Collections.unmodifiableCollection(Collections2.transform(attr,
+          function, Functions.objectToByteString()));
     }
     else
     {
@@ -485,8 +492,9 @@
 
 
 
-  private String getSingleValuedAttribute(
-      AttributeDescription attributeDescription)
+  private <N> N getSingleValuedAttribute(
+      final AttributeDescription attributeDescription,
+      final Function<ByteString, N, Void> function)
   {
     final Attribute attr = entry.getAttribute(attributeDescription);
     if (attr == null || attr.isEmpty())
@@ -495,7 +503,7 @@
     }
     else
     {
-      return attr.firstValueAsString();
+      return function.apply(attr.firstValue(), null);
     }
   }
 
diff --git a/sdk/src/org/opends/sdk/SSLContextBuilder.java b/sdk/src/org/opends/sdk/SSLContextBuilder.java
new file mode 100644
index 0000000..5db8f24
--- /dev/null
+++ b/sdk/src/org/opends/sdk/SSLContextBuilder.java
@@ -0,0 +1,255 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.security.GeneralSecurityException;
+import java.security.Provider;
+import java.security.SecureRandom;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+
+
+
+/**
+ * An SSL context builder provides an interface for incrementally constructing
+ * {@link SSLContext} instances for use when securing connections with SSL or
+ * the StartTLS extended operation. The {@link #getSSLContext()} should be
+ * called in order to obtain the {@code SSLContext}.
+ */
+public final class SSLContextBuilder
+{
+
+  /**
+   * SSL protocol: supports some version of SSL; may support other versions.
+   */
+  public static final String PROTOCOL_SSL = "SSL";
+
+  /**
+   * SSL protocol: supports SSL version 2 or higher; may support other versions.
+   */
+  public static final String PROTOCOL_SSL2 = "SSLv2";
+
+  /**
+   * SSL protocol: supports SSL version 3; may support other versions.
+   */
+  public static final String PROTOCOL_SSL3 = "SSLv3";
+
+  /**
+   * SSL protocol: supports some version of TLS; may support other versions.
+   */
+  public static final String PROTOCOL_TLS = "TLS";
+
+  /**
+   * SSL protocol: supports RFC 2246: TLS version 1.0 ; may support other
+   * versions.
+   */
+  public static final String PROTOCOL_TLS1 = "TLSv1";
+
+  /**
+   * SSL protocol: supports RFC 4346: TLS version 1.1 ; may support other
+   * versions.
+   */
+  public static final String PROTOCOL_TLS1_1 = "TLSv1.1";
+
+  private TrustManager trustManager = null;
+  private KeyManager keyManager = null;
+  private String protocol = PROTOCOL_TLS1;
+  private SecureRandom random = null;
+
+  // These are mutually exclusive.
+  private Provider provider = null;
+  private String providerName = null;
+
+
+
+  /**
+   * Creates a new SSL context builder using default parameters.
+   */
+  public SSLContextBuilder()
+  {
+    // Do nothing.
+  }
+
+
+
+  /**
+   * Creates a {@code SSLContext} using the parameters of this SSL context
+   * builder.
+   *
+   * @return A {@code SSLContext} using the parameters of this SSL context
+   *         builder.
+   * @throws GeneralSecurityException
+   *           If the SSL context could not be created, perhaps due to missing
+   *           algorithms.
+   */
+  public SSLContext getSSLContext() throws GeneralSecurityException
+  {
+    TrustManager[] tm = null;
+    if (trustManager != null)
+    {
+      tm = new TrustManager[] { trustManager };
+    }
+
+    KeyManager[] km = null;
+    if (keyManager != null)
+    {
+      km = new KeyManager[] { keyManager };
+    }
+
+    SSLContext sslContext;
+    if (provider != null)
+    {
+      sslContext = SSLContext.getInstance(protocol, provider);
+    }
+    else if (providerName != null)
+    {
+      sslContext = SSLContext.getInstance(protocol, providerName);
+    }
+    else
+    {
+      sslContext = SSLContext.getInstance(protocol);
+    }
+    sslContext.init(km, tm, random);
+
+    return sslContext;
+  }
+
+
+
+  /**
+   * Sets the key manager which the SSL context should use. By default, no key
+   * manager is specified indicating that no certificates will be used.
+   *
+   * @param keyManager
+   *          The key manager which the SSL context should use, which may be
+   *          {@code null} indicating that no certificates will be used.
+   * @return This SSL context builder.
+   */
+  public SSLContextBuilder setKeyManager(final KeyManager keyManager)
+  {
+    this.keyManager = keyManager;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the protocol which the SSL context should use. By default, TLSv1 will
+   * be used.
+   *
+   * @param protocol
+   *          The protocol which the SSL context should use, which may be
+   *          {@code null} indicating that TLSv1 will be used.
+   * @return This SSL context builder.
+   */
+  public SSLContextBuilder setProtocol(final String protocol)
+  {
+    this.protocol = protocol;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the provider which the SSL context should use. By default, the default
+   * provider associated with this JVM will be used.
+   *
+   * @param provider
+   *          The provider which the SSL context should use, which may be
+   *          {@code null} indicating that the default provider associated with
+   *          this JVM will be used.
+   * @return This SSL context builder.
+   */
+  public SSLContextBuilder setProvider(final Provider provider)
+  {
+    this.provider = provider;
+    this.providerName = null;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the provider which the SSL context should use. By default, the default
+   * provider associated with this JVM will be used.
+   *
+   * @param providerName
+   *          The name of the provider which the SSL context should use, which
+   *          may be {@code null} indicating that the default provider
+   *          associated with this JVM will be used.
+   * @return This SSL context builder.
+   */
+  public SSLContextBuilder setProvider(final String providerName)
+  {
+    this.provider = null;
+    this.providerName = providerName;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the secure random number generator which the SSL context should use.
+   * By default, the default secure random number generator associated with this
+   * JVM will be used.
+   *
+   * @param random
+   *          The secure random number generator which the SSL context should
+   *          use, which may be {@code null} indicating that the default secure
+   *          random number generator associated with this JVM will be used.
+   * @return This SSL context builder.
+   */
+  public SSLContextBuilder setSecureRandom(final SecureRandom random)
+  {
+    this.random = random;
+    return this;
+  }
+
+
+
+  /**
+   * Sets the trust manager which the SSL context should use. By default, no
+   * trust manager is specified indicating that only certificates signed by the
+   * authorities associated with this JVM will be accepted.
+   *
+   * @param trustManager
+   *          The trust manager which the SSL context should use, which may be
+   *          {@code null} indicating that only certificates signed by the
+   *          authorities associated with this JVM will be accepted.
+   * @return This SSL context builder.
+   */
+  public SSLContextBuilder setTrustManager(final TrustManager trustManager)
+  {
+    this.trustManager = trustManager;
+    return this;
+  }
+}
diff --git a/sdk/src/org/opends/sdk/SchemaResolver.java b/sdk/src/org/opends/sdk/SchemaResolver.java
new file mode 100644
index 0000000..f7243c4
--- /dev/null
+++ b/sdk/src/org/opends/sdk/SchemaResolver.java
@@ -0,0 +1,63 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import org.opends.sdk.schema.Schema;
+
+
+
+/**
+ * Schema resolvers are included with a set of {@code DecodeOptions} in order to
+ * allow application to control how {@code Schema} instances are selected when
+ * decoding requests and responses.
+ * <p>
+ * Implementations must be thread safe. More specifically, any schema caching
+ * performed by the implementation must be capable of handling multiple
+ * concurrent schema requests.
+ *
+ * @see Schema
+ * @see DecodeOptions
+ */
+public interface SchemaResolver
+{
+
+  /**
+   * Finds the appropriate schema for use with the provided distinguished name.
+   * <p>
+   * Schema resolution must always succeed regardless of any errors that occur.
+   *
+   * @param dn
+   *          The string representation of a distinguished name associated with
+   *          an entry whose schema is to be located.
+   * @return The appropriate schema for use with the provided distinguished
+   *         name.
+   */
+  public abstract Schema resolveSchema(String dn);
+}
diff --git a/sdk/src/org/opends/sdk/SearchResultHandler.java b/sdk/src/org/opends/sdk/SearchResultHandler.java
index 74ad84c..fc059b0 100644
--- a/sdk/src/org/opends/sdk/SearchResultHandler.java
+++ b/sdk/src/org/opends/sdk/SearchResultHandler.java
@@ -35,30 +35,33 @@
 
 
 /**
- * A completion handler for consuming the results of an asynchronous
- * Search operation.
+ * A completion handler for consuming the results of a Search operation.
  * <p>
- * {@link Connection} objects allow a search result completion handler
- * to be specified when sending Search operation requests to a Directory
- * Server. The {@link #handleEntry} method is invoked each time a Search
- * Result Entry is returned from the Directory Server. The
- * {@link #handleReference} method is invoked for each Search Result
- * Reference returned from the Directory Server.
+ * {@link Connection} and {@link AsynchronousConnection} objects allow a search
+ * result completion handler to be specified when sending Search operation
+ * requests to a Directory Server. The {@link #handleEntry} method is invoked
+ * each time a Search Result Entry is returned from the Directory Server. The
+ * {@link #handleReference} method is invoked for each Search Result Reference
+ * returned from the Directory Server.
  * <p>
- * Implementations of these methods should complete in a timely manner
- * so as to avoid keeping the invoking thread from dispatching to other
- * completion handlers.
+ * Implementations of these methods should complete in a timely manner so as to
+ * avoid keeping the invoking thread from dispatching to other completion
+ * handlers.
  */
 public interface SearchResultHandler
 {
   /**
-   * Invoked each time a search result entry is returned from an
-   * asynchronous search operation.
+   * Invoked each time a search result entry is returned from an asynchronous
+   * search operation.
    *
    * @param entry
    *          The search result entry.
+   * @return {@code true} if this handler should continue to be notified of any
+   *         remaining entries and references, or {@code false} if the remaining
+   *         entries and references should be skipped for some reason (e.g. a
+   *         client side size limit has been reached).
    */
-  void handleEntry(SearchResultEntry entry);
+  boolean handleEntry(SearchResultEntry entry);
 
 
 
@@ -68,6 +71,10 @@
    *
    * @param reference
    *          The search result reference.
+   * @return {@code true} if this handler should continue to be notified of any
+   *         remaining entries and references, or {@code false} if the remaining
+   *         entries and references should be skipped for some reason (e.g. a
+   *         client side size limit has been reached).
    */
-  void handleReference(SearchResultReference reference);
+  boolean handleReference(SearchResultReference reference);
 }
diff --git a/sdk/src/org/opends/sdk/SearchScope.java b/sdk/src/org/opends/sdk/SearchScope.java
index 7f02192..04ec469 100644
--- a/sdk/src/org/opends/sdk/SearchScope.java
+++ b/sdk/src/org/opends/sdk/SearchScope.java
@@ -36,16 +36,15 @@
 
 
 /**
- * A Search operation search scope as defined in RFC 4511 section
- * 4.5.1.2 is used to specify the scope of a Search operation.
+ * A Search operation search scope as defined in RFC 4511 section 4.5.1.2 is
+ * used to specify the scope of a Search operation.
  *
- * @see <a href="http://tools.ietf.org/html/rfc4511#section-4.5.1.2">RFC
- *      4511 - Lightweight Directory Access Protocol (LDAP): The
- *      Protocol </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4511#section-4.5.1.2">RFC 4511 -
+ *      Lightweight Directory Access Protocol (LDAP): The Protocol </a>
  * @see <a
  *      href="http://tools.ietf.org/html/draft-sermersheim-ldap-subordinate-scope">
- *      draft-sermersheim-ldap-subordinate-scope - Subordinate Subtree
- *      Search Scope for LDAP </a>
+ *      draft-sermersheim-ldap-subordinate-scope - Subordinate Subtree Search
+ *      Scope for LDAP </a>
  */
 public final class SearchScope
 {
@@ -60,8 +59,8 @@
   public static final SearchScope BASE_OBJECT = register(0, "base");
 
   /**
-   * The scope is constrained to the immediate subordinates of the
-   * search base entry.
+   * The scope is constrained to the immediate subordinates of the search base
+   * entry.
    */
   public static final SearchScope SINGLE_LEVEL = register(1, "one");
 
@@ -72,44 +71,23 @@
   public static final SearchScope WHOLE_SUBTREE = register(2, "sub");
 
   /**
-   * The scope is constrained to all the subordinates of the search base
-   * entry, but does not include the search base entry itself (as
-   * wholeSubtree does).
+   * The scope is constrained to all the subordinates of the search base entry,
+   * but does not include the search base entry itself (as wholeSubtree does).
    */
-  public static final SearchScope SUBORDINATES = register(3,
-      "subordinates");
+  public static final SearchScope SUBORDINATES = register(3, "subordinates");
 
 
 
   /**
-   * Creates and registers a new search scope with the application.
-   *
-   * @param intValue
-   *          The integer value of the search scope as defined in RFC
-   *          4511 section 4.5.1.2.
-   * @param name
-   *          The name of the search scope as defined in RFC 4516.
-   * @return The new search scope.
-   */
-  private static SearchScope register(int intValue, String name)
-  {
-    SearchScope t = new SearchScope(intValue, name);
-    ELEMENTS[intValue] = t;
-    return t;
-  }
-
-
-
-  /**
-   * Returns the search scope having the specified integer value as
-   * defined in RFC 4511 section 4.5.1.2.
+   * Returns the search scope having the specified integer value as defined in
+   * RFC 4511 section 4.5.1.2.
    *
    * @param intValue
    *          The integer value of the search scope.
-   * @return The search scope, or {@code null} if there was no search
-   *         scope associated with {@code intValue}.
+   * @return The search scope, or {@code null} if there was no search scope
+   *         associated with {@code intValue}.
    */
-  public static SearchScope valueOf(int intValue)
+  public static SearchScope valueOf(final int intValue)
   {
     if (intValue < 0 || intValue >= ELEMENTS.length)
     {
@@ -121,12 +99,10 @@
 
 
   /**
-   * Returns an unmodifiable list containing the set of available search
-   * scopes indexed on their integer value as defined in RFC 4511
-   * section 4.5.1.2.
+   * Returns an unmodifiable list containing the set of available search scopes
+   * indexed on their integer value as defined in RFC 4511 section 4.5.1.2.
    *
-   * @return An unmodifiable list containing the set of available search
-   *         scopes.
+   * @return An unmodifiable list containing the set of available search scopes.
    */
   public static List<SearchScope> values()
   {
@@ -135,6 +111,25 @@
 
 
 
+  /**
+   * Creates and registers a new search scope with the application.
+   *
+   * @param intValue
+   *          The integer value of the search scope as defined in RFC 4511
+   *          section 4.5.1.2.
+   * @param name
+   *          The name of the search scope as defined in RFC 4516.
+   * @return The new search scope.
+   */
+  private static SearchScope register(final int intValue, final String name)
+  {
+    final SearchScope t = new SearchScope(intValue, name);
+    ELEMENTS[intValue] = t;
+    return t;
+  }
+
+
+
   private final int intValue;
 
   private final String name;
@@ -142,7 +137,7 @@
 
 
   // Prevent direct instantiation.
-  private SearchScope(int intValue, String name)
+  private SearchScope(final int intValue, final String name)
   {
     this.intValue = intValue;
     this.name = name;
@@ -153,7 +148,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean equals(Object obj)
+  @Override
+  public boolean equals(final Object obj)
   {
     if (this == obj)
     {
@@ -174,6 +170,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   public int hashCode()
   {
     return intValue;
@@ -182,8 +179,8 @@
 
 
   /**
-   * Returns the integer value of this search scope as defined in RFC
-   * 4511 section 4.5.1.2.
+   * Returns the integer value of this search scope as defined in RFC 4511
+   * section 4.5.1.2.
    *
    * @return The integer value of this search scope.
    */
@@ -195,11 +192,12 @@
 
 
   /**
-   * Returns the string representation of this search scope as defined
-   * in RFC 4516.
+   * Returns the string representation of this search scope as defined in RFC
+   * 4516.
    *
    * @return The string representation of this search scope.
    */
+  @Override
   public String toString()
   {
     return name;
diff --git a/sdk/src/org/opends/sdk/ServerConnection.java b/sdk/src/org/opends/sdk/ServerConnection.java
new file mode 100644
index 0000000..ef81e2a
--- /dev/null
+++ b/sdk/src/org/opends/sdk/ServerConnection.java
@@ -0,0 +1,277 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import org.opends.sdk.requests.*;
+import org.opends.sdk.responses.BindResult;
+import org.opends.sdk.responses.CompareResult;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.Result;
+
+
+
+/**
+ * A handler interface for processing requests from clients.
+ *
+ * @param <C>
+ *          The type of request context.
+ */
+public interface ServerConnection<C>
+{
+
+  /**
+   * Invoked when an abandon request is received from a client.
+   *
+   * @param requestContext
+   *          The request context.
+   * @param request
+   *          The abandon request.
+   * @throws UnsupportedOperationException
+   *           If this server connection does not handle abandon requests.
+   */
+  void abandon(C requestContext, AbandonRequest request)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * Invoked when an add request is received from a client.
+   *
+   * @param requestContext
+   *          The request context.
+   * @param request
+   *          The add request.
+   * @param resultHandler
+   *          The handler which should be used to send back the result to the
+   *          client.
+   * @param intermediateResponseHandler
+   *          The handler which should be used to send back any intermediate
+   *          responses to the client.
+   * @throws UnsupportedOperationException
+   *           If this server connection does not handle add requests.
+   */
+  void add(C requestContext, AddRequest request,
+      ResultHandler<Result> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * Invoked when a bind request is received from a client.
+   *
+   * @param requestContext
+   *          The request context.
+   * @param version
+   *          The protocol version included with the bind request.
+   * @param request
+   *          The bind request.
+   * @param resultHandler
+   *          The handler which should be used to send back the result to the
+   *          client.
+   * @param intermediateResponseHandler
+   *          The handler which should be used to send back any intermediate
+   *          responses to the client.
+   * @throws UnsupportedOperationException
+   *           If this server connection does not handle bind requests.
+   */
+  void bind(C requestContext, int version, BindRequest request,
+      ResultHandler<? super BindResult> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * Invoked when the client closes the connection, possibly using an unbind
+   * request.
+   *
+   * @param requestContext
+   *          The request context.
+   * @param request
+   *          The unbind request, which may be {@code null} if one was not sent
+   *          before the connection was closed.
+   */
+  void closed(C requestContext, UnbindRequest request);
+
+
+
+  /**
+   * Invoked when an error occurs on the connection and it is no longer usable.
+   *
+   * @param error
+   *          The exception describing the problem that occurred.
+   */
+  void closed(Throwable error);
+
+
+
+  /**
+   * Invoked when a compare request is received from a client.
+   *
+   * @param requestContext
+   *          The request context.
+   * @param request
+   *          The compare request.
+   * @param resultHandler
+   *          The handler which should be used to send back the result to the
+   *          client.
+   * @param intermediateResponseHandler
+   *          The handler which should be used to send back any intermediate
+   *          responses to the client.
+   * @throws UnsupportedOperationException
+   *           If this server connection does not handle compare requests.
+   */
+  void compare(C requestContext, CompareRequest request,
+      ResultHandler<? super CompareResult> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * Invoked when a delete request is received from a client.
+   *
+   * @param requestContext
+   *          The request context.
+   * @param request
+   *          The delete request.
+   * @param resultHandler
+   *          The handler which should be used to send back the result to the
+   *          client.
+   * @param intermediateResponseHandler
+   *          The handler which should be used to send back any intermediate
+   *          responses to the client.
+   * @throws UnsupportedOperationException
+   *           If this server connection does not handle delete requests.
+   */
+  void delete(C requestContext, DeleteRequest request,
+      ResultHandler<Result> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * Invoked when an extended request is received from a client.
+   *
+   * @param <R>
+   *          The type of result returned by the extended request.
+   * @param requestContext
+   *          The request context.
+   * @param request
+   *          The extended request.
+   * @param resultHandler
+   *          The handler which should be used to send back the result to the
+   *          client.
+   * @param intermediateResponseHandler
+   *          The handler which should be used to send back any intermediate
+   *          responses to the client.
+   * @throws UnsupportedOperationException
+   *           If this server connection does not handle extended requests.
+   */
+  <R extends ExtendedResult> void extendedRequest(C requestContext,
+      ExtendedRequest<R> request, ResultHandler<R> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * Invoked when a modify request is received from a client.
+   *
+   * @param requestContext
+   *          The request context.
+   * @param request
+   *          The modify request.
+   * @param resultHandler
+   *          The handler which should be used to send back the result to the
+   *          client.
+   * @param intermediateResponseHandler
+   *          The handler which should be used to send back any intermediate
+   *          responses to the client.
+   * @throws UnsupportedOperationException
+   *           If this server connection does not handle modify requests.
+   */
+  void modify(C requestContext, ModifyRequest request,
+      ResultHandler<Result> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * Invoked when a modify DN request is received from a client.
+   *
+   * @param requestContext
+   *          The request context.
+   * @param request
+   *          The modify DN request.
+   * @param resultHandler
+   *          The handler which should be used to send back the result to the
+   *          client.
+   * @param intermediateResponseHandler
+   *          The handler which should be used to send back any intermediate
+   *          responses to the client.
+   * @throws UnsupportedOperationException
+   *           If this server connection does not handle modify DN requests.
+   */
+  void modifyDN(C requestContext, ModifyDNRequest request,
+      ResultHandler<Result> resultHandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * Invoked when a search request is received from a client.
+   *
+   * @param requestContext
+   *          The request context.
+   * @param request
+   *          The search request.
+   * @param resultHandler
+   *          The handler which should be used to send back the result to the
+   *          client.
+   * @param searchResulthandler
+   *          The handler which should be used to send back the search result
+   *          entries and references to the client.
+   * @param intermediateResponseHandler
+   *          The handler which should be used to send back any intermediate
+   *          responses to the client.
+   * @throws UnsupportedOperationException
+   *           If this server connection does not handle search requests.
+   */
+  void search(C requestContext, SearchRequest request,
+      ResultHandler<Result> resultHandler,
+      SearchResultHandler searchResulthandler,
+      IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException;
+}
diff --git a/sdk/src/org/opends/sdk/ServerConnectionFactory.java b/sdk/src/org/opends/sdk/ServerConnectionFactory.java
new file mode 100644
index 0000000..72f3928
--- /dev/null
+++ b/sdk/src/org/opends/sdk/ServerConnectionFactory.java
@@ -0,0 +1,59 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+/**
+ * A handler interface for accepting new connections from clients.
+ *
+ * @param <C>
+ *          The type of client context.
+ * @param <R>
+ *          The type of request context.
+ */
+public interface ServerConnectionFactory<C, R>
+{
+  /**
+   * Returns a {@code ServerConnection} which will be used to handle requests
+   * from a client connection.
+   *
+   * @param clientContext
+   *          The protocol dependent context information associated with the
+   *          client connection. Depending on the protocol this may contain
+   *          information about the client such as their address and level
+   *          connection security. It may also be used to manage the state of
+   *          the client's connection.
+   * @return a {@code ServerConnection} which will be used to handle requests
+   *         from a client connection.
+   * @throws ErrorResultException
+   *           If this server connection factory cannot accept the client
+   *           connection.
+   */
+  ServerConnection<R> accept(C clientContext) throws ErrorResultException;
+}
diff --git a/sdk/src/org/opends/sdk/SortKey.java b/sdk/src/org/opends/sdk/SortKey.java
new file mode 100644
index 0000000..606119a
--- /dev/null
+++ b/sdk/src/org/opends/sdk/SortKey.java
@@ -0,0 +1,704 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.*;
+
+import java.util.*;
+
+import org.opends.sdk.schema.MatchingRule;
+import org.opends.sdk.schema.Schema;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * A search result sort key as defined in RFC 2891 is used to specify how search
+ * result entries should be ordered. Sort keys are used with the server side
+ * sort request control
+ * {@link org.opends.sdk.controls.ServerSideSortRequestControl}, but could also
+ * be used for performing client side sorting as well.
+ * <p>
+ * The following example illustrates how a single sort key may be used to sort
+ * entries as they are returned from a search operation using the {@code cn}
+ * attribute as the sort key:
+ *
+ * <pre>
+ * Connection connection = ...;
+ * SearchRequest request = ...;
+ *
+ * Comparator&lt;Entry> comparator = SortKey.comparator("cn");
+ * Set&lt;SearchResultEntry>; results = new TreeSet&lt;SearchResultEntry>(comparator);
+ *
+ * connection.search(request, results);
+ * </pre>
+ *
+ * A sort key includes an attribute description and a boolean value that
+ * indicates whether the sort should be ascending or descending. It may also
+ * contain a specific ordering matching rule that should be used for the sorting
+ * process, although if none is provided it will use the default ordering
+ * matching rule for the attribute type.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc2891">RFC 2891 - LDAP Control
+ *      Extension for Server Side Sorting of Search Results </a>
+ */
+public final class SortKey
+{
+  private static final class CompositeEntryComparator implements
+      Comparator<Entry>
+  {
+    private final List<Comparator<Entry>> comparators;
+
+
+
+    private CompositeEntryComparator(final List<Comparator<Entry>> comparators)
+    {
+      this.comparators = comparators;
+    }
+
+
+
+    public int compare(final Entry entry1, final Entry entry2)
+    {
+      for (final Comparator<Entry> comparator : comparators)
+      {
+        final int result = comparator.compare(entry1, entry2);
+        if (result != 0)
+        {
+          return result;
+        }
+      }
+      return 0;
+    }
+
+  }
+
+
+
+  /**
+   * A comparator which can be used to compare entries using a sort key.
+   */
+  private static final class EntryComparator implements Comparator<Entry>
+  {
+    private final AttributeDescription attributeDescription;
+    private final MatchingRule matchingRule;
+    private final Comparator<ByteSequence> valueComparator;
+    private final boolean isReverseOrder;
+
+
+
+    private EntryComparator(final AttributeDescription attributeDescription,
+        final MatchingRule matchingRule, final boolean isReverseOrder)
+
+    {
+      this.attributeDescription = attributeDescription;
+      this.matchingRule = matchingRule;
+      this.valueComparator = matchingRule.comparator();
+      this.isReverseOrder = isReverseOrder;
+    }
+
+
+
+    /**
+     * We must use the lowest available value in both entries and missing
+     * attributes sort last.
+     */
+    public int compare(final Entry entry1, final Entry entry2)
+    {
+      // Find an normalize the lowest value attribute in entry1
+      ByteString lowestNormalizedValue1 = null;
+      for (final Attribute attribute : entry1
+          .getAllAttributes(attributeDescription))
+      {
+        for (final ByteString value : attribute)
+        {
+          try
+          {
+            final ByteString tmp = matchingRule.normalizeAttributeValue(value);
+            if (lowestNormalizedValue1 == null)
+            {
+              lowestNormalizedValue1 = tmp;
+            }
+            else if (valueComparator.compare(tmp, lowestNormalizedValue1) < 0)
+            {
+              lowestNormalizedValue1 = tmp;
+            }
+          }
+          catch (final DecodeException ignored)
+          {
+            // Ignore the error - treat the value as missing.
+          }
+        }
+      }
+
+      // Find an normalize the lowest value attribute in entry2
+      ByteString lowestNormalizedValue2 = null;
+      for (final Attribute attribute : entry2
+          .getAllAttributes(attributeDescription))
+      {
+        for (final ByteString value : attribute)
+        {
+          try
+          {
+            final ByteString tmp = matchingRule.normalizeAttributeValue(value);
+            if (lowestNormalizedValue2 == null)
+            {
+              lowestNormalizedValue2 = tmp;
+            }
+            else if (valueComparator.compare(tmp, lowestNormalizedValue2) < 0)
+            {
+              lowestNormalizedValue2 = tmp;
+            }
+          }
+          catch (final DecodeException ignored)
+          {
+            // Ignore the error - treat the value as missing.
+          }
+        }
+      }
+
+      // Entries with missing attributes always sort after (regardless of
+      // order).
+      if (lowestNormalizedValue1 == null)
+      {
+        return lowestNormalizedValue2 != null ? 1 : 0;
+      }
+
+      if (lowestNormalizedValue2 == null)
+      {
+        return -1;
+      }
+
+      if (isReverseOrder)
+      {
+        return valueComparator.compare(lowestNormalizedValue2,
+            lowestNormalizedValue1);
+      }
+      else
+      {
+        return valueComparator.compare(lowestNormalizedValue1,
+            lowestNormalizedValue2);
+      }
+    }
+
+  }
+
+
+
+  /**
+   * Returns a {@code Comparator} which can be used to compare entries using the
+   * provided list of sort keys. The sort keys will be decoded using the default
+   * schema.
+   *
+   * @param keys
+   *          The list of sort keys.
+   * @return The {@code Comparator}.
+   * @throws LocalizedIllegalArgumentException
+   *           If one of the sort keys could not be converted to a comparator.
+   * @throws IllegalArgumentException
+   *           If {@code keys} was empty.
+   * @throws NullPointerException
+   *           If {@code keys} was {@code null}.
+   */
+  public static Comparator<Entry> comparator(final Collection<SortKey> keys)
+      throws LocalizedIllegalArgumentException, IllegalArgumentException,
+      NullPointerException
+  {
+    return comparator(Schema.getDefaultSchema(), keys);
+  }
+
+
+
+  /**
+   * Returns a {@code Comparator} which can be used to compare entries using the
+   * provided list of sort keys. The sort keys will be decoded using the
+   * provided schema.
+   *
+   * @param schema
+   *          The schema which should be used for decoding the sort keys.
+   * @param keys
+   *          The list of sort keys.
+   * @return The {@code Comparator}.
+   * @throws LocalizedIllegalArgumentException
+   *           If one of the sort keys could not be converted to a comparator.
+   * @throws IllegalArgumentException
+   *           If {@code keys} was empty.
+   * @throws NullPointerException
+   *           If {@code schema} or {@code keys} was {@code null}.
+   */
+  public static Comparator<Entry> comparator(final Schema schema,
+      final Collection<SortKey> keys) throws LocalizedIllegalArgumentException,
+      IllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(schema, keys);
+    Validator.ensureTrue(!keys.isEmpty(), "keys must not be empty");
+
+    final List<Comparator<Entry>> comparators = new ArrayList<Comparator<Entry>>(
+        keys.size());
+    for (final SortKey key : keys)
+    {
+      comparators.add(key.comparator(schema));
+    }
+    return new CompositeEntryComparator(comparators);
+  }
+
+
+
+  /**
+   * Returns a {@code Comparator} which can be used to compare entries using the
+   * provided list of sort keys. The sort keys will be decoded using the
+   * provided schema.
+   *
+   * @param schema
+   *          The schema which should be used for decoding the sort keys.
+   * @param firstKey
+   *          The first sort key.
+   * @param remainingKeys
+   *          The remaining sort keys.
+   * @return The {@code Comparator}.
+   * @throws LocalizedIllegalArgumentException
+   *           If one of the sort keys could not be converted to a comparator.
+   * @throws NullPointerException
+   *           If {@code schema} or {@code firstKey} was {@code null}.
+   */
+  public static Comparator<Entry> comparator(final Schema schema,
+      final SortKey firstKey, final SortKey... remainingKeys)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(schema, firstKey, remainingKeys);
+
+    final List<Comparator<Entry>> comparators = new ArrayList<Comparator<Entry>>(
+        1 + remainingKeys.length);
+    comparators.add(firstKey.comparator(schema));
+    for (final SortKey key : remainingKeys)
+    {
+      comparators.add(key.comparator(schema));
+    }
+    return new CompositeEntryComparator(comparators);
+  }
+
+
+
+  /**
+   * Returns a {@code Comparator} which can be used to compare entries using the
+   * provided list of sort keys. The sort keys will be decoded using the default
+   * schema.
+   *
+   * @param firstKey
+   *          The first sort key.
+   * @param remainingKeys
+   *          The remaining sort keys.
+   * @return The {@code Comparator}.
+   * @throws LocalizedIllegalArgumentException
+   *           If one of the sort keys could not be converted to a comparator.
+   * @throws NullPointerException
+   *           If {@code firstKey} was {@code null}.
+   */
+  public static Comparator<Entry> comparator(final SortKey firstKey,
+      final SortKey... remainingKeys) throws LocalizedIllegalArgumentException,
+      NullPointerException
+  {
+    return comparator(Schema.getDefaultSchema(), firstKey, remainingKeys);
+  }
+
+
+
+  /**
+   * Returns a {@code Comparator} which can be used to compare entries using the
+   * provided string representation of a list of sort keys. The sort keys will
+   * be decoded using the default schema. The string representation is comprised
+   * of a comma separate list of sort keys as defined in
+   * {@link #valueOf(String)}. There must be at least one sort key present in
+   * the string representation.
+   *
+   * @param sortKeys
+   *          The list of sort keys.
+   * @return The {@code Comparator}.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code sortKeys} is not a valid string representation of a
+   *           list of sort keys, or if one of the sort keys could not be
+   *           converted to a comparator.
+   * @throws NullPointerException
+   *           If {@code sortKeys} was {@code null}.
+   */
+  public static Comparator<Entry> comparator(final String sortKeys)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(sortKeys);
+
+    final List<Comparator<Entry>> comparators = new LinkedList<Comparator<Entry>>();
+    final StringTokenizer tokenizer = new StringTokenizer(sortKeys, ",");
+    while (tokenizer.hasMoreTokens())
+    {
+      final String token = tokenizer.nextToken().trim();
+      comparators.add(valueOf(token).comparator());
+    }
+    if (comparators.isEmpty())
+    {
+      final LocalizableMessage message = ERR_SORT_KEY_NO_SORT_KEYS
+          .get(sortKeys);
+      throw new LocalizedIllegalArgumentException(message);
+    }
+    return new CompositeEntryComparator(comparators);
+  }
+
+
+
+  /**
+   * Parses the provided string representation of a sort key as a {@code
+   * SortKey}. The string representation has the following ABNF (see RFC 4512
+   * for definitions of the elements below):
+   *
+   * <pre>
+   *   SortKey = [ PLUS / HYPHEN ]    ; order specifier
+   *             attributedescription ; attribute description
+   *             [ COLON oid ]        ; ordering matching rule OID
+   * </pre>
+   *
+   * Examples:
+   *
+   * <pre>
+   *   cn                           ; case ignore ascending sort on "cn"
+   *   -cn                          ; case ignore descending sort on "cn"
+   *   +cn;lang-fr                  ; case ignore ascending sort on "cn;lang-fr"
+   *   -cn;lang-fr:caseExactMatch   ; case exact ascending sort on "cn;lang-fr"
+   * </pre>
+   *
+   * @param sortKey
+   *          The string representation of a sort key.
+   * @return The parsed {@code SortKey}.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code sortKey} is not a valid string representation of a sort
+   *           key.
+   * @throws NullPointerException
+   *           If {@code sortKey} was {@code null}.
+   */
+  public static final SortKey valueOf(String sortKey)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(sortKey);
+
+    boolean reverseOrder = false;
+    if (sortKey.startsWith("-"))
+    {
+      reverseOrder = true;
+      sortKey = sortKey.substring(1);
+    }
+    else if (sortKey.startsWith("+"))
+    {
+      sortKey = sortKey.substring(1);
+    }
+
+    final int colonPos = sortKey.indexOf(':');
+    if (colonPos < 0)
+    {
+      if (sortKey.length() == 0)
+      {
+        final LocalizableMessage message = ERR_SORT_KEY_NO_ATTR_NAME
+            .get(sortKey);
+        throw new LocalizedIllegalArgumentException(message);
+      }
+
+      return new SortKey(sortKey, reverseOrder, null);
+    }
+    else if (colonPos == 0)
+    {
+      final LocalizableMessage message = ERR_SORT_KEY_NO_ATTR_NAME.get(sortKey);
+      throw new LocalizedIllegalArgumentException(message);
+    }
+    else if (colonPos == (sortKey.length() - 1))
+    {
+      final LocalizableMessage message = ERR_SORT_KEY_NO_MATCHING_RULE
+          .get(sortKey);
+      throw new LocalizedIllegalArgumentException(message);
+    }
+    else
+    {
+      final String attrName = sortKey.substring(0, colonPos);
+      final String ruleID = sortKey.substring(colonPos + 1);
+
+      return new SortKey(attrName, reverseOrder, ruleID);
+    }
+  }
+
+
+
+  private final String attributeDescription;
+
+  private final String orderingMatchingRule;
+
+  private final boolean isReverseOrder;
+
+
+
+  /**
+   * Creates a new sort key using the provided attribute description. The
+   * returned sort key will compare attributes in the order specified using the
+   * named ordering matching rule.
+   *
+   * @param attributeDescription
+   *          The name of the attribute to be sorted using this sort key.
+   * @param isReverseOrder
+   *          {@code true} if this sort key should be evaluated in reverse
+   *          (descending) order.
+   * @param orderingMatchingRule
+   *          The name or OID of the ordering matching rule, which should be
+   *          used when comparing attributes using this sort key, or {@code
+   *          null} if the default ordering matching rule associated with the
+   *          attribute should be used.
+   * @throws NullPointerException
+   *           If {@code AttributeDescription} was {@code null}.
+   */
+  public SortKey(final AttributeDescription attributeDescription,
+      final boolean isReverseOrder, final MatchingRule orderingMatchingRule)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(attributeDescription);
+    this.attributeDescription = attributeDescription.toString();
+    this.orderingMatchingRule = orderingMatchingRule != null ? orderingMatchingRule
+        .getNameOrOID()
+        : null;
+    this.isReverseOrder = isReverseOrder;
+  }
+
+
+
+  /**
+   * Creates a new sort key using the provided attribute description. The
+   * returned sort key will compare attributes in ascending order using the
+   * default ordering matching rule associated with the attribute.
+   *
+   * @param attributeDescription
+   *          The name of the attribute to be sorted using this sort key.
+   * @throws NullPointerException
+   *           If {@code AttributeDescription} was {@code null}.
+   */
+  public SortKey(final String attributeDescription) throws NullPointerException
+  {
+    this(attributeDescription, false, null);
+  }
+
+
+
+  /**
+   * Creates a new sort key using the provided attribute description. The
+   * returned sort key will compare attributes in the order specified using the
+   * default ordering matching rule associated with the attribute.
+   *
+   * @param attributeDescription
+   *          The name of the attribute to be sorted using this sort key.
+   * @param isReverseOrder
+   *          {@code true} if this sort key should be evaluated in reverse
+   *          (descending) order.
+   * @throws NullPointerException
+   *           If {@code AttributeDescription} was {@code null}.
+   */
+  public SortKey(final String attributeDescription, final boolean isReverseOrder)
+      throws NullPointerException
+  {
+    this(attributeDescription, isReverseOrder, null);
+  }
+
+
+
+  /**
+   * Creates a new sort key using the provided attribute description. The
+   * returned sort key will compare attributes in the order specified using the
+   * named ordering matching rule.
+   *
+   * @param attributeDescription
+   *          The name of the attribute to be sorted using this sort key.
+   * @param isReverseOrder
+   *          {@code true} if this sort key should be evaluated in reverse
+   *          (descending) order.
+   * @param orderingMatchingRule
+   *          The name or OID of the ordering matching rule, which should be
+   *          used when comparing attributes using this sort key, or {@code
+   *          null} if the default ordering matching rule associated with the
+   *          attribute should be used.
+   * @throws NullPointerException
+   *           If {@code AttributeDescription} was {@code null}.
+   */
+  public SortKey(final String attributeDescription,
+      final boolean isReverseOrder, final String orderingMatchingRule)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(attributeDescription);
+    this.attributeDescription = attributeDescription;
+    this.orderingMatchingRule = orderingMatchingRule;
+    this.isReverseOrder = isReverseOrder;
+  }
+
+
+
+  /**
+   * Returns a {@code Comparator} which can be used to compare entries using
+   * this sort key. The attribute description and matching rule, if present,
+   * will be decoded using the default schema.
+   *
+   * @return The {@code Comparator}.
+   * @throws LocalizedIllegalArgumentException
+   *           If attributeDescription is not a valid LDAP string representation
+   *           of an attribute description, or if no ordering matching rule was
+   *           found.
+   */
+  public Comparator<Entry> comparator()
+      throws LocalizedIllegalArgumentException
+  {
+    return comparator(Schema.getDefaultSchema());
+  }
+
+
+
+  /**
+   * Returns a {@code Comparator} which can be used to compare entries using
+   * this sort key. The attribute description and matching rule, if present,
+   * will be decoded using the provided schema.
+   *
+   * @param schema
+   *          The schema which should be used for decoding the attribute
+   *          description and matching rule.
+   * @return The {@code Comparator}.
+   * @throws LocalizedIllegalArgumentException
+   *           If attributeDescription is not a valid LDAP string representation
+   *           of an attribute description, or if no ordering matching rule was
+   *           found.
+   * @throws NullPointerException
+   *           If {@code schema} was {@code null}.
+   */
+  public Comparator<Entry> comparator(final Schema schema)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(schema);
+
+    final AttributeDescription ad = AttributeDescription.valueOf(
+        attributeDescription, schema);
+
+    MatchingRule mrule;
+    if (orderingMatchingRule != null)
+    {
+      // FIXME: need to check that the matching rule is a matching rule and can
+      // be used with the attribute.
+      mrule = schema.getMatchingRule(orderingMatchingRule);
+
+      if (mrule == null)
+      {
+        // Specified ordering matching rule not found.
+        final LocalizableMessage message = ERR_SORT_KEY_MRULE_NOT_FOUND.get(
+            toString(), orderingMatchingRule);
+        throw new LocalizedIllegalArgumentException(message);
+      }
+    }
+    else
+    {
+      mrule = ad.getAttributeType().getOrderingMatchingRule();
+
+      if (mrule == null)
+      {
+        // No default ordering matching rule found.
+        final LocalizableMessage message = ERR_SORT_KEY_DEFAULT_MRULE_NOT_FOUND
+            .get(toString(), attributeDescription);
+        throw new LocalizedIllegalArgumentException(message);
+      }
+    }
+
+    return new EntryComparator(ad, mrule, isReverseOrder);
+  }
+
+
+
+  /**
+   * Returns the name of the attribute to be sorted using this sort key.
+   *
+   * @return The name of the attribute to be sorted using this sort key.
+   */
+  public String getAttributeDescription()
+  {
+    return attributeDescription;
+  }
+
+
+
+  /**
+   * Returns the name or OID of the ordering matching rule, if specified, which
+   * should be used when comparing attributes using this sort key.
+   *
+   * @return The name or OID of the ordering matching rule, if specified, which
+   *         should be used when comparing attributes using this sort key, or
+   *         {@code null} if the default ordering matching rule associated with
+   *         the attribute should be used.
+   */
+  public String getOrderingMatchingRule()
+  {
+    return orderingMatchingRule;
+  }
+
+
+
+  /**
+   * Returns {@code true} if this sort key should be evaluated in reverse
+   * (descending) order. More specifically, comparisons performed using the
+   * ordering matching rule associated with this sort key will have their
+   * results inverted.
+   *
+   * @return {@code true} if this sort key should be evaluated in reverse
+   *         (descending) order.
+   */
+  public boolean isReverseOrder()
+  {
+    return isReverseOrder;
+  }
+
+
+
+  /**
+   * Returns a string representation of this sort key using the format defined
+   * in {@link #valueOf(String)}.
+   *
+   * @return A string representation of this sort key.
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    if (isReverseOrder)
+    {
+      builder.append('-');
+    }
+    builder.append(attributeDescription);
+    if (orderingMatchingRule != null)
+    {
+      builder.append(':');
+      builder.append(orderingMatchingRule);
+    }
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/SortedEntry.java b/sdk/src/org/opends/sdk/SortedEntry.java
deleted file mode 100644
index 02b2b1a..0000000
--- a/sdk/src/org/opends/sdk/SortedEntry.java
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk;
-
-
-
-import java.util.Collection;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
-import org.opends.sdk.requests.Requests;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * An implementation of the {@code Entry} interface which uses a {@code
- * SortedMap} for storing attributes. Attributes are returned in
- * ascending order of attribute description, with {@code objectClass}
- * first, then all user attributes, and finally any operational
- * attributes. All operations are supported by this implementation.
- */
-public final class SortedEntry extends AbstractEntry
-{
-  private final SortedMap<AttributeDescription, Attribute> attributes = new TreeMap<AttributeDescription, Attribute>();
-
-  private DN name;
-
-
-
-  /**
-   * Creates an empty sorted entry and an empty (root) distinguished
-   * name.
-   */
-  public SortedEntry()
-  {
-    this(DN.rootDN());
-  }
-
-
-
-  /**
-   * Creates an empty sorted entry using the provided distinguished
-   * name.
-   *
-   * @param name
-   *          The distinguished name of this entry.
-   * @throws NullPointerException
-   *           If {@code name} was {@code null}.
-   */
-  public SortedEntry(DN name) throws NullPointerException
-  {
-    Validator.ensureNotNull(name);
-    this.name = name;
-  }
-
-
-
-  /**
-   * Creates an empty sorted entry using the provided distinguished name
-   * decoded using the default schema.
-   *
-   * @param name
-   *          The distinguished name of this entry.
-   * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
-   * @throws NullPointerException
-   *           If {@code name} was {@code null}.
-   */
-  public SortedEntry(String name)
-      throws LocalizedIllegalArgumentException, NullPointerException
-  {
-    this(DN.valueOf(name));
-  }
-
-
-
-  /**
-   * Creates a sorted entry having the same distinguished name,
-   * attributes, and object classes of the provided entry.
-   *
-   * @param entry
-   *          The entry to be copied.
-   * @throws NullPointerException
-   *           If {@code entry} was {@code null}.
-   */
-  public SortedEntry(Entry entry)
-  {
-    Validator.ensureNotNull(entry);
-
-    this.name = entry.getName();
-    for (Attribute attribute : entry.getAttributes())
-    {
-      addAttribute(attribute);
-    }
-  }
-
-
-
-  /**
-   * Creates a new sorted entry using the provided lines of LDIF decoded
-   * using the default schema.
-   *
-   * @param ldifLines
-   *          Lines of LDIF containing the an LDIF add change record or
-   *          an LDIF entry record.
-   * @throws LocalizedIllegalArgumentException
-   *           If {@code ldifLines} was empty, or contained invalid
-   *           LDIF, or could not be decoded using the default schema.
-   * @throws NullPointerException
-   *           If {@code ldifLines} was {@code null} .
-   */
-  public SortedEntry(String... ldifLines)
-      throws LocalizedIllegalArgumentException, NullPointerException
-  {
-    this(Requests.newAddRequest(ldifLines));
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean addAttribute(Attribute attribute,
-      Collection<ByteString> duplicateValues)
-      throws NullPointerException
-  {
-    Validator.ensureNotNull(attribute);
-
-    if (!attribute.isEmpty())
-    {
-      AttributeDescription attributeDescription = attribute
-          .getAttributeDescription();
-      Attribute oldAttribute = attributes.get(attributeDescription);
-      if (oldAttribute != null)
-      {
-        return oldAttribute.addAll(attribute, duplicateValues);
-      }
-      else
-      {
-        attributes.put(attributeDescription, attribute);
-        return true;
-      }
-    }
-    return false;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Entry clearAttributes()
-  {
-    attributes.clear();
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean containsAttribute(
-      AttributeDescription attributeDescription)
-      throws NullPointerException
-  {
-    Validator.ensureNotNull(attributeDescription);
-
-    return attributes.containsKey(attributeDescription);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Attribute getAttribute(
-      AttributeDescription attributeDescription)
-      throws NullPointerException
-  {
-    Validator.ensureNotNull(attributeDescription);
-
-    return attributes.get(attributeDescription);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public int getAttributeCount()
-  {
-    return attributes.size();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Iterable<Attribute> getAttributes()
-  {
-    return attributes.values();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public DN getName()
-  {
-    return name;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean removeAttribute(Attribute attribute,
-      Collection<ByteString> missingValues) throws NullPointerException
-  {
-    Validator.ensureNotNull(attribute);
-
-    AttributeDescription attributeDescription = attribute
-        .getAttributeDescription();
-
-    if (attribute.isEmpty())
-    {
-      return attributes.remove(attributeDescription) != null;
-    }
-    else
-    {
-      Attribute oldAttribute = attributes.get(attributeDescription);
-      if (oldAttribute != null)
-      {
-        boolean modified = oldAttribute.removeAll(attribute,
-            missingValues);
-        if (oldAttribute.isEmpty())
-        {
-          attributes.remove(attributeDescription);
-          return true;
-        }
-        return modified;
-      }
-      else
-      {
-        return false;
-      }
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Entry setName(DN dn) throws NullPointerException
-  {
-    Validator.ensureNotNull(dn);
-    this.name = dn;
-    return this;
-  }
-
-}
diff --git a/sdk/src/org/opends/sdk/SynchronousConnection.java b/sdk/src/org/opends/sdk/SynchronousConnection.java
index 29645f7..1d82232 100644
--- a/sdk/src/org/opends/sdk/SynchronousConnection.java
+++ b/sdk/src/org/opends/sdk/SynchronousConnection.java
@@ -32,6 +32,7 @@
 import org.opends.sdk.requests.*;
 import org.opends.sdk.responses.BindResult;
 import org.opends.sdk.responses.CompareResult;
+import org.opends.sdk.responses.ExtendedResult;
 import org.opends.sdk.responses.Result;
 import org.opends.sdk.schema.Schema;
 
@@ -40,8 +41,8 @@
 
 
 /**
- * A {@code SynchronousConnection} adapts an {@code
- * AsynchronousConnection} into a synchronous {@code Connection}.
+ * A {@code SynchronousConnection} adapts an {@code AsynchronousConnection} into
+ * a synchronous {@code Connection}.
  */
 public class SynchronousConnection extends AbstractConnection
 {
@@ -50,15 +51,15 @@
 
 
   /**
-   * Creates a new abstract connection which will route all synchronous
-   * requests to the provided asynchronous connection.
+   * Creates a new abstract connection which will route all synchronous requests
+   * to the provided asynchronous connection.
    *
    * @param connection
    *          The asynchronous connection to be used.
    * @throws NullPointerException
    *           If {@code connection} was {@code null}.
    */
-  public SynchronousConnection(AsynchronousConnection connection)
+  public SynchronousConnection(final AsynchronousConnection connection)
       throws NullPointerException
   {
     Validator.ensureNotNull(connection);
@@ -70,11 +71,11 @@
   /**
    * {@inheritDoc}
    */
-  public Result add(AddRequest request) throws ErrorResultException,
+  public Result add(final AddRequest request) throws ErrorResultException,
       InterruptedException, UnsupportedOperationException,
       IllegalStateException, NullPointerException
   {
-    FutureResult<Result> future = connection.add(request, null);
+    final FutureResult<Result> future = connection.add(request, null);
     try
     {
       return future.get();
@@ -88,162 +89,137 @@
 
 
 
-  public void addConnectionEventListener(
-      ConnectionEventListener listener) throws IllegalStateException,
-      NullPointerException
-  {
-    connection.addConnectionEventListener(listener);
-  }
-
-
-
-  public BindResult bind(BindRequest request)
-      throws ErrorResultException, InterruptedException,
-      UnsupportedOperationException, IllegalStateException,
-      NullPointerException
-  {
-    FutureResult<BindResult> future = connection.bind(request, null);
-    try
-    {
-      return future.get();
-    }
-    finally
-    {
-      // Cancel the request if it hasn't completed.
-      future.cancel(false);
-    }
-  }
-
-
-
-  public void close()
-  {
-    connection.close();
-  }
-
-
-
-  public void close(UnbindRequest request, String reason)
-      throws NullPointerException
-  {
-    connection.close(request, reason);
-  }
-
-
-
-  public CompareResult compare(CompareRequest request)
-      throws ErrorResultException, InterruptedException,
-      UnsupportedOperationException, IllegalStateException,
-      NullPointerException
-  {
-    FutureResult<CompareResult> future = connection.compare(request,
-        null);
-    try
-    {
-      return future.get();
-    }
-    finally
-    {
-      // Cancel the request if it hasn't completed.
-      future.cancel(false);
-    }
-  }
-
-
-
-  public Result delete(DeleteRequest request)
-      throws ErrorResultException, InterruptedException,
-      UnsupportedOperationException, IllegalStateException,
-      NullPointerException
-  {
-    FutureResult<Result> future = connection.delete(request, null);
-    try
-    {
-      return future.get();
-    }
-    finally
-    {
-      // Cancel the request if it hasn't completed.
-      future.cancel(false);
-    }
-  }
-
-
-
-  public <R extends Result> R extendedRequest(ExtendedRequest<R> request)
-      throws ErrorResultException, InterruptedException,
-      UnsupportedOperationException, IllegalStateException,
-      NullPointerException
-  {
-    FutureResult<R> future = connection.extendedRequest(request, null);
-    try
-    {
-      return future.get();
-    }
-    finally
-    {
-      // Cancel the request if it hasn't completed.
-      future.cancel(false);
-    }
-  }
-
-
-
-  public Result modify(ModifyRequest request)
-      throws ErrorResultException, InterruptedException,
-      UnsupportedOperationException, IllegalStateException,
-      NullPointerException
-  {
-    FutureResult<Result> future = connection.modify(request, null);
-    try
-    {
-      return future.get();
-    }
-    finally
-    {
-      // Cancel the request if it hasn't completed.
-      future.cancel(false);
-    }
-  }
-
-
-
-  public Result modifyDN(ModifyDNRequest request)
-      throws ErrorResultException, InterruptedException,
-      UnsupportedOperationException, IllegalStateException,
-      NullPointerException
-  {
-    FutureResult<Result> future = connection.modifyDN(request, null);
-    try
-    {
-      return future.get();
-    }
-    finally
-    {
-      // Cancel the request if it hasn't completed.
-      future.cancel(false);
-    }
-  }
-
-
-
-  public void removeConnectionEventListener(
-      ConnectionEventListener listener) throws NullPointerException
-  {
-    connection.removeConnectionEventListener(listener);
-  }
-
-
-
   /**
    * {@inheritDoc}
    */
-  public Result search(SearchRequest request,
-      SearchResultHandler handler) throws ErrorResultException,
+  public void addConnectionEventListener(final ConnectionEventListener listener)
+      throws IllegalStateException, NullPointerException
+  {
+    connection.addConnectionEventListener(listener);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public BindResult bind(final BindRequest request)
+      throws ErrorResultException, InterruptedException,
+      UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final FutureResult<BindResult> future = connection.bind(request, null);
+    try
+    {
+      return future.get();
+    }
+    finally
+    {
+      // Cancel the request if it hasn't completed.
+      future.cancel(false);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void close()
+  {
+    connection.close();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void close(final UnbindRequest request, final String reason)
+      throws NullPointerException
+  {
+    connection.close(request, reason);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public CompareResult compare(final CompareRequest request)
+      throws ErrorResultException, InterruptedException,
+      UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final FutureResult<CompareResult> future = connection
+        .compare(request, null);
+    try
+    {
+      return future.get();
+    }
+    finally
+    {
+      // Cancel the request if it hasn't completed.
+      future.cancel(false);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Result delete(final DeleteRequest request)
+      throws ErrorResultException, InterruptedException,
+      UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final FutureResult<Result> future = connection.delete(request, null);
+    try
+    {
+      return future.get();
+    }
+    finally
+    {
+      // Cancel the request if it hasn't completed.
+      future.cancel(false);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public <R extends ExtendedResult> R extendedRequest(
+      final ExtendedRequest<R> request) throws ErrorResultException,
       InterruptedException, UnsupportedOperationException,
       IllegalStateException, NullPointerException
   {
-    FutureResult<Result> future = connection.search(request, null,
+    final FutureResult<R> future = connection.extendedRequest(request, null);
+    try
+    {
+      return future.get();
+    }
+    finally
+    {
+      // Cancel the request if it hasn't completed.
+      future.cancel(false);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public <R extends ExtendedResult> R extendedRequest(
+      final ExtendedRequest<R> request,
+      final IntermediateResponseHandler handler) throws ErrorResultException,
+      InterruptedException, UnsupportedOperationException,
+      IllegalStateException, NullPointerException
+  {
+    final FutureResult<R> future = connection.extendedRequest(request, null,
         handler);
     try
     {
@@ -261,6 +237,16 @@
   /**
    * {@inheritDoc}
    */
+  public AsynchronousConnection getAsynchronousConnection()
+  {
+    return connection;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
   public boolean isClosed()
   {
     return connection.isClosed();
@@ -271,11 +257,66 @@
   /**
    * {@inheritDoc}
    */
-  public Schema readSchemaForEntry(DN name)
-      throws ErrorResultException, InterruptedException,
-      UnsupportedOperationException, IllegalStateException
+  public boolean isValid()
   {
-    FutureResult<Schema> future = connection.readSchemaForEntry(name,
+    return connection.isValid();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Result modify(final ModifyRequest request)
+      throws ErrorResultException, InterruptedException,
+      UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final FutureResult<Result> future = connection.modify(request, null);
+    try
+    {
+      return future.get();
+    }
+    finally
+    {
+      // Cancel the request if it hasn't completed.
+      future.cancel(false);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Result modifyDN(final ModifyDNRequest request)
+      throws ErrorResultException, InterruptedException,
+      UnsupportedOperationException, IllegalStateException,
+      NullPointerException
+  {
+    final FutureResult<Result> future = connection.modifyDN(request, null);
+    try
+    {
+      return future.get();
+    }
+    finally
+    {
+      // Cancel the request if it hasn't completed.
+      future.cancel(false);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public Schema readSchemaForEntry(final DN name) throws ErrorResultException,
+      InterruptedException, UnsupportedOperationException,
+      IllegalStateException
+  {
+    final FutureResult<Schema> future = connection.readSchemaForEntry(name,
         null);
     try
     {
@@ -288,4 +329,38 @@
     }
   }
 
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public void removeConnectionEventListener(
+      final ConnectionEventListener listener) throws NullPointerException
+  {
+    connection.removeConnectionEventListener(listener);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Result search(final SearchRequest request,
+      final SearchResultHandler handler) throws ErrorResultException,
+      InterruptedException, UnsupportedOperationException,
+      IllegalStateException, NullPointerException
+  {
+    final FutureResult<Result> future = connection.search(request, null,
+        handler);
+    try
+    {
+      return future.get();
+    }
+    finally
+    {
+      // Cancel the request if it hasn't completed.
+      future.cancel(false);
+    }
+  }
+
 }
diff --git a/sdk/src/org/opends/sdk/TimeoutResultException.java b/sdk/src/org/opends/sdk/TimeoutResultException.java
index c7fbe1c..db3f200 100644
--- a/sdk/src/org/opends/sdk/TimeoutResultException.java
+++ b/sdk/src/org/opends/sdk/TimeoutResultException.java
@@ -34,14 +34,13 @@
 
 
 /**
- * Thrown when the result code returned in a Result indicates that the
- * Request was aborted because it did not complete in the required time
- * out period.
+ * Thrown when the result code returned in a Result indicates that the Request
+ * was aborted because it did not complete in the required time out period.
  */
 @SuppressWarnings("serial")
 public class TimeoutResultException extends ErrorResultException
 {
-  TimeoutResultException(Result result)
+  TimeoutResultException(final Result result)
   {
     super(result);
   }
diff --git a/sdk/src/org/opends/sdk/TreeMapEntry.java b/sdk/src/org/opends/sdk/TreeMapEntry.java
new file mode 100644
index 0000000..75b46d3
--- /dev/null
+++ b/sdk/src/org/opends/sdk/TreeMapEntry.java
@@ -0,0 +1,157 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.util.TreeMap;
+
+import org.opends.sdk.requests.Requests;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * An implementation of the {@code Entry} interface which uses a {@code TreeMap}
+ * for storing attributes. Attributes are returned in ascending order of
+ * attribute description, with {@code objectClass} first, then all user
+ * attributes, and finally any operational attributes. All operations are
+ * supported by this implementation.
+ * <p>
+ * A {@code TreeMapEntry} stores references to attributes which have been added
+ * using the {@link #addAttribute} methods. Attributes sharing the same
+ * attribute description are merged by adding the values of the new attribute to
+ * the existing attribute. More specifically, the existing attribute must be
+ * modifiable for the merge to succeed. Similarly, the {@link #removeAttribute}
+ * methods remove the specified values from the existing attribute. The
+ * {@link #replaceAttribute} methods remove the existing attribute (if present)
+ * and store a reference to the new attribute - neither the new or existing
+ * attribute need to be modifiable in this case.
+ */
+public final class TreeMapEntry extends AbstractMapEntry
+{
+  /**
+   * An entry factory which can be used to create new tree map entries.
+   */
+  public static final EntryFactory FACTORY = new EntryFactory()
+  {
+    public Entry newEntry(final DN name) throws NullPointerException
+    {
+      return new TreeMapEntry(name);
+    }
+  };
+
+
+
+  /**
+   * Creates an entry with an empty (root) distinguished name and no attributes.
+   */
+  public TreeMapEntry()
+  {
+    this(DN.rootDN());
+  }
+
+
+
+  /**
+   * Creates an empty entry using the provided distinguished name and no
+   * attributes.
+   *
+   * @param name
+   *          The distinguished name of this entry.
+   * @throws NullPointerException
+   *           If {@code name} was {@code null}.
+   */
+  public TreeMapEntry(final DN name) throws NullPointerException
+  {
+    super(Validator.ensureNotNull(name),
+        new TreeMap<AttributeDescription, Attribute>());
+  }
+
+
+
+  /**
+   * Creates an entry having the same distinguished name, attributes, and object
+   * classes of the provided entry.
+   *
+   * @param entry
+   *          The entry to be copied.
+   * @throws NullPointerException
+   *           If {@code entry} was {@code null}.
+   */
+  public TreeMapEntry(final Entry entry) throws NullPointerException
+  {
+    this(entry.getName());
+    for (final Attribute attribute : entry.getAllAttributes())
+    {
+      addAttribute(attribute);
+    }
+  }
+
+
+
+  /**
+   * Creates an empty entry using the provided distinguished name decoded using
+   * the default schema.
+   *
+   * @param name
+   *          The distinguished name of this entry.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code name} could not be decoded using the default schema.
+   * @throws NullPointerException
+   *           If {@code name} was {@code null}.
+   */
+  public TreeMapEntry(final String name)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    this(DN.valueOf(name));
+  }
+
+
+
+  /**
+   * Creates a new entry using the provided lines of LDIF decoded using the
+   * default schema.
+   *
+   * @param ldifLines
+   *          Lines of LDIF containing the an LDIF add change record or an LDIF
+   *          entry record.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code ldifLines} was empty, or contained invalid LDIF, or
+   *           could not be decoded using the default schema.
+   * @throws NullPointerException
+   *           If {@code ldifLines} was {@code null} .
+   */
+  public TreeMapEntry(final String... ldifLines)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    this(Requests.newAddRequest(ldifLines));
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/TrustManagers.java b/sdk/src/org/opends/sdk/TrustManagers.java
new file mode 100644
index 0000000..1453851
--- /dev/null
+++ b/sdk/src/org/opends/sdk/TrustManagers.java
@@ -0,0 +1,553 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
+
+import org.opends.sdk.schema.Schema;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * This class contains methods for creating common types of trust manager.
+ */
+public final class TrustManagers
+{
+
+  /**
+   * An X509TrustManager which rejects certificate chains whose subject DN does
+   * not match a specified host name.
+   */
+  private static final class CheckHostName implements X509TrustManager
+  {
+
+    private final X509TrustManager trustManager;
+
+    private final String hostNamePattern;
+
+
+
+    private CheckHostName(final X509TrustManager trustManager,
+        final String hostNamePattern)
+    {
+      this.trustManager = trustManager;
+      this.hostNamePattern = hostNamePattern;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void checkClientTrusted(final X509Certificate[] chain,
+        final String authType) throws CertificateException
+    {
+      verifyHostName(chain);
+      trustManager.checkClientTrusted(chain, authType);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void checkServerTrusted(final X509Certificate[] chain,
+        final String authType) throws CertificateException
+    {
+      verifyHostName(chain);
+      trustManager.checkServerTrusted(chain, authType);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public X509Certificate[] getAcceptedIssuers()
+    {
+      return trustManager.getAcceptedIssuers();
+    }
+
+
+
+    /**
+     * Checks whether a host name matches the provided pattern. It accepts the
+     * use of wildcards in the pattern, e.g. {@code *.example.com}.
+     *
+     * @param hostName
+     *          The host name.
+     * @param pattern
+     *          The host name pattern, which may contain wild cards.
+     * @return {@code true} if the host name matched the pattern, otherwise
+     *         {@code false}.
+     */
+    private boolean hostNameMatchesPattern(final String hostName,
+        final String pattern)
+    {
+      final String[] nameElements = hostName.split("\\.");
+      final String[] patternElements = pattern.split("\\.");
+
+      boolean hostMatch = nameElements.length == patternElements.length;
+      for (int i = 0; i < nameElements.length && hostMatch; i++)
+      {
+        final String ne = nameElements[i];
+        final String pe = patternElements[i];
+        if (!pe.equals("*"))
+        {
+          hostMatch = ne.equalsIgnoreCase(pe);
+        }
+      }
+      return hostMatch;
+    }
+
+
+
+    private void verifyHostName(final X509Certificate[] chain)
+        throws CertificateException
+    {
+      try
+      {
+        // TODO: NPE if root DN.
+        final DN dn = DN.valueOf(chain[0].getSubjectX500Principal().getName(),
+            Schema.getCoreSchema());
+        final String value = dn.iterator().next().iterator().next()
+            .getAttributeValue().toString();
+        if (!hostNameMatchesPattern(value, hostNamePattern))
+        {
+          throw new CertificateException(
+              "The host name contained in the certificate chain subject DN \'"
+                  + chain[0].getSubjectX500Principal()
+                  + "' does not match the host name \'" + hostNamePattern + "'");
+        }
+      }
+      catch (final Throwable t)
+      {
+        LOG.log(Level.WARNING, "Error parsing subject dn: "
+            + chain[0].getSubjectX500Principal(), t);
+      }
+    }
+  }
+
+
+
+  /**
+   * An X509TrustManager which rejects certificates which have expired or are
+   * not yet valid.
+   */
+  private static final class CheckValidatyDates implements X509TrustManager
+  {
+
+    private final X509TrustManager trustManager;
+
+
+
+    private CheckValidatyDates(final X509TrustManager trustManager)
+    {
+      this.trustManager = trustManager;
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void checkClientTrusted(final X509Certificate[] chain,
+        final String authType) throws CertificateException
+    {
+      verifyExpiration(chain);
+      trustManager.checkClientTrusted(chain, authType);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void checkServerTrusted(final X509Certificate[] chain,
+        final String authType) throws CertificateException
+    {
+      verifyExpiration(chain);
+      trustManager.checkServerTrusted(chain, authType);
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public X509Certificate[] getAcceptedIssuers()
+    {
+      return trustManager.getAcceptedIssuers();
+    }
+
+
+
+    private void verifyExpiration(final X509Certificate[] chain)
+        throws CertificateException
+    {
+      final Date currentDate = new Date();
+      for (final X509Certificate c : chain)
+      {
+        try
+        {
+          c.checkValidity(currentDate);
+        }
+        catch (final CertificateExpiredException e)
+        {
+          LOG.log(Level.WARNING, "Refusing to trust security"
+              + " certificate \"" + c.getSubjectDN().getName()
+              + "\" because it" + " expired on "
+              + String.valueOf(c.getNotAfter()));
+
+          throw e;
+        }
+        catch (final CertificateNotYetValidException e)
+        {
+          LOG.log(Level.WARNING, "Refusing to trust security"
+              + " certificate \"" + c.getSubjectDN().getName()
+              + "\" because it" + " is not valid until "
+              + String.valueOf(c.getNotBefore()));
+
+          throw e;
+        }
+      }
+    }
+  }
+
+
+
+  /**
+   * An X509TrustManager which does not trust any certificates.
+   */
+  private static final class DistrustAll implements X509TrustManager
+  {
+    // Single instance.
+    private static final DistrustAll INSTANCE = new DistrustAll();
+
+
+
+    // Prevent instantiation.
+    private DistrustAll()
+    {
+      // Nothing to do.
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void checkClientTrusted(final X509Certificate[] chain,
+        final String authType) throws CertificateException
+    {
+      throw new CertificateException();
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void checkServerTrusted(final X509Certificate[] chain,
+        final String authType) throws CertificateException
+    {
+      throw new CertificateException();
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public X509Certificate[] getAcceptedIssuers()
+    {
+      return new X509Certificate[0];
+    }
+  }
+
+
+
+  /**
+   * An X509TrustManager which trusts all certificates.
+   */
+  private static final class TrustAll implements X509TrustManager
+  {
+
+    // Single instance.
+    private static final TrustAll INSTANCE = new TrustAll();
+
+
+
+    // Prevent instantiation.
+    private TrustAll()
+    {
+      // Nothing to do.
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void checkClientTrusted(final X509Certificate[] chain,
+        final String authType) throws CertificateException
+    {
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void checkServerTrusted(final X509Certificate[] chain,
+        final String authType) throws CertificateException
+    {
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public X509Certificate[] getAcceptedIssuers()
+    {
+      return new X509Certificate[0];
+    }
+  }
+
+
+
+  private static final Logger LOG = Logger.getLogger(TrustManagers.class
+      .getName());
+
+
+
+  /**
+   * Wraps the provided {@code X509TrustManager} by adding additional validation
+   * which rejects certificate chains whose subject DN does not match the
+   * specified host name pattern. The pattern may contain wild-cards, for
+   * example {@code *.example.com}.
+   *
+   * @param hostNamePattern
+   *          A host name pattern which the RDN value contained in certificate
+   *          subject DNs must match.
+   * @param trustManager
+   *          The trust manager to be wrapped.
+   * @return The wrapped trust manager.
+   * @throws NullPointerException
+   *           If {@code trustManager} or {@code hostNamePattern} was {@code
+   *           null}.
+   */
+  public static X509TrustManager checkHostName(final String hostNamePattern,
+      final X509TrustManager trustManager) throws NullPointerException
+  {
+    Validator.ensureNotNull(trustManager, hostNamePattern);
+    return new CheckHostName(trustManager, hostNamePattern);
+  }
+
+
+
+  /**
+   * Creates a new {@code X509TrustManager} which will use the named trust store
+   * file to determine whether to trust a certificate. It will use the default
+   * trust store format for the JVM (e.g. {@code JKS}) and will not use a
+   * password to open the trust store.
+   *
+   * @param file
+   *          The trust store file name.
+   * @return A new {@code X509TrustManager} which will use the named trust store
+   *         file to determine whether to trust a certificate.
+   * @throws GeneralSecurityException
+   *           If the trust store could not be loaded, perhaps due to incorrect
+   *           format, or missing algorithms.
+   * @throws IOException
+   *           If the trust store file could not be found or could not be read.
+   * @throws NullPointerException
+   *           If {@code file} was {@code null}.
+   */
+  public static X509TrustManager checkUsingTrustStore(final String file)
+      throws GeneralSecurityException, IOException, NullPointerException
+  {
+    return checkUsingTrustStore(file, null, null);
+  }
+
+
+
+  /**
+   * Creates a new {@code X509TrustManager} which will use the named trust store
+   * file to determine whether to trust a certificate. It will use the provided
+   * trust store format and password.
+   *
+   * @param file
+   *          The trust store file name.
+   * @param password
+   *          The trust store password, which may be {@code null}.
+   * @param format
+   *          The trust store format, which may be {@code null} to indicate that
+   *          the default trust store format for the JVM (e.g. {@code JKS})
+   *          should be used.
+   * @return A new {@code X509TrustManager} which will use the named trust store
+   *         file to determine whether to trust a certificate.
+   * @throws GeneralSecurityException
+   *           If the trust store could not be loaded, perhaps due to incorrect
+   *           format, or missing algorithms.
+   * @throws IOException
+   *           If the trust store file could not be found or could not be read.
+   * @throws NullPointerException
+   *           If {@code file} was {@code null}.
+   */
+  public static X509TrustManager checkUsingTrustStore(final String file,
+      final String password, final String format)
+      throws GeneralSecurityException, IOException, NullPointerException
+  {
+    Validator.ensureNotNull(file);
+
+    final File trustStoreFile = new File(file);
+    final char[] trustStorePassword = password != null ? password.toCharArray()
+        : null;
+    final String trustStoreFormat = format != null ? format : KeyStore
+        .getDefaultType();
+
+    final KeyStore keyStore = KeyStore.getInstance(trustStoreFormat);
+
+    FileInputStream fos = null;
+    try
+    {
+      fos = new FileInputStream(trustStoreFile);
+      keyStore.load(fos, trustStorePassword);
+    }
+    finally
+    {
+      if (fos != null)
+      {
+        try
+        {
+          fos.close();
+        }
+        catch (final IOException ignored)
+        {
+          // Ignore.
+        }
+      }
+    }
+
+    final TrustManagerFactory tmf = TrustManagerFactory
+        .getInstance(TrustManagerFactory.getDefaultAlgorithm());
+    tmf.init(keyStore);
+
+    X509TrustManager x509tm = null;
+    for (final TrustManager tm : tmf.getTrustManagers())
+    {
+      if (tm instanceof X509TrustManager)
+      {
+        x509tm = (X509TrustManager) tm;
+        break;
+      }
+    }
+
+    if (x509tm == null)
+    {
+      throw new NoSuchAlgorithmException();
+    }
+
+    return x509tm;
+  }
+
+
+
+  /**
+   * Wraps the provided {@code X509TrustManager} by adding additional validation
+   * which rejects certificate chains containing certificates which have expired
+   * or are not yet valid.
+   *
+   * @param trustManager
+   *          The trust manager to be wrapped.
+   * @return The wrapped trust manager.
+   * @throws NullPointerException
+   *           If {@code trustManager} was {@code null}.
+   */
+  public static X509TrustManager checkValidityDates(
+      final X509TrustManager trustManager) throws NullPointerException
+  {
+    Validator.ensureNotNull(trustManager);
+    return new CheckValidatyDates(trustManager);
+  }
+
+
+
+  /**
+   * Returns an {@code X509TrustManager} which does not trust any certificates.
+   *
+   * @return An {@code X509TrustManager} which does not trust any certificates.
+   */
+  public static X509TrustManager distrustAll()
+  {
+    return DistrustAll.INSTANCE;
+  }
+
+
+
+  /**
+   * Returns an {@code X509TrustManager} which trusts all certificates.
+   *
+   * @return An {@code X509TrustManager} which trusts all certificates.
+   */
+  public static X509TrustManager trustAll()
+  {
+    return TrustAll.INSTANCE;
+  }
+
+
+
+  // Prevent insantiation.
+  private TrustManagers()
+  {
+    // Nothing to do.
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/Types.java b/sdk/src/org/opends/sdk/Types.java
index 81c65a6..c8cbd29 100644
--- a/sdk/src/org/opends/sdk/Types.java
+++ b/sdk/src/org/opends/sdk/Types.java
@@ -34,9 +34,11 @@
 import java.util.NoSuchElementException;
 
 import org.opends.sdk.schema.AttributeType;
-import org.opends.sdk.schema.ObjectClass;
 
-import com.sun.opends.sdk.util.*;
+import com.sun.opends.sdk.util.Function;
+import com.sun.opends.sdk.util.Iterables;
+import com.sun.opends.sdk.util.Iterators;
+import com.sun.opends.sdk.util.Validator;
 
 
 
@@ -57,14 +59,15 @@
 
 
 
-    private EmptyAttribute(AttributeDescription attributeDescription)
+    private EmptyAttribute(final AttributeDescription attributeDescription)
     {
       this.attributeDescription = attributeDescription;
     }
 
 
 
-    public boolean add(ByteString value)
+    @Override
+    public boolean add(final ByteString value)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -72,6 +75,7 @@
 
 
 
+    @Override
     public void clear() throws UnsupportedOperationException
     {
       throw new UnsupportedOperationException();
@@ -79,6 +83,15 @@
 
 
 
+    @Override
+    public boolean contains(final Object value) throws NullPointerException
+    {
+      return false;
+    }
+
+
+
+    @Override
     public AttributeDescription getAttributeDescription()
     {
       return attributeDescription;
@@ -86,6 +99,7 @@
 
 
 
+    @Override
     public boolean isEmpty()
     {
       return true;
@@ -93,6 +107,7 @@
 
 
 
+    @Override
     public Iterator<ByteString> iterator()
     {
       return Iterators.empty();
@@ -100,26 +115,21 @@
 
 
 
-    public int size()
-    {
-      return 0;
-    }
-
-
-
-    public boolean contains(Object value) throws NullPointerException
-    {
-      return false;
-    }
-
-
-
-    public boolean remove(Object value)
+    @Override
+    public boolean remove(final Object value)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
     }
 
+
+
+    @Override
+    public int size()
+    {
+      return 0;
+    }
+
   }
 
 
@@ -136,8 +146,8 @@
 
 
 
-    private RenamedAttribute(Attribute attribute,
-        AttributeDescription attributeDescription)
+    private RenamedAttribute(final Attribute attribute,
+        final AttributeDescription attributeDescription)
     {
       this.attribute = attribute;
       this.attributeDescription = attributeDescription;
@@ -145,7 +155,7 @@
 
 
 
-    public boolean add(ByteString value)
+    public boolean add(final ByteString value)
         throws UnsupportedOperationException, NullPointerException
     {
       return attribute.add(value);
@@ -153,7 +163,7 @@
 
 
 
-    public boolean add(Object firstValue, Object... remainingValues)
+    public boolean add(final Object firstValue, final Object... remainingValues)
         throws UnsupportedOperationException, NullPointerException
     {
       return attribute.add(firstValue, remainingValues);
@@ -161,7 +171,7 @@
 
 
 
-    public boolean addAll(Collection<? extends ByteString> values)
+    public boolean addAll(final Collection<? extends ByteString> values)
         throws UnsupportedOperationException, NullPointerException
     {
       return attribute.addAll(values);
@@ -169,8 +179,8 @@
 
 
 
-    public boolean addAll(Collection<? extends ByteString> values,
-        Collection<? super ByteString> duplicateValues)
+    public boolean addAll(final Collection<? extends ByteString> values,
+        final Collection<? super ByteString> duplicateValues)
         throws UnsupportedOperationException, NullPointerException
     {
       return attribute.addAll(values, duplicateValues);
@@ -185,14 +195,14 @@
 
 
 
-    public boolean contains(Object value) throws NullPointerException
+    public boolean contains(final Object value) throws NullPointerException
     {
       return attribute.contains(value);
     }
 
 
 
-    public boolean containsAll(Collection<?> values)
+    public boolean containsAll(final Collection<?> values)
         throws NullPointerException
     {
       return attribute.containsAll(values);
@@ -200,7 +210,8 @@
 
 
 
-    public boolean equals(Object object)
+    @Override
+    public boolean equals(final Object object)
     {
       return AbstractAttribute.equals(this, object);
     }
@@ -235,6 +246,7 @@
 
 
 
+    @Override
     public int hashCode()
     {
       return AbstractAttribute.hashCode(this);
@@ -256,7 +268,7 @@
 
 
 
-    public boolean remove(Object value)
+    public boolean remove(final Object value)
         throws UnsupportedOperationException, NullPointerException
     {
       return attribute.remove(value);
@@ -264,7 +276,7 @@
 
 
 
-    public boolean removeAll(Collection<?> values)
+    public boolean removeAll(final Collection<?> values)
         throws UnsupportedOperationException, NullPointerException
     {
       return attribute.removeAll(values);
@@ -272,8 +284,8 @@
 
 
 
-    public <T> boolean removeAll(Collection<T> values,
-        Collection<? super T> missingValues)
+    public <T> boolean removeAll(final Collection<T> values,
+        final Collection<? super T> missingValues)
         throws UnsupportedOperationException, NullPointerException
     {
       return attribute.removeAll(values, missingValues);
@@ -281,7 +293,7 @@
 
 
 
-    public boolean retainAll(Collection<?> values)
+    public boolean retainAll(final Collection<?> values)
         throws UnsupportedOperationException, NullPointerException
     {
       return attribute.retainAll(values);
@@ -289,8 +301,8 @@
 
 
 
-    public <T> boolean retainAll(Collection<T> values,
-        Collection<? super T> missingValues)
+    public <T> boolean retainAll(final Collection<T> values,
+        final Collection<? super T> missingValues)
         throws UnsupportedOperationException, NullPointerException
     {
       return attribute.retainAll(values, missingValues);
@@ -312,7 +324,7 @@
 
 
 
-    public <T> T[] toArray(T[] array) throws ArrayStoreException,
+    public <T> T[] toArray(final T[] array) throws ArrayStoreException,
         NullPointerException
     {
       return attribute.toArray(array);
@@ -320,6 +332,7 @@
 
 
 
+    @Override
     public String toString()
     {
       return AbstractAttribute.toString(this);
@@ -339,14 +352,14 @@
 
 
 
-    private UnmodifiableAttribute(Attribute attribute)
+    private UnmodifiableAttribute(final Attribute attribute)
     {
       this.attribute = attribute;
     }
 
 
 
-    public boolean add(ByteString value)
+    public boolean add(final ByteString value)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -354,7 +367,7 @@
 
 
 
-    public boolean add(Object firstValue, Object... remainingValues)
+    public boolean add(final Object firstValue, final Object... remainingValues)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -362,7 +375,7 @@
 
 
 
-    public boolean addAll(Collection<? extends ByteString> values)
+    public boolean addAll(final Collection<? extends ByteString> values)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -370,8 +383,8 @@
 
 
 
-    public boolean addAll(Collection<? extends ByteString> values,
-        Collection<? super ByteString> duplicateValues)
+    public boolean addAll(final Collection<? extends ByteString> values,
+        final Collection<? super ByteString> duplicateValues)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -386,14 +399,14 @@
 
 
 
-    public boolean contains(Object value) throws NullPointerException
+    public boolean contains(final Object value) throws NullPointerException
     {
       return attribute.contains(value);
     }
 
 
 
-    public boolean containsAll(Collection<?> values)
+    public boolean containsAll(final Collection<?> values)
         throws NullPointerException
     {
       return attribute.containsAll(values);
@@ -401,7 +414,8 @@
 
 
 
-    public boolean equals(Object object)
+    @Override
+    public boolean equals(final Object object)
     {
       return (object == this || attribute.equals(object));
     }
@@ -436,6 +450,7 @@
 
 
 
+    @Override
     public int hashCode()
     {
       return attribute.hashCode();
@@ -457,7 +472,7 @@
 
 
 
-    public boolean remove(Object value)
+    public boolean remove(final Object value)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -465,7 +480,7 @@
 
 
 
-    public boolean removeAll(Collection<?> values)
+    public boolean removeAll(final Collection<?> values)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -473,8 +488,8 @@
 
 
 
-    public <T> boolean removeAll(Collection<T> values,
-        Collection<? super T> missingValues)
+    public <T> boolean removeAll(final Collection<T> values,
+        final Collection<? super T> missingValues)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -482,7 +497,7 @@
 
 
 
-    public boolean retainAll(Collection<?> values)
+    public boolean retainAll(final Collection<?> values)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -490,8 +505,8 @@
 
 
 
-    public <T> boolean retainAll(Collection<T> values,
-        Collection<? super T> missingValues)
+    public <T> boolean retainAll(final Collection<T> values,
+        final Collection<? super T> missingValues)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -513,7 +528,7 @@
 
 
 
-    public <T> T[] toArray(T[] array) throws ArrayStoreException,
+    public <T> T[] toArray(final T[] array) throws ArrayStoreException,
         NullPointerException
     {
       return attribute.toArray(array);
@@ -521,6 +536,7 @@
 
 
 
+    @Override
     public String toString()
     {
       return attribute.toString();
@@ -536,7 +552,7 @@
 
 
 
-    private UnmodifiableEntry(Entry entry)
+    private UnmodifiableEntry(final Entry entry)
     {
       this.entry = entry;
     }
@@ -546,8 +562,7 @@
     /**
      * {@inheritDoc}
      */
-    public boolean addAttribute(Attribute attribute,
-        Collection<ByteString> duplicateValues)
+    public boolean addAttribute(final Attribute attribute)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -558,7 +573,8 @@
     /**
      * {@inheritDoc}
      */
-    public boolean addAttribute(Attribute attribute)
+    public boolean addAttribute(final Attribute attribute,
+        final Collection<ByteString> duplicateValues)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -569,8 +585,8 @@
     /**
      * {@inheritDoc}
      */
-    public Entry addAttribute(String attributeDescription,
-        Object... values) throws LocalizedIllegalArgumentException,
+    public Entry addAttribute(final String attributeDescription,
+        final Object... values) throws LocalizedIllegalArgumentException,
         UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -585,10 +601,19 @@
 
 
 
-    public boolean containsAttribute(
-        AttributeDescription attributeDescription)
+    public boolean containsAttribute(final Attribute attribute,
+        final Collection<ByteString> missingValues) throws NullPointerException
     {
-      return entry.containsAttribute(attributeDescription);
+      return entry.containsAttribute(attribute, missingValues);
+    }
+
+
+
+    public boolean containsAttribute(final String attributeDescription,
+        final Object... values) throws LocalizedIllegalArgumentException,
+        NullPointerException
+    {
+      return entry.containsAttribute(attributeDescription, values);
     }
 
 
@@ -596,43 +621,27 @@
     /**
      * {@inheritDoc}
      */
-    public boolean containsAttribute(String attributeDescription)
-        throws LocalizedIllegalArgumentException, NullPointerException
-    {
-      return entry.containsAttribute(attributeDescription);
-    }
-
-
-
-    public boolean containsObjectClass(ObjectClass objectClass)
-    {
-      return entry.containsObjectClass(objectClass);
-    }
-
-
-
-    public boolean containsObjectClass(String objectClass)
-    {
-      return entry.containsObjectClass(objectClass);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean equals(Object object)
+    @Override
+    public boolean equals(final Object object)
     {
       return (object == this || entry.equals(object));
     }
 
 
 
-    public Iterable<Attribute> findAttributes(
-        AttributeDescription attributeDescription)
+    public Iterable<Attribute> getAllAttributes()
     {
       return Iterables.unmodifiable(Iterables.transform(entry
-          .findAttributes(attributeDescription),
+          .getAllAttributes(), UNMODIFIABLE_ATTRIBUTE_FUNCTION));
+    }
+
+
+
+    public Iterable<Attribute> getAllAttributes(
+        final AttributeDescription attributeDescription)
+    {
+      return Iterables.unmodifiable(Iterables.transform(entry
+          .getAllAttributes(attributeDescription),
           UNMODIFIABLE_ATTRIBUTE_FUNCTION));
     }
 
@@ -641,21 +650,21 @@
     /**
      * {@inheritDoc}
      */
-    public Iterable<Attribute> findAttributes(
-        String attributeDescription)
+    public Iterable<Attribute> getAllAttributes(
+        final String attributeDescription)
         throws LocalizedIllegalArgumentException, NullPointerException
     {
       return Iterables.unmodifiable(Iterables.transform(entry
-          .findAttributes(attributeDescription),
+          .getAllAttributes(attributeDescription),
           UNMODIFIABLE_ATTRIBUTE_FUNCTION));
     }
 
 
 
     public Attribute getAttribute(
-        AttributeDescription attributeDescription)
+        final AttributeDescription attributeDescription)
     {
-      Attribute attribute = entry.getAttribute(attributeDescription);
+      final Attribute attribute = entry.getAttribute(attributeDescription);
       if (attribute != null)
       {
         return unmodifiableAttribute(attribute);
@@ -671,10 +680,10 @@
     /**
      * {@inheritDoc}
      */
-    public Attribute getAttribute(String attributeDescription)
+    public Attribute getAttribute(final String attributeDescription)
         throws LocalizedIllegalArgumentException, NullPointerException
     {
-      Attribute attribute = entry.getAttribute(attributeDescription);
+      final Attribute attribute = entry.getAttribute(attributeDescription);
       if (attribute != null)
       {
         return unmodifiableAttribute(attribute);
@@ -694,14 +703,6 @@
 
 
 
-    public Iterable<Attribute> getAttributes()
-    {
-      return Iterables.unmodifiable(Iterables.transform(entry
-          .getAttributes(), UNMODIFIABLE_ATTRIBUTE_FUNCTION));
-    }
-
-
-
     /**
      * {@inheritDoc}
      */
@@ -712,16 +713,10 @@
 
 
 
-    public Iterable<String> getObjectClasses()
-    {
-      return Iterables.unmodifiable(entry.getObjectClasses());
-    }
-
-
-
     /**
      * {@inheritDoc}
      */
+    @Override
     public int hashCode()
     {
       return entry.hashCode();
@@ -732,8 +727,8 @@
     /**
      * {@inheritDoc}
      */
-    public boolean removeAttribute(Attribute attribute,
-        Collection<ByteString> missingValues)
+    public boolean removeAttribute(final Attribute attribute,
+        final Collection<ByteString> missingValues)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -742,7 +737,7 @@
 
 
     public boolean removeAttribute(
-        AttributeDescription attributeDescription)
+        final AttributeDescription attributeDescription)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -753,8 +748,8 @@
     /**
      * {@inheritDoc}
      */
-    public Entry removeAttribute(String attributeDescription)
-        throws LocalizedIllegalArgumentException,
+    public Entry removeAttribute(final String attributeDescription,
+        final Object... values) throws LocalizedIllegalArgumentException,
         UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -765,19 +760,7 @@
     /**
      * {@inheritDoc}
      */
-    public Entry removeAttribute(String attributeDescription,
-        Object... values) throws LocalizedIllegalArgumentException,
-        UnsupportedOperationException, NullPointerException
-    {
-      throw new UnsupportedOperationException();
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public boolean replaceAttribute(Attribute attribute)
+    public boolean replaceAttribute(final Attribute attribute)
         throws UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -788,8 +771,8 @@
     /**
      * {@inheritDoc}
      */
-    public Entry replaceAttribute(String attributeDescription,
-        Object... values) throws LocalizedIllegalArgumentException,
+    public Entry replaceAttribute(final String attributeDescription,
+        final Object... values) throws LocalizedIllegalArgumentException,
         UnsupportedOperationException, NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -797,19 +780,7 @@
 
 
 
-    /**
-     * {@inheritDoc}
-     */
-    public Entry setName(String dn)
-        throws LocalizedIllegalArgumentException,
-        UnsupportedOperationException, NullPointerException
-    {
-      throw new UnsupportedOperationException();
-    }
-
-
-
-    public Entry setName(DN dn) throws UnsupportedOperationException,
+    public Entry setName(final DN dn) throws UnsupportedOperationException,
         NullPointerException
     {
       throw new UnsupportedOperationException();
@@ -820,6 +791,19 @@
     /**
      * {@inheritDoc}
      */
+    public Entry setName(final String dn)
+        throws LocalizedIllegalArgumentException,
+        UnsupportedOperationException, NullPointerException
+    {
+      throw new UnsupportedOperationException();
+    }
+
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
     public String toString()
     {
       return entry.toString();
@@ -829,10 +813,11 @@
 
 
 
-  private static final Function<Attribute, Attribute, Void> UNMODIFIABLE_ATTRIBUTE_FUNCTION = new Function<Attribute, Attribute, Void>()
+  private static final Function<Attribute, Attribute, Void>
+    UNMODIFIABLE_ATTRIBUTE_FUNCTION = new Function<Attribute, Attribute, Void>()
   {
 
-    public Attribute apply(Attribute value, Void p)
+    public Attribute apply(final Attribute value, final Void p)
     {
       return unmodifiableAttribute(value);
     }
@@ -852,7 +837,7 @@
    *           If {@code attributeDescription} was {@code null}.
    */
   public static final Attribute emptyAttribute(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
       throws NullPointerException
   {
     return new EmptyAttribute(attributeDescription);
@@ -862,31 +847,29 @@
 
   /**
    * Returns a view of {@code attribute} having a different attribute
-   * description. All operations on the returned attribute
-   * "pass-through" to the underlying attribute.
+   * description. All operations on the returned attribute "pass-through" to the
+   * underlying attribute.
    *
    * @param attribute
    *          The attribute to be renamed.
    * @param attributeDescription
-   *          The new attribute description for {@code attribute}, which
-   *          must be compatible with {@code attribute}'s attribute
-   *          description.
+   *          The new attribute description for {@code attribute}, which must be
+   *          compatible with {@code attribute}'s attribute description.
    * @return A renamed view of {@code attribute}.
    * @throws IllegalArgumentException
-   *           If {@code attributeDescription} does not have the same
-   *           attribute type as {@code attribute}'s attribute
-   *           description.
+   *           If {@code attributeDescription} does not have the same attribute
+   *           type as {@code attribute}'s attribute description.
    * @throws NullPointerException
-   *           If {@code attribute} or {@code attributeDescription} was
-   *           {@code null}.
+   *           If {@code attribute} or {@code attributeDescription} was {@code
+   *           null}.
    */
-  public static final Attribute renameAttribute(Attribute attribute,
-      AttributeDescription attributeDescription)
+  public static final Attribute renameAttribute(final Attribute attribute,
+      final AttributeDescription attributeDescription)
       throws IllegalArgumentException, NullPointerException
   {
-    AttributeType oldType = attribute.getAttributeDescription()
+    final AttributeType oldType = attribute.getAttributeDescription()
         .getAttributeType();
-    AttributeType newType = attributeDescription.getAttributeType();
+    final AttributeType newType = attributeDescription.getAttributeType();
 
     // We could relax a bit by ensuring that they are both compatible
     // (e.g. one sub-type of another, or same equality matching rule,
@@ -900,21 +883,19 @@
 
 
   /**
-   * Returns a read-only view of {@code attribute}. Query operations on
-   * the returned attribute "read-through" to the underlying attribute,
-   * and attempts to modify the returned attribute either directly or
-   * indirectly via an iterator result in an {@code
-   * UnsupportedOperationException}.
+   * Returns a read-only view of {@code attribute}. Query operations on the
+   * returned attribute "read-through" to the underlying attribute, and attempts
+   * to modify the returned attribute either directly or indirectly via an
+   * iterator result in an {@code UnsupportedOperationException}.
    *
    * @param attribute
-   *          The attribute for which a read-only view is to be
-   *          returned.
+   *          The attribute for which a read-only view is to be returned.
    * @return A read-only view of {@code attribute}.
    * @throws NullPointerException
    *           If {@code attribute} was {@code null}.
    */
-  public static final Attribute unmodifiableAttribute(
-      Attribute attribute) throws NullPointerException
+  public static final Attribute unmodifiableAttribute(final Attribute attribute)
+      throws NullPointerException
   {
     return new UnmodifiableAttribute(attribute);
   }
@@ -923,10 +904,10 @@
 
   /**
    * Returns a read-only view of {@code entry} and its attributes. Query
-   * operations on the returned entry and its attributes"read-through"
-   * to the underlying entry or attribute, and attempts to modify the
-   * returned entry and its attributes either directly or indirectly via
-   * an iterator result in an {@code UnsupportedOperationException}.
+   * operations on the returned entry and its attributes"read-through" to the
+   * underlying entry or attribute, and attempts to modify the returned entry
+   * and its attributes either directly or indirectly via an iterator result in
+   * an {@code UnsupportedOperationException}.
    *
    * @param entry
    *          The entry for which a read-only view is to be returned.
@@ -934,7 +915,7 @@
    * @throws NullPointerException
    *           If {@code entry} was {@code null}.
    */
-  public static final Entry unmodifiableEntry(Entry entry)
+  public static final Entry unmodifiableEntry(final Entry entry)
       throws NullPointerException
   {
     return new UnmodifiableEntry(entry);
diff --git a/sdk/src/org/opends/sdk/asn1/ASN1.java b/sdk/src/org/opends/sdk/asn1/ASN1.java
index 231e520..df5c477 100644
--- a/sdk/src/org/opends/sdk/asn1/ASN1.java
+++ b/sdk/src/org/opends/sdk/asn1/ASN1.java
@@ -40,9 +40,10 @@
 import com.sun.opends.sdk.util.ByteSequenceOutputStream;
 
 
+
 /**
- * This class contains various static factory methods for creating ASN.1
- * readers and writers.
+ * This class contains various static factory methods for creating ASN.1 readers
+ * and writers.
  *
  * @see ASN1Reader
  * @see ASN1Writer
@@ -51,14 +52,14 @@
 {
 
   /**
-   * Returns an ASN.1 reader whose source is the provided byte array and
-   * having an unlimited maximum BER element size.
+   * Returns an ASN.1 reader whose source is the provided byte array and having
+   * an unlimited maximum BER element size.
    *
    * @param array
    *          The byte array to use.
    * @return The new ASN.1 reader.
    */
-  public static ASN1Reader getReader(byte[] array)
+  public static ASN1Reader getReader(final byte[] array)
   {
     return getReader(array, 0);
   }
@@ -66,17 +67,18 @@
 
 
   /**
-   * Returns an ASN.1 reader whose source is the provided byte array and
-   * having a user defined maximum BER element size.
+   * Returns an ASN.1 reader whose source is the provided byte array and having
+   * a user defined maximum BER element size.
    *
    * @param array
    *          The byte array to use.
    * @param maxElementSize
-   *          The maximum BER element size, or {@code 0} to indicate
-   *          that there is no limit.
+   *          The maximum BER element size, or {@code 0} to indicate that there
+   *          is no limit.
    * @return The new ASN.1 reader.
    */
-  public static ASN1Reader getReader(byte[] array, int maxElementSize)
+  public static ASN1Reader getReader(final byte[] array,
+      final int maxElementSize)
   {
     return getReader(ByteString.wrap(array), maxElementSize);
   }
@@ -84,14 +86,14 @@
 
 
   /**
-   * Returns an ASN.1 reader whose source is the provided byte sequence
-   * and having an unlimited maximum BER element size.
+   * Returns an ASN.1 reader whose source is the provided byte sequence and
+   * having an unlimited maximum BER element size.
    *
    * @param sequence
    *          The byte sequence to use.
    * @return The new ASN.1 reader.
    */
-  public static ASN1Reader getReader(ByteSequence sequence)
+  public static ASN1Reader getReader(final ByteSequence sequence)
   {
     return getReader(sequence, 0);
   }
@@ -99,34 +101,33 @@
 
 
   /**
-   * Returns an ASN.1 reader whose source is the provided byte sequence
-   * and having a user defined maximum BER element size.
+   * Returns an ASN.1 reader whose source is the provided byte sequence and
+   * having a user defined maximum BER element size.
    *
    * @param sequence
    *          The byte sequence to use.
    * @param maxElementSize
-   *          The maximum BER element size, or {@code 0} to indicate
-   *          that there is no limit.
+   *          The maximum BER element size, or {@code 0} to indicate that there
+   *          is no limit.
    * @return The new ASN.1 reader.
    */
-  public static ASN1Reader getReader(ByteSequence sequence,
-      int maxElementSize)
+  public static ASN1Reader getReader(final ByteSequence sequence,
+      final int maxElementSize)
   {
-    return new ASN1ByteSequenceReader(sequence.asReader(),
-        maxElementSize);
+    return new ASN1ByteSequenceReader(sequence.asReader(), maxElementSize);
   }
 
 
 
   /**
-   * Returns an ASN.1 reader whose source is the provided byte sequence
-   * reader and having an unlimited maximum BER element size.
+   * Returns an ASN.1 reader whose source is the provided byte sequence reader
+   * and having an unlimited maximum BER element size.
    *
    * @param reader
    *          The byte sequence reader to use.
    * @return The new ASN.1 reader.
    */
-  public static ASN1Reader getReader(ByteSequenceReader reader)
+  public static ASN1Reader getReader(final ByteSequenceReader reader)
   {
     return getReader(reader, 0);
   }
@@ -134,18 +135,18 @@
 
 
   /**
-   * Returns an ASN.1 reader whose source is the provided byte sequence
-   * reader and having a user defined maximum BER element size.
+   * Returns an ASN.1 reader whose source is the provided byte sequence reader
+   * and having a user defined maximum BER element size.
    *
    * @param reader
    *          The byte sequence reader to use.
    * @param maxElementSize
-   *          The maximum BER element size, or {@code 0} to indicate
-   *          that there is no limit.
+   *          The maximum BER element size, or {@code 0} to indicate that there
+   *          is no limit.
    * @return The new ASN.1 reader.
    */
-  public static ASN1Reader getReader(ByteSequenceReader reader,
-      int maxElementSize)
+  public static ASN1Reader getReader(final ByteSequenceReader reader,
+      final int maxElementSize)
   {
     return new ASN1ByteSequenceReader(reader, maxElementSize);
   }
@@ -153,14 +154,14 @@
 
 
   /**
-   * Returns an ASN.1 reader whose source is the provided input stream
-   * and having an unlimited maximum BER element size.
+   * Returns an ASN.1 reader whose source is the provided input stream and
+   * having an unlimited maximum BER element size.
    *
    * @param stream
    *          The input stream to use.
    * @return The new ASN.1 reader.
    */
-  public static ASN1Reader getReader(InputStream stream)
+  public static ASN1Reader getReader(final InputStream stream)
   {
     return getReader(stream, 0);
   }
@@ -168,18 +169,18 @@
 
 
   /**
-   * Returns an ASN.1 reader whose source is the provided input stream
-   * and having a user defined maximum BER element size.
+   * Returns an ASN.1 reader whose source is the provided input stream and
+   * having a user defined maximum BER element size.
    *
    * @param stream
    *          The input stream to use.
    * @param maxElementSize
-   *          The maximum BER element size, or {@code 0} to indicate
-   *          that there is no limit.
+   *          The maximum BER element size, or {@code 0} to indicate that there
+   *          is no limit.
    * @return The new ASN.1 reader.
    */
-  public static ASN1Reader getReader(InputStream stream,
-      int maxElementSize)
+  public static ASN1Reader getReader(final InputStream stream,
+      final int maxElementSize)
   {
     return new ASN1InputStreamReader(stream, maxElementSize);
   }
@@ -187,31 +188,30 @@
 
 
   /**
-   * Returns an ASN.1 writer whose destination is the provided byte
-   * string builder.
+   * Returns an ASN.1 writer whose destination is the provided byte string
+   * builder.
    *
    * @param builder
    *          The byte string builder to use.
    * @return The new ASN.1 writer.
    */
-  public static ASN1Writer getWriter(ByteStringBuilder builder)
+  public static ASN1Writer getWriter(final ByteStringBuilder builder)
   {
-    ByteSequenceOutputStream outputStream =
-        new ByteSequenceOutputStream(builder);
+    final ByteSequenceOutputStream outputStream = new ByteSequenceOutputStream(
+        builder);
     return getWriter(outputStream);
   }
 
 
 
   /**
-   * Returns an ASN.1 writer whose destination is the provided output
-   * stream.
+   * Returns an ASN.1 writer whose destination is the provided output stream.
    *
    * @param stream
    *          The output stream to use.
    * @return The new ASN.1 writer.
    */
-  public static ASN1Writer getWriter(OutputStream stream)
+  public static ASN1Writer getWriter(final OutputStream stream)
   {
     return new ASN1OutputStreamWriter(stream);
   }
diff --git a/sdk/src/org/opends/sdk/asn1/ASN1ByteSequenceReader.java b/sdk/src/org/opends/sdk/asn1/ASN1ByteSequenceReader.java
index e0dd0a6..612d101 100644
--- a/sdk/src/org/opends/sdk/asn1/ASN1ByteSequenceReader.java
+++ b/sdk/src/org/opends/sdk/asn1/ASN1ByteSequenceReader.java
@@ -30,7 +30,9 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.asn1.ASN1Constants.*;
+import static org.opends.sdk.asn1.ASN1Constants.ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
+import static org.opends.sdk.asn1.ASN1Constants.ELEMENT_READ_STATE_NEED_TYPE;
+import static org.opends.sdk.asn1.ASN1Constants.ELEMENT_READ_STATE_NEED_VALUE_BYTES;
 
 import java.io.IOException;
 import java.util.LinkedList;
@@ -64,16 +66,17 @@
 
 
   /**
-   * Creates a new ASN1 reader whose source is the provided byte
-   * sequence reader and having a user defined maximum BER element size.
+   * Creates a new ASN1 reader whose source is the provided byte sequence reader
+   * and having a user defined maximum BER element size.
    *
    * @param reader
    *          The byte sequence reader to be read.
    * @param maxElementSize
-   *          The maximum BER element size, or <code>0</code> to
-   *          indicate that there is no limit.
+   *          The maximum BER element size, or <code>0</code> to indicate that
+   *          there is no limit.
    */
-  ASN1ByteSequenceReader(ByteSequenceReader reader, int maxElementSize)
+  ASN1ByteSequenceReader(final ByteSequenceReader reader,
+      final int maxElementSize)
   {
     this.reader = reader;
     this.readerStack = new LinkedList<ByteSequenceReader>();
@@ -97,8 +100,7 @@
    */
   public boolean elementAvailable() throws IOException
   {
-    if ((state == ELEMENT_READ_STATE_NEED_TYPE)
-        && !needTypeState(false))
+    if ((state == ELEMENT_READ_STATE_NEED_TYPE) && !needTypeState(false))
     {
       return false;
     }
@@ -118,8 +120,7 @@
    */
   public boolean hasNextElement() throws IOException
   {
-    return (state != ELEMENT_READ_STATE_NEED_TYPE)
-        || needTypeState(false);
+    return (state != ELEMENT_READ_STATE_NEED_TYPE) || needTypeState(false);
   }
 
 
@@ -151,10 +152,10 @@
       // Read just the type.
       if (reader.remaining() <= 0)
       {
-        LocalizableMessage message = ERR_ASN1_TRUCATED_TYPE_BYTE.get();
+        final LocalizableMessage message = ERR_ASN1_TRUCATED_TYPE_BYTE.get();
         throw DecodeException.fatalError(message);
       }
-      int type = reader.get();
+      final int type = reader.get();
 
       peekType = (byte) type;
       state = ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
@@ -175,17 +176,18 @@
 
     if (peekLength != 1)
     {
-      LocalizableMessage message = ERR_ASN1_BOOLEAN_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_BOOLEAN_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
     if (reader.remaining() < peekLength)
     {
-      LocalizableMessage message = ERR_ASN1_BOOLEAN_TRUNCATED_VALUE
+      final LocalizableMessage message = ERR_ASN1_BOOLEAN_TRUNCATED_VALUE
           .get(peekLength);
       throw DecodeException.fatalError(message);
     }
-    int readByte = reader.get();
+    final int readByte = reader.get();
 
     state = ELEMENT_READ_STATE_NEED_TYPE;
     return readByte != 0x00;
@@ -196,12 +198,12 @@
   /**
    * {@inheritDoc}
    */
-  public void readEndSequence() throws IOException,
-      IllegalStateException
+  public void readEndSequence() throws IOException, IllegalStateException
   {
     if (readerStack.isEmpty())
     {
-      LocalizableMessage message = ERR_ASN1_SEQUENCE_READ_NOT_STARTED.get();
+      final LocalizableMessage message = ERR_ASN1_SEQUENCE_READ_NOT_STARTED
+          .get();
       throw new IllegalStateException(message.toString());
     }
 
@@ -242,7 +244,8 @@
 
     if ((peekLength < 1) || (peekLength > 4))
     {
-      LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
@@ -263,13 +266,14 @@
 
     if ((peekLength < 1) || (peekLength > 8))
     {
-      LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
     if (reader.remaining() < peekLength)
     {
-      LocalizableMessage message = ERR_ASN1_INTEGER_TRUNCATED_VALUE
+      final LocalizableMessage message = ERR_ASN1_INTEGER_TRUNCATED_VALUE
           .get(peekLength);
       throw DecodeException.fatalError(message);
     }
@@ -278,7 +282,7 @@
       long longValue = 0;
       for (int i = 0; i < peekLength; i++)
       {
-        int readByte = reader.get();
+        final int readByte = reader.get();
         if ((i == 0) && (readByte < 0))
         {
           longValue = 0xFFFFFFFFFFFFFFFFL;
@@ -294,7 +298,7 @@
       int intValue = 0;
       for (int i = 0; i < peekLength; i++)
       {
-        int readByte = reader.get();
+        final int readByte = reader.get();
         if ((i == 0) && (readByte < 0))
         {
           intValue = 0xFFFFFFFF;
@@ -320,7 +324,8 @@
     // Make sure that the decoded length is exactly zero byte.
     if (peekLength != 0)
     {
-      LocalizableMessage message = ERR_ASN1_NULL_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_NULL_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
@@ -339,7 +344,7 @@
 
     if (reader.remaining() < peekLength)
     {
-      LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
+      final LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
           .get(peekLength);
       throw DecodeException.fatalError(message);
     }
@@ -353,7 +358,7 @@
   /**
    * {@inheritDoc}
    */
-  public ByteStringBuilder readOctetString(ByteStringBuilder builder)
+  public ByteStringBuilder readOctetString(final ByteStringBuilder builder)
       throws IOException
   {
     // Read the header if haven't done so already
@@ -362,7 +367,7 @@
     // Copy the value.
     if (reader.remaining() < peekLength)
     {
-      LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
+      final LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
           .get(peekLength);
       throw DecodeException.fatalError(message);
     }
@@ -384,7 +389,7 @@
 
     if (reader.remaining() < peekLength)
     {
-      LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
+      final LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
           .get(peekLength);
       throw DecodeException.fatalError(message);
     }
@@ -405,13 +410,13 @@
 
     if (reader.remaining() < peekLength)
     {
-      LocalizableMessage message = ERR_ASN1_SEQUENCE_SET_TRUNCATED_VALUE
+      final LocalizableMessage message = ERR_ASN1_SEQUENCE_SET_TRUNCATED_VALUE
           .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
-    ByteSequenceReader subByteString = reader.getByteSequence(
-        peekLength).asReader();
+    final ByteSequenceReader subByteString = reader.getByteSequence(peekLength)
+        .asReader();
     readerStack.addFirst(reader);
     reader = subByteString;
 
@@ -443,7 +448,8 @@
 
     if (reader.remaining() < peekLength)
     {
-      LocalizableMessage message = ERR_ASN1_SKIP_TRUNCATED_VALUE.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_SKIP_TRUNCATED_VALUE
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
@@ -455,25 +461,24 @@
 
 
   /**
-   * Internal helper method reading the first length bytes and
-   * transition to the next state if successful.
+   * Internal helper method reading the first length bytes and transition to the
+   * next state if successful.
    *
    * @param throwEofException
-   *          <code>true</code> to throw an exception when the end of
-   *          the sequence is encountered.
+   *          <code>true</code> to throw an exception when the end of the
+   *          sequence is encountered.
    * @return <code>true</code> if the length bytes was successfully read
    * @throws IOException
-   *           If an error occurs while trying to decode an ASN1
-   *           element.
+   *           If an error occurs while trying to decode an ASN1 element.
    */
-  private boolean needFirstLengthByteState(boolean throwEofException)
+  private boolean needFirstLengthByteState(final boolean throwEofException)
       throws IOException
   {
     if (reader.remaining() <= 0)
     {
       if (throwEofException)
       {
-        LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTE.get();
+        final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTE.get();
         throw DecodeException.fatalError(message);
       }
       return false;
@@ -485,7 +490,7 @@
       int lengthBytesNeeded = peekLength;
       if (lengthBytesNeeded > 4)
       {
-        LocalizableMessage message = ERR_ASN1_INVALID_NUM_LENGTH_BYTES
+        final LocalizableMessage message = ERR_ASN1_INVALID_NUM_LENGTH_BYTES
             .get(lengthBytesNeeded);
         throw DecodeException.fatalError(message);
       }
@@ -495,7 +500,7 @@
       {
         if (throwEofException)
         {
-          LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTES
+          final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTES
               .get(lengthBytesNeeded);
           throw DecodeException.fatalError(message);
         }
@@ -514,7 +519,7 @@
     // message size.
     if ((maxElementSize > 0) && (peekLength > maxElementSize))
     {
-      LocalizableMessage message = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
+      final LocalizableMessage message = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
           .get(peekLength, maxElementSize);
       throw DecodeException.fatalError(message);
     }
@@ -525,18 +530,17 @@
 
 
   /**
-   * Internal helper method reading the ASN.1 type byte and transition
-   * to the next state if successful.
+   * Internal helper method reading the ASN.1 type byte and transition to the
+   * next state if successful.
    *
    * @param throwEofException
-   *          <code>true</code> to throw an exception when the end of
-   *          the sequence is encountered.
+   *          <code>true</code> to throw an exception when the end of the
+   *          sequence is encountered.
    * @return <code>true</code> if the type byte was successfully read
    * @throws IOException
-   *           If an error occurs while trying to decode an ASN1
-   *           element.
+   *           If an error occurs while trying to decode an ASN1 element.
    */
-  private boolean needTypeState(boolean throwEofException)
+  private boolean needTypeState(final boolean throwEofException)
       throws IOException
   {
     // Read just the type.
@@ -544,12 +548,12 @@
     {
       if (throwEofException)
       {
-        LocalizableMessage message = ERR_ASN1_TRUCATED_TYPE_BYTE.get();
+        final LocalizableMessage message = ERR_ASN1_TRUCATED_TYPE_BYTE.get();
         throw DecodeException.fatalError(message);
       }
       return false;
     }
-    int type = reader.get();
+    final int type = reader.get();
 
     peekType = (byte) type;
     state = ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
diff --git a/sdk/src/org/opends/sdk/asn1/ASN1Constants.java b/sdk/src/org/opends/sdk/asn1/ASN1Constants.java
index 63d37fd..c70ace7 100644
--- a/sdk/src/org/opends/sdk/asn1/ASN1Constants.java
+++ b/sdk/src/org/opends/sdk/asn1/ASN1Constants.java
@@ -29,39 +29,33 @@
 
 
 /**
- * This class defines a number of constants that may be used when
- * interacting with ASN.1 elements.
+ * This class defines a number of constants that may be used when interacting
+ * with ASN.1 elements.
  */
 public final class ASN1Constants
 {
 
-  // Prevent instantiation.
-  private ASN1Constants()
-  {
-    // Nothing to do.
-  }
-
   /**
-   * The ASN.1 element decoding state that indicates that the next byte
-   * read should be the BER type for a new element.
+   * The ASN.1 element decoding state that indicates that the next byte read
+   * should be the BER type for a new element.
    */
   static final int ELEMENT_READ_STATE_NEED_TYPE = 0;
 
   /**
-   * The ASN.1 element decoding state that indicates that the next byte
-   * read should be the first byte for the element length.
+   * The ASN.1 element decoding state that indicates that the next byte read
+   * should be the first byte for the element length.
    */
   static final int ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE = 1;
 
   /**
-   * The ASN.1 element decoding state that indicates that the next byte
-   * read should be additional bytes of a multi-byte length.
+   * The ASN.1 element decoding state that indicates that the next byte read
+   * should be additional bytes of a multi-byte length.
    */
   static final int ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES = 2;
 
   /**
-   * The ASN.1 element decoding state that indicates that the next byte
-   * read should be applied to the value of the element.
+   * The ASN.1 element decoding state that indicates that the next byte read
+   * should be applied to the value of the element.
    */
   static final int ELEMENT_READ_STATE_NEED_VALUE_BYTES = 3;
 
@@ -106,62 +100,70 @@
   static final byte[] NO_VALUE = new byte[0];
 
   /**
-   * The bitmask that can be ANDed with the BER type to zero out all
-   * bits except those used in the class.
+   * The bitmask that can be ANDed with the BER type to zero out all bits except
+   * those used in the class.
    */
   static final byte TYPE_MASK_ALL_BUT_CLASS = (byte) 0xC0;
 
   /**
-   * The bitmask that can be ANDed with the BER type to determine if the
-   * element is in the universal class.
+   * The bitmask that can be ANDed with the BER type to determine if the element
+   * is in the universal class.
    */
   static final byte TYPE_MASK_UNIVERSAL = 0x00;
 
   /**
-   * The bitmask that can be ANDed with the BER type to determine if the
-   * element is in the application-specific class.
+   * The bitmask that can be ANDed with the BER type to determine if the element
+   * is in the application-specific class.
    */
   static final byte TYPE_MASK_APPLICATION = 0x40;
 
   /**
-   * The bitmask that can be ANDed with the BER type to determine if the
-   * element is in the context-specific class.
+   * The bitmask that can be ANDed with the BER type to determine if the element
+   * is in the context-specific class.
    */
   static final byte TYPE_MASK_CONTEXT = (byte) 0x80;
 
   /**
-   * The bitmask that can be ANDed with the BER type to determine if the
-   * element is in the private class.
+   * The bitmask that can be ANDed with the BER type to determine if the element
+   * is in the private class.
    */
   static final byte TYPE_MASK_PRIVATE = (byte) 0xC0;
 
   /**
-   * The bitmask that can be ANDed with the BER type to zero out all
-   * bits except the primitive/constructed bit.
+   * The bitmask that can be ANDed with the BER type to zero out all bits except
+   * the primitive/constructed bit.
    */
   static final byte TYPE_MASK_ALL_BUT_PC = (byte) 0x20;
 
   /**
-   * The bitmask that can be ANDed with the BER type to determine if the
-   * element is a primitive.
+   * The bitmask that can be ANDed with the BER type to determine if the element
+   * is a primitive.
    */
   static final byte TYPE_MASK_PRIMITIVE = 0x00;
 
   /**
-   * The bitmask that can be ANDed with the BER type to determine if the
-   * element is constructed.
+   * The bitmask that can be ANDed with the BER type to determine if the element
+   * is constructed.
    */
   static final byte TYPE_MASK_CONSTRUCTED = 0x20;
 
   /**
-   * The byte array containing the pre-encoded ASN.1 encoding for a
-   * boolean value of "false".
+   * The byte array containing the pre-encoded ASN.1 encoding for a boolean
+   * value of "false".
    */
   public static final byte BOOLEAN_VALUE_FALSE = 0x00;
 
   /**
-   * The byte array containing the pre-encoded ASN.1 encoding for a
-   * boolean value of "false".
+   * The byte array containing the pre-encoded ASN.1 encoding for a boolean
+   * value of "false".
    */
   public static final byte BOOLEAN_VALUE_TRUE = (byte) 0xFF;
+
+
+
+  // Prevent instantiation.
+  private ASN1Constants()
+  {
+    // Nothing to do.
+  }
 }
diff --git a/sdk/src/org/opends/sdk/asn1/ASN1InputStreamReader.java b/sdk/src/org/opends/sdk/asn1/ASN1InputStreamReader.java
index 25e57a6..919b4ba 100644
--- a/sdk/src/org/opends/sdk/asn1/ASN1InputStreamReader.java
+++ b/sdk/src/org/opends/sdk/asn1/ASN1InputStreamReader.java
@@ -30,7 +30,10 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.asn1.ASN1Constants.*;
+import static org.opends.sdk.asn1.ASN1Constants.ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES;
+import static org.opends.sdk.asn1.ASN1Constants.ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE;
+import static org.opends.sdk.asn1.ASN1Constants.ELEMENT_READ_STATE_NEED_TYPE;
+import static org.opends.sdk.asn1.ASN1Constants.ELEMENT_READ_STATE_NEED_VALUE_BYTES;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -72,16 +75,16 @@
 
 
   /**
-   * Creates a new ASN1 reader whose source is the provided input stream
-   * and having a user defined maximum BER element size.
+   * Creates a new ASN1 reader whose source is the provided input stream and
+   * having a user defined maximum BER element size.
    *
    * @param stream
    *          The input stream to be read.
    * @param maxElementSize
-   *          The maximum BER element size, or <code>0</code> to
-   *          indicate that there is no limit.
+   *          The maximum BER element size, or <code>0</code> to indicate that
+   *          there is no limit.
    */
-  ASN1InputStreamReader(InputStream stream, int maxElementSize)
+  ASN1InputStreamReader(final InputStream stream, final int maxElementSize)
   {
     this.in = stream;
     this.streamStack = new LinkedList<InputStream>();
@@ -109,8 +112,7 @@
    */
   public boolean elementAvailable() throws IOException
   {
-    if ((state == ELEMENT_READ_STATE_NEED_TYPE)
-        && !needTypeState(false, false))
+    if ((state == ELEMENT_READ_STATE_NEED_TYPE) && !needTypeState(false, false))
     {
       return false;
     }
@@ -140,7 +142,7 @@
       // We are reading a sub sequence. Return true as long as we
       // haven't exhausted the size limit for the sub sequence sub input
       // stream.
-      SizeLimitInputStream subSq = (SizeLimitInputStream) in;
+      final SizeLimitInputStream subSq = (SizeLimitInputStream) in;
       return (subSq.getSizeLimit() - subSq.getBytesRead() > 0);
     }
 
@@ -197,14 +199,15 @@
 
     if (peekLength != 1)
     {
-      LocalizableMessage message = ERR_ASN1_BOOLEAN_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_BOOLEAN_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
-    int readByte = in.read();
+    final int readByte = in.read();
     if (readByte == -1)
     {
-      LocalizableMessage message = ERR_ASN1_BOOLEAN_TRUNCATED_VALUE
+      final LocalizableMessage message = ERR_ASN1_BOOLEAN_TRUNCATED_VALUE
           .get(peekLength);
       throw DecodeException.fatalError(message);
     }
@@ -212,8 +215,8 @@
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)",
-          peekType, peekLength, String.valueOf(readByte != 0x00)));
+          "READ ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)", peekType,
+          peekLength, String.valueOf(readByte != 0x00)));
     }
 
     state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -225,34 +228,33 @@
   /**
    * {@inheritDoc}
    */
-  public void readEndSequence() throws IOException,
-      IllegalStateException
+  public void readEndSequence() throws IOException, IllegalStateException
   {
     if (streamStack.isEmpty())
     {
-      LocalizableMessage message = ERR_ASN1_SEQUENCE_READ_NOT_STARTED.get();
+      final LocalizableMessage message = ERR_ASN1_SEQUENCE_READ_NOT_STARTED
+          .get();
       throw new IllegalStateException(message.toString());
     }
 
     // Ignore all unused trailing components.
-    SizeLimitInputStream subSq = (SizeLimitInputStream) in;
+    final SizeLimitInputStream subSq = (SizeLimitInputStream) in;
     if (subSq.getSizeLimit() - subSq.getBytesRead() > 0)
     {
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINE))
       {
         StaticUtils.DEBUG_LOG.fine(String.format(
-            "Ignoring %d unused trailing bytes in ASN.1 SEQUENCE",
-            subSq.getSizeLimit() - subSq.getBytesRead()));
+            "Ignoring %d unused trailing bytes in ASN.1 SEQUENCE", subSq
+                .getSizeLimit()
+                - subSq.getBytesRead()));
       }
 
       subSq.skip(subSq.getSizeLimit() - subSq.getBytesRead());
-
     }
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String
-          .format("READ ASN.1 END SEQUENCE"));
+      StaticUtils.DEBUG_LOG.finest(String.format("READ ASN.1 END SEQUENCE"));
     }
 
     in = streamStack.removeFirst();
@@ -285,7 +287,8 @@
 
     if ((peekLength < 1) || (peekLength > 4))
     {
-      LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
@@ -306,7 +309,8 @@
 
     if ((peekLength < 1) || (peekLength > 8))
     {
-      LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_INTEGER_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
@@ -315,10 +319,10 @@
       long longValue = 0;
       for (int i = 0; i < peekLength; i++)
       {
-        int readByte = in.read();
+        final int readByte = in.read();
         if (readByte == -1)
         {
-          LocalizableMessage message = ERR_ASN1_INTEGER_TRUNCATED_VALUE
+          final LocalizableMessage message = ERR_ASN1_INTEGER_TRUNCATED_VALUE
               .get(peekLength);
           throw DecodeException.fatalError(message);
         }
@@ -337,10 +341,10 @@
       int intValue = 0;
       for (int i = 0; i < peekLength; i++)
       {
-        int readByte = in.read();
+        final int readByte = in.read();
         if (readByte == -1)
         {
-          LocalizableMessage message = ERR_ASN1_INTEGER_TRUNCATED_VALUE
+          final LocalizableMessage message = ERR_ASN1_INTEGER_TRUNCATED_VALUE
               .get(peekLength);
           throw DecodeException.fatalError(message);
         }
@@ -354,8 +358,8 @@
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "READ ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            peekType, peekLength, intValue));
+            "READ ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", peekType,
+            peekLength, intValue));
       }
 
       state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -376,15 +380,15 @@
     // Make sure that the decoded length is exactly zero byte.
     if (peekLength != 0)
     {
-      LocalizableMessage message = ERR_ASN1_NULL_INVALID_LENGTH.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_NULL_INVALID_LENGTH
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String
-          .format("READ ASN.1 NULL(type=0x%x, length=%d)", peekType,
-              peekLength));
+      StaticUtils.DEBUG_LOG.finest(String.format(
+          "READ ASN.1 NULL(type=0x%x, length=%d)", peekType, peekLength));
     }
 
     state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -407,7 +411,7 @@
     }
 
     // Copy the value and construct the element to return.
-    byte[] value = new byte[peekLength];
+    final byte[] value = new byte[peekLength];
     int bytesNeeded = peekLength;
     int bytesRead;
     while (bytesNeeded > 0)
@@ -415,7 +419,7 @@
       bytesRead = in.read(value, peekLength - bytesNeeded, bytesNeeded);
       if (bytesRead < 0)
       {
-        LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
+        final LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
             .get(peekLength);
         throw DecodeException.fatalError(message);
       }
@@ -425,9 +429,9 @@
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 OCTETSTRING(type=0x%x, length=%d)", peekType,
-          peekLength));
+      StaticUtils.DEBUG_LOG
+          .finest(String.format("READ ASN.1 OCTETSTRING(type=0x%x, length=%d)",
+              peekType, peekLength));
     }
 
     state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -439,7 +443,7 @@
   /**
    * {@inheritDoc}
    */
-  public ByteStringBuilder readOctetString(ByteStringBuilder builder)
+  public ByteStringBuilder readOctetString(final ByteStringBuilder builder)
       throws IOException
   {
     // Read the header if haven't done so already
@@ -459,7 +463,7 @@
       bytesRead = builder.append(in, bytesNeeded);
       if (bytesRead < 0)
       {
-        LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
+        final LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
             .get(peekLength);
         throw DecodeException.fatalError(message);
       }
@@ -468,9 +472,9 @@
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 OCTETSTRING(type=0x%x, length=%d)", peekType,
-          peekLength));
+      StaticUtils.DEBUG_LOG
+          .finest(String.format("READ ASN.1 OCTETSTRING(type=0x%x, length=%d)",
+              peekType, peekLength));
     }
 
     state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -503,11 +507,10 @@
     int bytesRead;
     while (bytesNeeded > 0)
     {
-      bytesRead = in
-          .read(buffer, peekLength - bytesNeeded, bytesNeeded);
+      bytesRead = in.read(buffer, peekLength - bytesNeeded, bytesNeeded);
       if (bytesRead < 0)
       {
-        LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
+        final LocalizableMessage message = ERR_ASN1_OCTET_STRING_TRUNCATED_VALUE
             .get(peekLength);
         throw DecodeException.fatalError(message);
       }
@@ -521,13 +524,12 @@
     {
       str = new String(buffer, 0, peekLength, "UTF-8");
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
       if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
       {
-        StaticUtils.DEBUG_LOG
-            .warning("Unable to decode ASN.1 OCTETSTRING "
-                + "bytes as UTF-8 string: " + e.toString());
+        StaticUtils.DEBUG_LOG.warning("Unable to decode ASN.1 OCTETSTRING "
+            + "bytes as UTF-8 string: " + e.toString());
       }
 
       str = new String(buffer, 0, peekLength);
@@ -536,8 +538,8 @@
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
-          "READ ASN.1 OCTETSTRING(type=0x%x, length=%d, value=%s)",
-          peekType, peekLength, str));
+          "READ ASN.1 OCTETSTRING(type=0x%x, length=%d, value=%s)", peekType,
+          peekLength, str));
     }
 
     return str;
@@ -553,7 +555,7 @@
     // Read the header if haven't done so already
     peekLength();
 
-    SizeLimitInputStream subStream = new SizeLimitInputStream(in,
+    final SizeLimitInputStream subStream = new SizeLimitInputStream(in,
         peekLength);
 
     if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
@@ -592,10 +594,11 @@
     // Read the header if haven't done so already
     peekLength();
 
-    long bytesSkipped = in.skip(peekLength);
+    final long bytesSkipped = in.skip(peekLength);
     if (bytesSkipped != peekLength)
     {
-      LocalizableMessage message = ERR_ASN1_SKIP_TRUNCATED_VALUE.get(peekLength);
+      final LocalizableMessage message = ERR_ASN1_SKIP_TRUNCATED_VALUE
+          .get(peekLength);
       throw DecodeException.fatalError(message);
     }
     state = ELEMENT_READ_STATE_NEED_TYPE;
@@ -605,23 +608,21 @@
 
 
   /**
-   * Internal helper method reading the additional ASN.1 length bytes
-   * and transition to the next state if successful.
+   * Internal helper method reading the additional ASN.1 length bytes and
+   * transition to the next state if successful.
    *
    * @param isBlocking
-   *          <code>true</code> to block if the type byte is not
-   *          available or <code>false</code> to check for availability
-   *          first.
+   *          <code>true</code> to block if the type byte is not available or
+   *          <code>false</code> to check for availability first.
    * @param throwEofException
-   *          <code>true</code> to throw an exception when an EOF is
-   *          encountered or <code>false</code> to return false.
-   * @return <code>true</code> if the length bytes was successfully
-   *         read.
+   *          <code>true</code> to throw an exception when an EOF is encountered
+   *          or <code>false</code> to return false.
+   * @return <code>true</code> if the length bytes was successfully read.
    * @throws IOException
    *           If an error occurs while reading from the stream.
    */
-  private boolean needAdditionalLengthBytesState(boolean isBlocking,
-      boolean throwEofException) throws IOException
+  private boolean needAdditionalLengthBytesState(final boolean isBlocking,
+      final boolean throwEofException) throws IOException
   {
     if (!isBlocking && (in.available() < lengthBytesNeeded))
     {
@@ -637,7 +638,7 @@
         state = ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES;
         if (throwEofException)
         {
-          LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTES
+          final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTES
               .get(lengthBytesNeeded);
           throw DecodeException.fatalError(message);
         }
@@ -651,7 +652,7 @@
     // message size.
     if ((maxElementSize > 0) && (peekLength > maxElementSize))
     {
-      LocalizableMessage message = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
+      final LocalizableMessage message = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
           .get(peekLength, maxElementSize);
       throw DecodeException.fatalError(message);
     }
@@ -662,22 +663,21 @@
 
 
   /**
-   * Internal helper method reading the first length bytes and
-   * transition to the next state if successful.
+   * Internal helper method reading the first length bytes and transition to the
+   * next state if successful.
    *
    * @param isBlocking
-   *          <code>true</code> to block if the type byte is not
-   *          available or <code>false</code> to check for availability
-   *          first.
+   *          <code>true</code> to block if the type byte is not available or
+   *          <code>false</code> to check for availability first.
    * @param throwEofException
-   *          <code>true</code> to throw an exception when an EOF is
-   *          encountered or <code>false</code> to return false.
+   *          <code>true</code> to throw an exception when an EOF is encountered
+   *          or <code>false</code> to return false.
    * @return <code>true</code> if the length bytes was successfully read
    * @throws IOException
    *           If an error occurs while reading from the stream.
    */
-  private boolean needFirstLengthByteState(boolean isBlocking,
-      boolean throwEofException) throws IOException
+  private boolean needFirstLengthByteState(final boolean isBlocking,
+      final boolean throwEofException) throws IOException
   {
     if (!isBlocking && (in.available() <= 0))
     {
@@ -689,7 +689,7 @@
     {
       if (throwEofException)
       {
-        LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTE.get();
+        final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTE.get();
         throw DecodeException.fatalError(message);
       }
       return false;
@@ -700,7 +700,7 @@
       lengthBytesNeeded = peekLength;
       if (lengthBytesNeeded > 4)
       {
-        LocalizableMessage message = ERR_ASN1_INVALID_NUM_LENGTH_BYTES
+        final LocalizableMessage message = ERR_ASN1_INVALID_NUM_LENGTH_BYTES
             .get(lengthBytesNeeded);
         throw DecodeException.fatalError(message);
       }
@@ -720,7 +720,7 @@
           state = ELEMENT_READ_STATE_NEED_ADDITIONAL_LENGTH_BYTES;
           if (throwEofException)
           {
-            LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTES
+            final LocalizableMessage message = ERR_ASN1_TRUNCATED_LENGTH_BYTES
                 .get(lengthBytesNeeded);
             throw DecodeException.fatalError(message);
           }
@@ -735,7 +735,7 @@
     // message size.
     if ((maxElementSize > 0) && (peekLength > maxElementSize))
     {
-      LocalizableMessage message = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
+      final LocalizableMessage message = ERR_LDAP_CLIENT_DECODE_MAX_REQUEST_SIZE_EXCEEDED
           .get(peekLength, maxElementSize);
       throw DecodeException.fatalError(message);
     }
@@ -746,22 +746,21 @@
 
 
   /**
-   * Internal helper method reading the ASN.1 type byte and transition
-   * to the next state if successful.
+   * Internal helper method reading the ASN.1 type byte and transition to the
+   * next state if successful.
    *
    * @param isBlocking
-   *          <code>true</code> to block if the type byte is not
-   *          available or <code>false</code> to check for availability
-   *          first.
+   *          <code>true</code> to block if the type byte is not available or
+   *          <code>false</code> to check for availability first.
    * @param throwEofException
-   *          <code>true</code> to throw an exception when an EOF is
-   *          encountered or <code>false</code> to return false.
+   *          <code>true</code> to throw an exception when an EOF is encountered
+   *          or <code>false</code> to return false.
    * @return <code>true</code> if the type byte was successfully read
    * @throws IOException
    *           If an error occurs while reading from the stream.
    */
-  private boolean needTypeState(boolean isBlocking,
-      boolean throwEofException) throws IOException
+  private boolean needTypeState(final boolean isBlocking,
+      final boolean throwEofException) throws IOException
   {
     // Read just the type.
     if (!isBlocking && (in.available() <= 0))
@@ -769,12 +768,12 @@
       return false;
     }
 
-    int type = in.read();
+    final int type = in.read();
     if (type == -1)
     {
       if (throwEofException)
       {
-        LocalizableMessage message = ERR_ASN1_TRUCATED_TYPE_BYTE.get();
+        final LocalizableMessage message = ERR_ASN1_TRUCATED_TYPE_BYTE.get();
         throw DecodeException.fatalError(message);
       }
       return false;
diff --git a/sdk/src/org/opends/sdk/asn1/ASN1OutputStreamWriter.java b/sdk/src/org/opends/sdk/asn1/ASN1OutputStreamWriter.java
index 206e8d4..a61e6a1 100644
--- a/sdk/src/org/opends/sdk/asn1/ASN1OutputStreamWriter.java
+++ b/sdk/src/org/opends/sdk/asn1/ASN1OutputStreamWriter.java
@@ -28,8 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.asn1.ASN1Constants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED;
+import static org.opends.sdk.asn1.ASN1Constants.BOOLEAN_VALUE_FALSE;
+import static org.opends.sdk.asn1.ASN1Constants.BOOLEAN_VALUE_TRUE;
 
 import java.io.IOException;
 import java.io.OutputStream;
@@ -44,6 +45,7 @@
 import com.sun.opends.sdk.util.StaticUtils;
 
 
+
 /**
  * An ASN1Writer implementation that outputs to an outputstream.
  */
@@ -63,7 +65,7 @@
    * @param stream
    *          The underlying output stream.
    */
-  ASN1OutputStreamWriter(OutputStream stream)
+  ASN1OutputStreamWriter(final OutputStream stream)
   {
     this.out = stream;
     this.rootStream = stream;
@@ -103,18 +105,18 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeBoolean(byte type, boolean booleanValue)
+  public ASN1Writer writeBoolean(final byte type, final boolean booleanValue)
       throws IOException
   {
     out.write(type);
     writeLength(1);
     out.write(booleanValue ? BOOLEAN_VALUE_TRUE : BOOLEAN_VALUE_FALSE);
 
-    if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
-          "WRITE ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)", type,
-          1, String.valueOf(booleanValue)));
+          "WRITE ASN.1 BOOLEAN(type=0x%x, length=%d, value=%s)", type, 1,
+          String.valueOf(booleanValue)));
     }
     return this;
   }
@@ -124,21 +126,23 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeEndSequence() throws IOException, IllegalStateException
+  public ASN1Writer writeEndSequence() throws IOException,
+      IllegalStateException
   {
     if (stackDepth < 0)
     {
-      LocalizableMessage message = ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED.get();
+      final LocalizableMessage message = ERR_ASN1_SEQUENCE_WRITE_NOT_STARTED
+          .get();
       throw new IllegalStateException(message.toString());
     }
 
-    ByteSequenceOutputStream childStream = streamStack.get(stackDepth);
+    final ByteSequenceOutputStream childStream = streamStack.get(stackDepth);
 
     // Decrement the stack depth and get the parent stream
     --stackDepth;
 
-    OutputStream parentStream =
-        stackDepth < 0 ? rootStream : streamStack.get(stackDepth);
+    final OutputStream parentStream = stackDepth < 0 ? rootStream : streamStack
+        .get(stackDepth);
 
     // Switch to parent stream and reset the sub-stream
     out = parentStream;
@@ -147,7 +151,7 @@
     writeLength(childStream.length());
     childStream.writeTo(parentStream);
 
-    if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
           "WRITE ASN.1 END SEQUENCE(length=%d)", childStream.length()));
@@ -172,7 +176,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeEnumerated(byte type, int intValue)
+  public ASN1Writer writeEnumerated(final byte type, final int intValue)
       throws IOException
   {
     return writeInteger(type, intValue);
@@ -183,7 +187,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeInteger(byte type, int intValue)
+  public ASN1Writer writeInteger(final byte type, final int intValue)
       throws IOException
   {
     out.write(type);
@@ -192,11 +196,11 @@
     {
       writeLength(1);
       out.write((byte) (intValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 1, intValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 1,
+            intValue));
       }
     }
     else if (((intValue < 0) && ((intValue & 0xFFFF8000) == 0xFFFF8000))
@@ -205,11 +209,11 @@
       writeLength(2);
       out.write((byte) ((intValue >> 8) & 0xFF));
       out.write((byte) (intValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 2, intValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 2,
+            intValue));
       }
     }
     else if (((intValue < 0) && ((intValue & 0xFF800000) == 0xFF800000))
@@ -219,11 +223,11 @@
       out.write((byte) ((intValue >> 16) & 0xFF));
       out.write((byte) ((intValue >> 8) & 0xFF));
       out.write((byte) (intValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 3, intValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 3,
+            intValue));
       }
     }
     else
@@ -233,11 +237,11 @@
       out.write((byte) ((intValue >> 16) & 0xFF));
       out.write((byte) ((intValue >> 8) & 0xFF));
       out.write((byte) (intValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-            type, 4, intValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 4,
+            intValue));
       }
     }
     return this;
@@ -248,7 +252,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeInteger(byte type, long longValue)
+  public ASN1Writer writeInteger(final byte type, final long longValue)
       throws IOException
   {
     out.write(type);
@@ -257,11 +261,11 @@
     {
       writeLength(1);
       out.write((byte) (longValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 1, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 1,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFFFFFFFFFFFF8000L) == 0xFFFFFFFFFFFF8000L))
@@ -270,11 +274,11 @@
       writeLength(2);
       out.write((byte) ((longValue >> 8) & 0xFF));
       out.write((byte) (longValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 2, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 2,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFFFFFFFFFF800000L) == 0xFFFFFFFFFF800000L))
@@ -284,11 +288,11 @@
       out.write((byte) ((longValue >> 16) & 0xFF));
       out.write((byte) ((longValue >> 8) & 0xFF));
       out.write((byte) (longValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 3, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 3,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFFFFFFFF80000000L) == 0xFFFFFFFF80000000L))
@@ -299,11 +303,11 @@
       out.write((byte) ((longValue >> 16) & 0xFF));
       out.write((byte) ((longValue >> 8) & 0xFF));
       out.write((byte) (longValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 4, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 4,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFFFFFF8000000000L) == 0xFFFFFF8000000000L))
@@ -315,11 +319,11 @@
       out.write((byte) ((longValue >> 16) & 0xFF));
       out.write((byte) ((longValue >> 8) & 0xFF));
       out.write((byte) (longValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 5, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 5,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFFFF800000000000L) == 0xFFFF800000000000L))
@@ -332,11 +336,11 @@
       out.write((byte) ((longValue >> 16) & 0xFF));
       out.write((byte) ((longValue >> 8) & 0xFF));
       out.write((byte) (longValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 6, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 6,
+            longValue));
       }
     }
     else if (((longValue < 0) && ((longValue & 0xFF80000000000000L) == 0xFF80000000000000L))
@@ -350,11 +354,11 @@
       out.write((byte) ((longValue >> 16) & 0xFF));
       out.write((byte) ((longValue >> 8) & 0xFF));
       out.write((byte) (longValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 7, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 7,
+            longValue));
       }
     }
     else
@@ -368,11 +372,11 @@
       out.write((byte) ((longValue >> 16) & 0xFF));
       out.write((byte) ((longValue >> 8) & 0xFF));
       out.write((byte) (longValue & 0xFF));
-      if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+      if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
       {
         StaticUtils.DEBUG_LOG.finest(String.format(
-            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)",
-                type, 8, longValue));
+            "WRITE ASN.1 INTEGER(type=0x%x, length=%d, value=%d)", type, 8,
+            longValue));
       }
     }
     return this;
@@ -383,12 +387,12 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeNull(byte type) throws IOException
+  public ASN1Writer writeNull(final byte type) throws IOException
   {
     out.write(type);
     writeLength(0);
 
-    if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
           "WRITE ASN.1 NULL(type=0x%x, length=%d)", type, 0));
@@ -401,18 +405,17 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeOctetString(byte type, byte[] value,
-      int offset, int length) throws IOException
+  public ASN1Writer writeOctetString(final byte type, final byte[] value,
+      final int offset, final int length) throws IOException
   {
     out.write(type);
     writeLength(length);
     out.write(value, offset, length);
 
-    if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
-          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)",
-              type, length));
+          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)", type, length));
     }
     return this;
   }
@@ -422,17 +425,17 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeOctetString(byte type, ByteSequence value)
+  public ASN1Writer writeOctetString(final byte type, final ByteSequence value)
       throws IOException
   {
     out.write(type);
     writeLength(value.length());
     value.copyTo(out);
 
-    if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
-      StaticUtils.DEBUG_LOG.finest(String.format(
-          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)", type, value
+      StaticUtils.DEBUG_LOG.finest(String
+          .format("WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d)", type, value
               .length()));
     }
     return this;
@@ -443,7 +446,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeOctetString(byte type, String value)
+  public ASN1Writer writeOctetString(final byte type, final String value)
       throws IOException
   {
     out.write(type);
@@ -454,15 +457,15 @@
       return this;
     }
 
-    byte[] bytes = StaticUtils.getBytes(value);
+    final byte[] bytes = StaticUtils.getBytes(value);
     writeLength(bytes.length);
     out.write(bytes);
 
-    if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
-          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d, "
-              + "value=%s)", type, bytes.length, value));
+          "WRITE ASN.1 OCTETSTRING(type=0x%x, length=%d, " + "value=%s)", type,
+          bytes.length, value));
     }
     return this;
   }
@@ -472,7 +475,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeStartSequence(byte type) throws IOException
+  public ASN1Writer writeStartSequence(final byte type) throws IOException
   {
     // Write the type in current stream switch to next sub-stream
     out.write(type);
@@ -483,8 +486,8 @@
     // Make sure we have a cached sub-stream at this depth
     if (stackDepth >= streamStack.size())
     {
-      ByteSequenceOutputStream subStream =
-          new ByteSequenceOutputStream(new ByteStringBuilder());
+      final ByteSequenceOutputStream subStream = new ByteSequenceOutputStream(
+          new ByteStringBuilder());
       streamStack.add(subStream);
       out = subStream;
     }
@@ -493,7 +496,7 @@
       out = streamStack.get(stackDepth);
     }
 
-    if(StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
+    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINEST))
     {
       StaticUtils.DEBUG_LOG.finest(String.format(
           "WRITE ASN.1 START SEQUENCE(type=0x%x)", type));
@@ -506,7 +509,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeStartSet(byte type) throws IOException
+  public ASN1Writer writeStartSet(final byte type) throws IOException
   {
     // From an implementation point of view, a set is equivalent to a
     // sequence.
@@ -516,15 +519,14 @@
 
 
   /**
-   * Writes the provided value for use as the length of an ASN.1
-   * element.
+   * Writes the provided value for use as the length of an ASN.1 element.
    *
    * @param length
    *          The length to encode for use in an ASN.1 element.
    * @throws IOException
    *           if an error occurs while writing.
    */
-  private void writeLength(int length) throws IOException
+  private void writeLength(final int length) throws IOException
   {
     if (length < 128)
     {
diff --git a/sdk/src/org/opends/sdk/asn1/ASN1Reader.java b/sdk/src/org/opends/sdk/asn1/ASN1Reader.java
index b47ba44..025270d 100644
--- a/sdk/src/org/opends/sdk/asn1/ASN1Reader.java
+++ b/sdk/src/org/opends/sdk/asn1/ASN1Reader.java
@@ -41,8 +41,8 @@
 /**
  * An interface for decoding ASN.1 elements from a data source.
  * <p>
- * Methods for creating {@link ASN1Reader}s are provided in the
- * {@link ASN1} class.
+ * Methods for creating {@link ASN1Reader}s are provided in the {@link ASN1}
+ * class.
  */
 public interface ASN1Reader extends Closeable
 {
@@ -58,11 +58,10 @@
 
 
   /**
-   * Indicates whether or not the next element can be read without
-   * blocking.
+   * Indicates whether or not the next element can be read without blocking.
    *
-   * @return {@code true} if a complete element is available or {@code
-   *         false} otherwise.
+   * @return {@code true} if a complete element is available or {@code false}
+   *         otherwise.
    * @throws DecodeException
    *           If the available data was not valid ASN.1.
    * @throws IOException
@@ -73,17 +72,17 @@
 
 
   /**
-   * Indicates whether or not the current stream, sequence, or set
-   * contains another element. Note that this method may return {@code
-   * true} even if a previous call to {@link #elementAvailable} returned
-   * {@code false}, indicating that the current set or sequence contains
-   * another element but an attempt to read that element may block. This
-   * method will block if there is not enough data available to make the
-   * determination (typically only the next element's type is required).
+   * Indicates whether or not the current stream, sequence, or set contains
+   * another element. Note that this method may return {@code true} even if a
+   * previous call to {@link #elementAvailable} returned {@code false},
+   * indicating that the current set or sequence contains another element but an
+   * attempt to read that element may block. This method will block if there is
+   * not enough data available to make the determination (typically only the
+   * next element's type is required).
    *
-   * @return {@code true} if the current stream, sequence, or set
-   *         contains another element, or {@code false} if the end of
-   *         the stream, sequence, or set has been reached.
+   * @return {@code true} if the current stream, sequence, or set contains
+   *         another element, or {@code false} if the end of the stream,
+   *         sequence, or set has been reached.
    * @throws DecodeException
    *           If the available data was not valid ASN.1.
    * @throws IOException
@@ -94,11 +93,10 @@
 
 
   /**
-   * Returns the data length of the next element without actually
-   * reading it.
+   * Returns the data length of the next element without actually reading it.
    *
-   * @return The data length of the next element, or {@code -1} if the
-   *         end of the stream, sequence, or set has been reached.
+   * @return The data length of the next element, or {@code -1} if the end of
+   *         the stream, sequence, or set has been reached.
    * @throws DecodeException
    *           If the available data was not valid ASN.1.
    * @throws IOException
@@ -111,8 +109,8 @@
   /**
    * Returns the type of the next element without actually reading it.
    *
-   * @return The type of the next element, or {@code -1} if the end of
-   *         the stream, sequence, or set has been reached.
+   * @return The type of the next element, or {@code -1} if the end of the
+   *         stream, sequence, or set has been reached.
    * @throws DecodeException
    *           If the available data was not valid ASN.1.
    * @throws IOException
@@ -123,8 +121,8 @@
 
 
   /**
-   * Reads the next element as a boolean having the Universal Boolean
-   * ASN.1 type tag.
+   * Reads the next element as a boolean having the Universal Boolean ASN.1 type
+   * tag.
    *
    * @return The decoded boolean value.
    * @throws DecodeException
@@ -155,8 +153,7 @@
    * Finishes reading a sequence and discards any unread elements.
    *
    * @throws DecodeException
-   *           If an error occurs while advancing to the end of the
-   *           sequence.
+   *           If an error occurs while advancing to the end of the sequence.
    * @throws IOException
    *           If an unexpected IO error occurred.
    * @throws IllegalStateException
@@ -177,14 +174,13 @@
    * @throws IllegalStateException
    *           If there is no set being read.
    */
-  void readEndSet() throws DecodeException, IOException,
-      IllegalStateException;
+  void readEndSet() throws DecodeException, IOException, IllegalStateException;
 
 
 
   /**
-   * Reads the next element as an enumerated having the Universal
-   * Enumerated ASN.1 type tag.
+   * Reads the next element as an enumerated having the Universal Enumerated
+   * ASN.1 type tag.
    *
    * @return The decoded enumerated value.
    * @throws DecodeException
@@ -197,8 +193,7 @@
 
 
   /**
-   * Reads the next element as an enumerated having the provided type
-   * tag.
+   * Reads the next element as an enumerated having the provided type tag.
    *
    * @param type
    *          The expected type tag of the element.
@@ -213,8 +208,8 @@
 
 
   /**
-   * Reads the next element as an integer having the Universal Integer
-   * ASN.1 type tag.
+   * Reads the next element as an integer having the Universal Integer ASN.1
+   * type tag.
    *
    * @return The decoded integer value.
    * @throws DecodeException
@@ -242,8 +237,8 @@
 
 
   /**
-   * Reads the next element as a null element having the Universal Null
-   * ASN.1 type tag.
+   * Reads the next element as a null element having the Universal Null ASN.1
+   * type tag.
    *
    * @throws DecodeException
    *           If the element cannot be decoded as a null element.
@@ -255,8 +250,7 @@
 
 
   /**
-   * Reads the next element as a null element having the provided type
-   * tag.
+   * Reads the next element as a null element having the provided type tag.
    *
    * @param type
    *          The expected type tag of the element.
@@ -270,11 +264,10 @@
 
 
   /**
-   * Reads the next element as an octet string having the Universal
-   * Octet String ASN.1 type tag.
+   * Reads the next element as an octet string having the Universal Octet String
+   * ASN.1 type tag.
    *
-   * @return The decoded octet string represented using a
-   *         {@link ByteString}.
+   * @return The decoded octet string represented using a {@link ByteString}.
    * @throws DecodeException
    *           If the element cannot be decoded as an octet string.
    * @throws IOException
@@ -285,32 +278,28 @@
 
 
   /**
-   * Reads the next element as an octet string having the provided type
-   * tag.
+   * Reads the next element as an octet string having the provided type tag.
    *
    * @param type
    *          The expected type tag of the element.
-   * @return The decoded octet string represented using a
-   *         {@link ByteString}.
+   * @return The decoded octet string represented using a {@link ByteString}.
    * @throws DecodeException
    *           If the element cannot be decoded as an octet string.
    * @throws IOException
    *           If an unexpected IO error occurred.
    */
-  ByteString readOctetString(byte type) throws DecodeException,
-      IOException;
+  ByteString readOctetString(byte type) throws DecodeException, IOException;
 
 
 
   /**
-   * Reads the next element as an octet string having the provided type
-   * tag and appends it to the provided {@link ByteStringBuilder}.
+   * Reads the next element as an octet string having the provided type tag and
+   * appends it to the provided {@link ByteStringBuilder}.
    *
    * @param type
    *          The expected type tag of the element.
    * @param builder
-   *          The {@link ByteStringBuilder} to append the octet string
-   *          to.
+   *          The {@link ByteStringBuilder} to append the octet string to.
    * @return A reference to {@code builder}.
    * @throws DecodeException
    *           If the element cannot be decoded as an octet string.
@@ -323,13 +312,11 @@
 
 
   /**
-   * Reads the next element as an octet string having the Universal
-   * Octet String ASN.1 type tag and appends it to the provided
-   * {@link ByteStringBuilder}.
+   * Reads the next element as an octet string having the Universal Octet String
+   * ASN.1 type tag and appends it to the provided {@link ByteStringBuilder}.
    *
    * @param builder
-   *          The {@link ByteStringBuilder} to append the octet string
-   *          to.
+   *          The {@link ByteStringBuilder} to append the octet string to.
    * @return A reference to {@code builder}.
    * @throws DecodeException
    *           If the element cannot be decoded as an octet string.
@@ -342,9 +329,8 @@
 
 
   /**
-   * Reads the next element as an octet string having the Universal
-   * Octet String ASN.1 type tag and decodes the value as a UTF-8
-   * encoded string.
+   * Reads the next element as an octet string having the Universal Octet String
+   * ASN.1 type tag and decodes the value as a UTF-8 encoded string.
    *
    * @return The decoded octet string as a UTF-8 encoded string.
    * @throws DecodeException
@@ -352,14 +338,13 @@
    * @throws IOException
    *           If an unexpected IO error occurred.
    */
-  String readOctetStringAsString() throws DecodeException,
-      IOException;
+  String readOctetStringAsString() throws DecodeException, IOException;
 
 
 
   /**
-   * Reads the next element as an octet string having the provided type
-   * tag and decodes the value as a UTF-8 encoded string.
+   * Reads the next element as an octet string having the provided type tag and
+   * decodes the value as a UTF-8 encoded string.
    *
    * @param type
    *          The expected type tag of the element.
@@ -369,15 +354,14 @@
    * @throws IOException
    *           If an unexpected IO error occurred.
    */
-  String readOctetStringAsString(byte type) throws DecodeException,
-      IOException;
+  String readOctetStringAsString(byte type) throws DecodeException, IOException;
 
 
 
   /**
-   * Reads the next element as a sequence having the Universal Sequence
-   * ASN.1 type tag. All further reads will read the elements in the
-   * sequence until {@link #readEndSequence()} is called.
+   * Reads the next element as a sequence having the Universal Sequence ASN.1
+   * type tag. All further reads will read the elements in the sequence until
+   * {@link #readEndSequence()} is called.
    *
    * @throws DecodeException
    *           If the element cannot be decoded as a sequence.
@@ -389,8 +373,8 @@
 
 
   /**
-   * Reads the next element as a sequence having the provided type tag.
-   * All further reads will read the elements in the sequence until
+   * Reads the next element as a sequence having the provided type tag. All
+   * further reads will read the elements in the sequence until
    * {@link #readEndSequence()} is called.
    *
    * @param type
@@ -400,14 +384,13 @@
    * @throws IOException
    *           If an unexpected IO error occurred.
    */
-  void readStartSequence(byte type) throws DecodeException,
-      IOException;
+  void readStartSequence(byte type) throws DecodeException, IOException;
 
 
 
   /**
-   * Reads the next element as a set having the Universal Set ASN.1 type
-   * tag. All further reads will read the elements in the set until
+   * Reads the next element as a set having the Universal Set ASN.1 type tag.
+   * All further reads will read the elements in the set until
    * {@link #readEndSet()} is called.
    *
    * @throws DecodeException
@@ -420,9 +403,9 @@
 
 
   /**
-   * Reads the next element as a set having the provided type tag. All
-   * further reads will read the elements in the set until
-   * {@link #readEndSet()} is called.
+   * Reads the next element as a set having the provided type tag. All further
+   * reads will read the elements in the set until {@link #readEndSet()} is
+   * called.
    *
    * @param type
    *          The expected type tag of the element.
diff --git a/sdk/src/org/opends/sdk/asn1/ASN1Writer.java b/sdk/src/org/opends/sdk/asn1/ASN1Writer.java
index b4621ed..b992ab6 100644
--- a/sdk/src/org/opends/sdk/asn1/ASN1Writer.java
+++ b/sdk/src/org/opends/sdk/asn1/ASN1Writer.java
@@ -39,16 +39,16 @@
 /**
  * An interface for encoding ASN.1 elements to a data source.
  * <p>
- * Methods for creating {@link ASN1Writer}s are provided in the
- * {@link ASN1} class.
+ * Methods for creating {@link ASN1Writer}s are provided in the {@link ASN1}
+ * class.
  */
 public interface ASN1Writer extends Closeable, Flushable
 {
 
   /**
-   * Closes this ASN.1 writer, flushing it first. Closing a previously
-   * closed ASN.1 writer has no effect. Any unfinished sequences and/or
-   * sets will be ended.
+   * Closes this ASN.1 writer, flushing it first. Closing a previously closed
+   * ASN.1 writer has no effect. Any unfinished sequences and/or sets will be
+   * ended.
    *
    * @throws IOException
    *           If an error occurs while closing.
@@ -59,17 +59,15 @@
 
   /**
    * Flushes this ASN.1 writer so that any buffered elements are written
-   * immediately to their intended destination. Then, if that
-   * destination is another byte stream, flush it. Thus one {@code
-   * flush()} invocation will flush all the buffers in a chain of
-   * streams.
+   * immediately to their intended destination. Then, if that destination is
+   * another byte stream, flush it. Thus one {@code flush()} invocation will
+   * flush all the buffers in a chain of streams.
    * <p>
-   * If the intended destination of this stream is an abstraction
-   * provided by the underlying operating system, for example a file,
-   * then flushing the stream guarantees only that bytes previously
-   * written to the stream are passed to the operating system for
-   * writing; it does not guarantee that they are actually written to a
-   * physical device such as a disk drive.
+   * If the intended destination of this stream is an abstraction provided by
+   * the underlying operating system, for example a file, then flushing the
+   * stream guarantees only that bytes previously written to the stream are
+   * passed to the operating system for writing; it does not guarantee that they
+   * are actually written to a physical device such as a disk drive.
    *
    * @throws IOException
    *           If an error occurs while flushing.
@@ -79,8 +77,7 @@
 
 
   /**
-   * Writes a boolean element using the Universal Boolean ASN.1 type
-   * tag.
+   * Writes a boolean element using the Universal Boolean ASN.1 type tag.
    *
    * @param value
    *          The boolean value.
@@ -116,8 +113,7 @@
    * @throws IllegalStateException
    *           If there is no sequence being written.
    */
-  ASN1Writer writeEndSequence() throws IOException,
-      IllegalStateException;
+  ASN1Writer writeEndSequence() throws IOException, IllegalStateException;
 
 
 
@@ -130,7 +126,7 @@
    * @throws IllegalStateException
    *           If there is no set being written, IllegalStateException.
    */
-  ASN1Writer writeEndSet() throws IOException;
+  ASN1Writer writeEndSet() throws IOException, IllegalStateException;
 
 
 
@@ -150,8 +146,7 @@
 
 
   /**
-   * Writes an enumerated element using the Universal Enumerated ASN.1
-   * type tag.
+   * Writes an enumerated element using the Universal Enumerated ASN.1 type tag.
    *
    * @param value
    *          The enumerated value.
@@ -194,8 +189,7 @@
 
 
   /**
-   * Writes an integer element using the Universal Integer ASN.1 type
-   * tag.
+   * Writes an integer element using the Universal Integer ASN.1 type tag.
    *
    * @param value
    *          The integer value.
@@ -208,8 +202,7 @@
 
 
   /**
-   * Writes an integer element using the Universal Integer ASN.1 type
-   * tag.
+   * Writes an integer element using the Universal Integer ASN.1 type tag.
    *
    * @param value
    *          The integer value.
@@ -260,8 +253,8 @@
    * @throws IOException
    *           If an error occurs while writing the element.
    */
-  ASN1Writer writeOctetString(byte type, byte[] value, int offset,
-      int length) throws IOException;
+  ASN1Writer writeOctetString(byte type, byte[] value, int offset, int length)
+      throws IOException;
 
 
 
@@ -276,14 +269,13 @@
    * @throws IOException
    *           If an error occurs while writing the element.
    */
-  ASN1Writer writeOctetString(byte type, ByteSequence value)
-      throws IOException;
+  ASN1Writer writeOctetString(byte type, ByteSequence value) throws IOException;
 
 
 
   /**
-   * Writes a string as a UTF-8 encoded octet string element using the
-   * provided type tag.
+   * Writes a string as a UTF-8 encoded octet string element using the provided
+   * type tag.
    *
    * @param type
    *          The type tag of the element.
@@ -293,14 +285,13 @@
    * @throws IOException
    *           If an error occurs while writing the element.
    */
-  ASN1Writer writeOctetString(byte type, String value)
-      throws IOException;
+  ASN1Writer writeOctetString(byte type, String value) throws IOException;
 
 
 
   /**
-   * Writes an octet string element using the Universal Octet String
-   * ASN.1 type tag.
+   * Writes an octet string element using the Universal Octet String ASN.1 type
+   * tag.
    *
    * @param value
    *          The byte array containing the octet string data.
@@ -318,8 +309,8 @@
 
 
   /**
-   * Writes an octet string element using the Universal Octet String
-   * ASN.1 type tag.
+   * Writes an octet string element using the Universal Octet String ASN.1 type
+   * tag.
    *
    * @param value
    *          The octet string value.
@@ -332,8 +323,8 @@
 
 
   /**
-   * Writes a string as a UTF-8 encoded octet string element using the
-   * Universal Octet String ASN.1 type tag.
+   * Writes a string as a UTF-8 encoded octet string element using the Universal
+   * Octet String ASN.1 type tag.
    *
    * @param value
    *          The string to be written as a UTF-8 encoded octet string.
@@ -346,8 +337,8 @@
 
 
   /**
-   * Writes a sequence element using the Universal Sequence ASN.1 type
-   * tag. All further writes will append elements to the sequence until
+   * Writes a sequence element using the Universal Sequence ASN.1 type tag. All
+   * further writes will append elements to the sequence until
    * {@link #writeEndSequence} is called.
    *
    * @return A reference to this ASN.1 writer.
@@ -359,9 +350,9 @@
 
 
   /**
-   * Writes a sequence element using the provided type tag. All further
-   * writes will append elements to the sequence until
-   * {@link #writeEndSequence} is called.
+   * Writes a sequence element using the provided type tag. All further writes
+   * will append elements to the sequence until {@link #writeEndSequence} is
+   * called.
    *
    * @param type
    *          The type tag of the element.
@@ -374,9 +365,9 @@
 
 
   /**
-   * Writes a set element using the Universal Set ASN.1 type tag. All
-   * further writes will append elements to the set until
-   * {@link #writeEndSet} is called.
+   * Writes a set element using the Universal Set ASN.1 type tag. All further
+   * writes will append elements to the set until {@link #writeEndSet} is
+   * called.
    *
    * @return A reference to this ASN.1 writer.
    * @throws IOException
@@ -387,9 +378,8 @@
 
 
   /**
-   * Writes a set element using the provided type tag. All further
-   * writes will append elements to the set until {@link #writeEndSet}
-   * is called.
+   * Writes a set element using the provided type tag. All further writes will
+   * append elements to the set until {@link #writeEndSet} is called.
    *
    * @param type
    *          The type tag of the element.
diff --git a/sdk/src/org/opends/sdk/asn1/AbstractASN1Reader.java b/sdk/src/org/opends/sdk/asn1/AbstractASN1Reader.java
index a6fb65a..970640d 100644
--- a/sdk/src/org/opends/sdk/asn1/AbstractASN1Reader.java
+++ b/sdk/src/org/opends/sdk/asn1/AbstractASN1Reader.java
@@ -29,7 +29,7 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ASN1_UNEXPECTED_TAG;
 import static org.opends.sdk.asn1.ASN1Constants.*;
 
 import java.io.IOException;
@@ -41,7 +41,6 @@
 
 
 
-
 /**
  * An abstract {@code ASN1Reader} which can be used as the basis for
  * implementing new ASN1 reader implementations.
@@ -137,7 +136,7 @@
    * {@inheritDoc}
    */
   public ByteStringBuilder readOctetString(byte type,
-      ByteStringBuilder builder) throws IOException
+      final ByteStringBuilder builder) throws IOException
   {
     if (type == 0x00)
     {
@@ -199,12 +198,12 @@
 
 
 
-  private void checkType(byte expectedType) throws IOException
+  private void checkType(final byte expectedType) throws IOException
   {
     if (peekType() != expectedType)
     {
-      LocalizableMessage message = ERR_ASN1_UNEXPECTED_TAG.get(expectedType,
-          peekType());
+      final LocalizableMessage message = ERR_ASN1_UNEXPECTED_TAG.get(
+          expectedType, peekType());
       throw DecodeException.fatalError(message);
     }
   }
diff --git a/sdk/src/org/opends/sdk/asn1/AbstractASN1Writer.java b/sdk/src/org/opends/sdk/asn1/AbstractASN1Writer.java
index f98bdf1..892a149 100644
--- a/sdk/src/org/opends/sdk/asn1/AbstractASN1Writer.java
+++ b/sdk/src/org/opends/sdk/asn1/AbstractASN1Writer.java
@@ -56,7 +56,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeBoolean(boolean value) throws IOException
+  public ASN1Writer writeBoolean(final boolean value) throws IOException
   {
     return writeBoolean(UNIVERSAL_BOOLEAN_TYPE, value);
   }
@@ -66,7 +66,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeEnumerated(int value) throws IOException
+  public ASN1Writer writeEnumerated(final int value) throws IOException
   {
     return writeEnumerated(UNIVERSAL_ENUMERATED_TYPE, value);
   }
@@ -76,7 +76,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeInteger(int value) throws IOException
+  public ASN1Writer writeInteger(final int value) throws IOException
   {
     return writeInteger(UNIVERSAL_INTEGER_TYPE, value);
   }
@@ -86,7 +86,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeInteger(long value) throws IOException
+  public ASN1Writer writeInteger(final long value) throws IOException
   {
     return writeInteger(UNIVERSAL_INTEGER_TYPE, value);
   }
@@ -106,11 +106,10 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeOctetString(byte[] value, int offset,
-      int length) throws IOException
+  public ASN1Writer writeOctetString(final byte[] value, final int offset,
+      final int length) throws IOException
   {
-    return writeOctetString(UNIVERSAL_OCTET_STRING_TYPE, value, offset,
-        length);
+    return writeOctetString(UNIVERSAL_OCTET_STRING_TYPE, value, offset, length);
   }
 
 
@@ -118,7 +117,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeOctetString(ByteSequence value)
+  public ASN1Writer writeOctetString(final ByteSequence value)
       throws IOException
   {
     return writeOctetString(UNIVERSAL_OCTET_STRING_TYPE, value);
@@ -129,7 +128,7 @@
   /**
    * {@inheritDoc}
    */
-  public ASN1Writer writeOctetString(String value) throws IOException
+  public ASN1Writer writeOctetString(final String value) throws IOException
   {
     return writeOctetString(UNIVERSAL_OCTET_STRING_TYPE, value);
   }
diff --git a/sdk/src/org/opends/sdk/asn1/package-info.java b/sdk/src/org/opends/sdk/asn1/package-info.java
index 5ab4bd7..f8c61ef 100755
--- a/sdk/src/org/opends/sdk/asn1/package-info.java
+++ b/sdk/src/org/opends/sdk/asn1/package-info.java
@@ -34,3 +34,6 @@
  * timestamp values.
  */
 package org.opends.sdk.asn1;
+
+
+
diff --git a/sdk/src/org/opends/sdk/controls/AccountUsabilityControl.java b/sdk/src/org/opends/sdk/controls/AccountUsabilityControl.java
deleted file mode 100644
index 88f1256..0000000
--- a/sdk/src/org/opends/sdk/controls/AccountUsabilityControl.java
+++ /dev/null
@@ -1,688 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ByteStringBuilder;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-
-
-
-/**
- * This class implements the Sun-defined account usable control.
- */
-public class AccountUsabilityControl
-{
-  /**
-   * The OID for the account usable request and response controls.
-   */
-  public static final String OID_ACCOUNT_USABLE_CONTROL = "1.3.6.1.4.1.42.2.27.9.5.8";
-
-
-
-  /**
-   * This class implements the Sun-defined account usable request
-   * control. The OID for this control is 1.3.6.1.4.1.42.2.27.9.5.8, and
-   * it does not have a value.
-   */
-  public static class Request extends Control
-  {
-    public Request()
-    {
-      super(OID_ACCOUNT_USABLE_CONTROL, false);
-    }
-
-
-
-    public Request(boolean isCritical)
-    {
-      super(OID_ACCOUNT_USABLE_CONTROL, isCritical);
-    }
-
-
-
-    @Override
-    public ByteString getValue()
-    {
-      return null;
-    }
-
-
-
-    @Override
-    public boolean hasValue()
-    {
-      return false;
-    }
-
-
-
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("AccountUsableRequestControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * This class implements the account usable response control. This is
-   * a Sun-defined control with OID 1.3.6.1.4.1.42.2.27.9.5.8. The value
-   * of this control is composed according to the following BNF: <BR>
-   * 
-   * <PRE>
-   * ACCOUNT_USABLE_RESPONSE ::= CHOICE {
-   *      is_available           [0] INTEGER, -- Seconds before expiration --
-   *      is_not_available       [1] MORE_INFO }
-   * MORE_INFO ::= SEQUENCE {
-   *      inactive               [0] BOOLEAN DEFAULT FALSE,
-   *      reset                  [1] BOOLEAN DEFAULT FALSE,
-   *      expired                [2] BOOLEAN DEFAULT_FALSE,
-   *      remaining_grace        [3] INTEGER OPTIONAL,
-   *      seconds_before_unlock  [4] INTEGER OPTIONAL }
-   * </PRE>
-   */
-  public static class Response extends Control
-  {
-    // Indicates whether the user's account is usable.
-    private final boolean isUsable;
-
-    // Indicates whether the user's password is expired.
-    private final boolean isExpired;
-
-    // Indicates whether the user's account is inactive.
-    private final boolean isInactive;
-
-    // Indicates whether the user's account is currently locked.
-    private final boolean isLocked;
-
-    // Indicates whether the user's password has been reset and must be
-    // changed
-    // before anything else can be done.
-    private final boolean isReset;
-
-    // The number of remaining grace logins, if available.
-    private final int remainingGraceLogins;
-
-    // The length of time in seconds before the user's password expires,
-    // if
-    // available.
-    private final int secondsBeforeExpiration;
-
-    // The length of time before the user's account is unlocked, if
-    // available.
-    private final int secondsBeforeUnlock;
-
-
-
-    /**
-     * Creates a new account usability response control that may be used
-     * to indicate that the account is not available and provide
-     * information about the underlying reason. It will use the default
-     * OID and criticality.
-     * 
-     * @param isCritical
-     *          Indicates whether this control should be considered
-     *          critical in processing the request.
-     * @param isInactive
-     *          Indicates whether the user's account has been
-     *          inactivated by an administrator.
-     * @param isReset
-     *          Indicates whether the user's password has been reset by
-     *          an administrator.
-     * @param isExpired
-     *          Indicates whether the user's password is expired.
-     * @param remainingGraceLogins
-     *          The number of grace logins remaining. A value of zero
-     *          indicates that there are none remaining. A value of -1
-     *          indicates that grace login functionality is not enabled.
-     * @param isLocked
-     *          Indicates whether the user's account is currently locked
-     *          out.
-     * @param secondsBeforeUnlock
-     *          The length of time in seconds until the account is
-     *          unlocked. A value of -1 indicates that the account will
-     *          not be automatically unlocked and must be reset by an
-     *          administrator.
-     */
-    public Response(boolean isCritical, boolean isInactive,
-        boolean isReset, boolean isExpired, int remainingGraceLogins,
-        boolean isLocked, int secondsBeforeUnlock)
-    {
-      super(OID_ACCOUNT_USABLE_CONTROL, isCritical);
-
-      this.isInactive = isInactive;
-      this.isReset = isReset;
-      this.isExpired = isExpired;
-      this.remainingGraceLogins = remainingGraceLogins;
-      this.isLocked = isLocked;
-      this.secondsBeforeUnlock = secondsBeforeUnlock;
-
-      isUsable = false;
-      secondsBeforeExpiration = -1;
-    }
-
-
-
-    /**
-     * Creates a new account usability response control that may be used
-     * to indicate that the account is not available and provide
-     * information about the underlying reason. It will use the default
-     * OID and criticality.
-     * 
-     * @param isInactive
-     *          Indicates whether the user's account has been
-     *          inactivated by an administrator.
-     * @param isReset
-     *          Indicates whether the user's password has been reset by
-     *          an administrator.
-     * @param isExpired
-     *          Indicates whether the user's password is expired.
-     * @param remainingGraceLogins
-     *          The number of grace logins remaining. A value of zero
-     *          indicates that there are none remaining. A value of -1
-     *          indicates that grace login functionality is not enabled.
-     * @param isLocked
-     *          Indicates whether the user's account is currently locked
-     *          out.
-     * @param secondsBeforeUnlock
-     *          The length of time in seconds until the account is
-     *          unlocked. A value of -1 indicates that the account will
-     *          not be automatically unlocked and must be reset by an
-     *          administrator.
-     */
-    public Response(boolean isInactive, boolean isReset,
-        boolean isExpired, int remainingGraceLogins, boolean isLocked,
-        int secondsBeforeUnlock)
-    {
-      this(false, isInactive, isReset, isExpired, remainingGraceLogins,
-          isLocked, secondsBeforeUnlock);
-    }
-
-
-
-    /**
-     * Creates a new account usability response control that may be used
-     * to indicate that the account is available and provide the number
-     * of seconds until expiration. It will use the default OID and
-     * criticality.
-     * 
-     * @param isCritical
-     *          Indicates whether this control should be considered
-     *          critical in processing the request.
-     * @param secondsBeforeExpiration
-     *          The length of time in seconds until the user's password
-     *          expires, or -1 if the user's password will not expire or
-     *          the expiration time is unknown.
-     */
-    public Response(boolean isCritical, int secondsBeforeExpiration)
-    {
-      super(OID_ACCOUNT_USABLE_CONTROL, isCritical);
-
-      this.secondsBeforeExpiration = secondsBeforeExpiration;
-
-      isUsable = true;
-      isInactive = false;
-      isReset = false;
-      isExpired = false;
-      remainingGraceLogins = -1;
-      isLocked = false;
-      secondsBeforeUnlock = 0;
-    }
-
-
-
-    /**
-     * Creates a new account usability response control that may be used
-     * to indicate that the account is available and provide the number
-     * of seconds until expiration. It will use the default OID and
-     * criticality.
-     * 
-     * @param secondsBeforeExpiration
-     *          The length of time in seconds until the user's password
-     *          expires, or -1 if the user's password will not expire or
-     *          the expiration time is unknown.
-     */
-    public Response(int secondsBeforeExpiration)
-    {
-      this(false, secondsBeforeExpiration);
-    }
-
-
-
-    /**
-     * Retrieves the number of remaining grace logins for the user. This
-     * value is unreliable if the user's password is not expired.
-     * 
-     * @return The number of remaining grace logins for the user, or -1
-     *         if the grace logins feature is not enabled for the user.
-     */
-    public int getRemainingGraceLogins()
-    {
-      return remainingGraceLogins;
-    }
-
-
-
-    /**
-     * Retrieves the length of time in seconds before the user's
-     * password expires. This value is unreliable if the account is not
-     * available.
-     * 
-     * @return The length of time in seconds before the user's password
-     *         expires, or -1 if it is unknown or password expiration is
-     *         not enabled for the user.
-     */
-    public int getSecondsBeforeExpiration()
-    {
-      return secondsBeforeExpiration;
-    }
-
-
-
-    /**
-     * Retrieves the length of time in seconds before the user's account
-     * is automatically unlocked. This value is unreliable is the user's
-     * account is not locked.
-     * 
-     * @return The length of time in seconds before the user's account
-     *         is automatically unlocked, or -1 if it requires
-     *         administrative action to unlock the account.
-     */
-    public int getSecondsBeforeUnlock()
-    {
-      return secondsBeforeUnlock;
-    }
-
-
-
-    @Override
-    public ByteString getValue()
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-      try
-      {
-        writeValue(writer);
-        return buffer.toByteString();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-    }
-
-
-
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    /**
-     * Indicates whether the user's password is expired.
-     * 
-     * @return <CODE>true</CODE> if the user's password is expired, or
-     *         <CODE>false</CODE> if not.
-     */
-    public boolean isExpired()
-    {
-      return isExpired;
-    }
-
-
-
-    /**
-     * Indicates whether the user's account has been inactivated by an
-     * administrator.
-     * 
-     * @return <CODE>true</CODE> if the user's account has been
-     *         inactivated by an administrator, or <CODE>false</CODE> if
-     *         not.
-     */
-    public boolean isInactive()
-    {
-      return isInactive;
-    }
-
-
-
-    /**
-     * Indicates whether the user's account is locked for some reason.
-     * 
-     * @return <CODE>true</CODE> if the user's account is locked, or
-     *         <CODE>false</CODE> if it is not.
-     */
-    public boolean isLocked()
-    {
-      return isLocked;
-    }
-
-
-
-    /**
-     * Indicates whether the user's password has been administratively
-     * reset and the user must change that password before any other
-     * operations will be allowed.
-     * 
-     * @return <CODE>true</CODE> if the user's password has been
-     *         administratively reset, or <CODE>false</CODE> if not.
-     */
-    public boolean isReset()
-    {
-      return isReset;
-    }
-
-
-
-    /**
-     * Indicates whether the associated user account is available for
-     * use.
-     * 
-     * @return <CODE>true</CODE> if the associated user account is
-     *         available, or <CODE>false</CODE> if not.
-     */
-    public boolean isUsable()
-    {
-      return isUsable;
-    }
-
-
-
-    /**
-     * Appends a string representation of this password policy response
-     * control to the provided buffer.
-     * 
-     * @param buffer
-     *          The buffer to which the information should be appended.
-     */
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("AccountUsableResponseControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", isUsable=");
-      buffer.append(isUsable);
-      if (isUsable)
-      {
-        buffer.append(",secondsBeforeExpiration=");
-        buffer.append(secondsBeforeExpiration);
-      }
-      else
-      {
-        buffer.append(",isInactive=");
-        buffer.append(isInactive);
-        buffer.append(",isReset=");
-        buffer.append(isReset);
-        buffer.append(",isExpired=");
-        buffer.append(isExpired);
-        buffer.append(",remainingGraceLogins=");
-        buffer.append(remainingGraceLogins);
-        buffer.append(",isLocked=");
-        buffer.append(isLocked);
-        buffer.append(",secondsBeforeUnlock=");
-        buffer.append(secondsBeforeUnlock);
-      }
-
-      buffer.append(")");
-    }
-
-
-
-    /**
-     * Writes this control's value to an ASN.1 writer.
-     * 
-     * @param writer
-     *          The ASN.1 output stream to write to.
-     * @throws IOException
-     *           If a problem occurs while writing to the stream.
-     */
-    public void writeValue(ASN1Writer writer) throws IOException
-    {
-      if (secondsBeforeExpiration < 0)
-      {
-        writer.writeInteger(TYPE_SECONDS_BEFORE_EXPIRATION,
-            secondsBeforeExpiration);
-      }
-      else
-      {
-        writer.writeStartSequence(TYPE_MORE_INFO);
-        if (isInactive)
-        {
-          writer.writeBoolean(TYPE_INACTIVE, true);
-        }
-
-        if (isReset)
-        {
-          writer.writeBoolean(TYPE_RESET, true);
-        }
-
-        if (isExpired)
-        {
-          writer.writeBoolean(TYPE_EXPIRED, true);
-
-          if (remainingGraceLogins >= 0)
-          {
-            writer.writeInteger(TYPE_REMAINING_GRACE_LOGINS,
-                remainingGraceLogins);
-          }
-        }
-
-        if (isLocked)
-        {
-          writer.writeInteger(TYPE_SECONDS_BEFORE_UNLOCK,
-              secondsBeforeUnlock);
-        }
-        writer.writeEndSequence();
-      }
-    }
-  }
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private static final class RequestDecoder implements
-      ControlDecoder<Request>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Request decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value != null)
-      {
-        LocalizableMessage message = ERR_ACCTUSABLEREQ_CONTROL_HAS_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      return new Request(isCritical);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_ACCOUNT_USABLE_CONTROL;
-    }
-
-  }
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class ResponseDecoder implements
-      ControlDecoder<Response>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Response decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        // The response control must always have a value.
-        LocalizableMessage message = ERR_ACCTUSABLERES_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      try
-      {
-        ASN1Reader reader = ASN1.getReader(value);
-        switch (reader.peekType())
-        {
-        case TYPE_SECONDS_BEFORE_EXPIRATION:
-          int secondsBeforeExpiration = (int) reader.readInteger();
-          return new Response(isCritical, secondsBeforeExpiration);
-        case TYPE_MORE_INFO:
-          boolean isInactive = false;
-          boolean isReset = false;
-          boolean isExpired = false;
-          boolean isLocked = false;
-          int remainingGraceLogins = -1;
-          int secondsBeforeUnlock = 0;
-
-          reader.readStartSequence();
-          if (reader.hasNextElement()
-              && (reader.peekType() == TYPE_INACTIVE))
-          {
-            isInactive = reader.readBoolean();
-          }
-          if (reader.hasNextElement()
-              && (reader.peekType() == TYPE_RESET))
-          {
-            isReset = reader.readBoolean();
-          }
-          if (reader.hasNextElement()
-              && (reader.peekType() == TYPE_EXPIRED))
-          {
-            isExpired = reader.readBoolean();
-          }
-          if (reader.hasNextElement()
-              && (reader.peekType() == TYPE_REMAINING_GRACE_LOGINS))
-          {
-            remainingGraceLogins = (int) reader.readInteger();
-          }
-          if (reader.hasNextElement()
-              && (reader.peekType() == TYPE_SECONDS_BEFORE_UNLOCK))
-          {
-            isLocked = true;
-            secondsBeforeUnlock = (int) reader.readInteger();
-          }
-          reader.readEndSequence();
-
-          return new Response(isCritical, isInactive, isReset,
-              isExpired, remainingGraceLogins, isLocked,
-              secondsBeforeUnlock);
-
-        default:
-          LocalizableMessage message = ERR_ACCTUSABLERES_UNKNOWN_VALUE_ELEMENT_TYPE
-              .get(byteToHex(reader.peekType()));
-          throw DecodeException.error(message);
-        }
-      }
-      catch (IOException e)
-      {
-        StaticUtils.DEBUG_LOG.throwing(
-            "AccountUsabilityControl.ResponseDecoder", "decode", e);
-
-        LocalizableMessage message = ERR_ACCTUSABLERES_DECODE_ERROR
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message);
-      }
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_ACCOUNT_USABLE_CONTROL;
-    }
-
-  }
-
-
-
-  /**
-   * The BER type to use for the seconds before expiration when the
-   * account is available.
-   */
-  private static final byte TYPE_SECONDS_BEFORE_EXPIRATION = (byte) 0x80;
-
-  /**
-   * The BER type to use for the MORE_INFO sequence when the account is
-   * not available.
-   */
-  private static final byte TYPE_MORE_INFO = (byte) 0xA1;
-
-  /**
-   * The BER type to use for the MORE_INFO element that indicates that
-   * the account has been inactivated.
-   */
-  private static final byte TYPE_INACTIVE = (byte) 0x80;
-
-  /**
-   * The BER type to use for the MORE_INFO element that indicates that
-   * the password has been administratively reset.
-   */
-  private static final byte TYPE_RESET = (byte) 0x81;
-
-  /**
-   * The BER type to use for the MORE_INFO element that indicates that
-   * the user's password is expired.
-   */
-  private static final byte TYPE_EXPIRED = (byte) 0x82;
-
-  /**
-   * The BER type to use for the MORE_INFO element that provides the
-   * number of remaining grace logins.
-   */
-  private static final byte TYPE_REMAINING_GRACE_LOGINS = (byte) 0x83;
-
-  /**
-   * The BER type to use for the MORE_INFO element that indicates that
-   * the password has been administratively reset.
-   */
-  private static final byte TYPE_SECONDS_BEFORE_UNLOCK = (byte) 0x84;
-
-  /**
-   * The Control Decoder that can be used to decode the request control.
-   */
-  public static final ControlDecoder<Request> REQUEST_DECODER = new RequestDecoder();
-
-  /**
-   * The Control Decoder that can be used to decode the response
-   * control.
-   */
-  public static final ControlDecoder<Response> RESPONSE_DECODER = new ResponseDecoder();
-}
diff --git a/sdk/src/org/opends/sdk/controls/AssertionControl.java b/sdk/src/org/opends/sdk/controls/AssertionControl.java
deleted file mode 100644
index 2affdc6..0000000
--- a/sdk/src/org/opends/sdk/controls/AssertionControl.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.*;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.ldap.LDAPUtils;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * Assertion control.
- */
-public class AssertionControl extends Control
-{
-  /**
-   * The IANA-assigned OID for the LDAP assertion control.
-   */
-  public static final String OID_LDAP_ASSERTION = "1.3.6.1.1.12";
-
-
-
-  /**
-   * Decodes a assertion control from a byte string.
-   */
-  private final static class Decoder implements
-      ControlDecoder<AssertionControl>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public AssertionControl decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_LDAPASSERT_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      Filter filter;
-      try
-      {
-        filter = LDAPUtils.decodeFilter(reader);
-      }
-      catch (IOException e)
-      {
-        throw DecodeException.error(
-            ERR_LDAPASSERT_INVALID_CONTROL_VALUE
-                .get(getExceptionMessage(e)), e);
-      }
-
-      return new AssertionControl(isCritical, filter);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getOID()
-    {
-      return OID_LDAP_ASSERTION;
-    }
-
-  }
-
-
-
-  /**
-   * A control decoder which can be used to decode assertion controls.
-   */
-  public static final ControlDecoder<AssertionControl> DECODER = new Decoder();
-
-  // The assertion filter.
-  private final Filter filter;
-
-
-
-  /**
-   * Creates a new assertion using the default OID and the provided
-   * criticality and assertion filter.
-   * 
-   * @param isCritical
-   *          Indicates whether this control should be considered
-   *          critical to the operation processing.
-   * @param filter
-   *          The assertion filter.
-   */
-  public AssertionControl(boolean isCritical, Filter filter)
-  {
-    super(OID_LDAP_ASSERTION, isCritical);
-
-    Validator.ensureNotNull(filter);
-    this.filter = filter;
-  }
-
-
-
-  /**
-   * Returns the assertion filter.
-   * 
-   * @return The assertion filter.
-   */
-  public Filter getFilter()
-  {
-    return filter;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ByteString getValue()
-  {
-    ByteStringBuilder buffer = new ByteStringBuilder();
-    ASN1Writer writer = ASN1.getWriter(buffer);
-    try
-    {
-      LDAPUtils.encodeFilter(writer, filter);
-      return buffer.toByteString();
-    }
-    catch (IOException ioe)
-    {
-      // This should never happen unless there is a bug somewhere.
-      throw new RuntimeException(ioe);
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean hasValue()
-  {
-    return true;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("AssertionControl(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(", filter=\"");
-    filter.toString(buffer);
-    buffer.append("\")");
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/AssertionRequestControl.java b/sdk/src/org/opends/sdk/controls/AssertionRequestControl.java
new file mode 100644
index 0000000..2571fda
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/AssertionRequestControl.java
@@ -0,0 +1,242 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_LDAPASSERT_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_LDAPASSERT_INVALID_CONTROL_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_LDAPASSERT_NO_CONTROL_VALUE;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+
+import com.sun.opends.sdk.ldap.LDAPUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The assertion request control as defined in RFC 4528. The Assertion control
+ * allows a client to specify that a directory operation should only be
+ * processed if an assertion applied to the target entry of the operation is
+ * true. It can be used to construct "test and set", "test and clear", and other
+ * conditional operations.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4528">RFC 4528 - Lightweight
+ *      Directory Access Protocol (LDAP) Assertion Control </a>
+ */
+public final class AssertionRequestControl implements Control
+{
+  /**
+   * The IANA-assigned OID for the LDAP assertion request control.
+   */
+  public static final String OID = "1.3.6.1.1.12";
+
+  /**
+   * A decoder which can be used for decoding the LDAP assertion request
+   * control.
+   */
+  public static final ControlDecoder<AssertionRequestControl> DECODER =
+    new ControlDecoder<AssertionRequestControl>()
+  {
+
+    public AssertionRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof AssertionRequestControl)
+      {
+        return (AssertionRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_LDAPASSERT_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The response control must always have a value.
+        final LocalizableMessage message = ERR_LDAPASSERT_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      Filter filter;
+      try
+      {
+        filter = LDAPUtils.decodeFilter(reader);
+      }
+      catch (final IOException e)
+      {
+        throw DecodeException.error(ERR_LDAPASSERT_INVALID_CONTROL_VALUE
+            .get(getExceptionMessage(e)), e);
+      }
+
+      return new AssertionRequestControl(control.isCritical(), filter);
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new assertion using the provided criticality and assertion
+   * filter.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param filter
+   *          The assertion filter.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code filter} was {@code null}.
+   */
+  public static AssertionRequestControl newControl(final boolean isCritical,
+      final Filter filter) throws NullPointerException
+  {
+    return new AssertionRequestControl(isCritical, filter);
+  }
+
+
+
+  // The assertion filter.
+  private final Filter filter;
+
+  private final boolean isCritical;
+
+
+
+  // Prevent direct instantiation.
+  private AssertionRequestControl(final boolean isCritical, final Filter filter)
+  {
+    Validator.ensureNotNull(filter);
+    this.isCritical = isCritical;
+    this.filter = filter;
+  }
+
+
+
+  /**
+   * Returns the assertion filter.
+   *
+   * @return The assertion filter.
+   */
+  public Filter getFilter()
+  {
+    return filter;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      LDAPUtils.encodeFilter(writer, filter);
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("AssertionRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", filter=\"");
+    builder.append(filter.toString());
+    builder.append("\")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/AuthorizationIdentityControl.java b/sdk/src/org/opends/sdk/controls/AuthorizationIdentityControl.java
deleted file mode 100644
index cbf1442..0000000
--- a/sdk/src/org/opends/sdk/controls/AuthorizationIdentityControl.java
+++ /dev/null
@@ -1,295 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements the authorization identity control as defined
- * in RFC 3829.
- */
-public class AuthorizationIdentityControl
-{
-  /**
-   * The OID for the authorization identity request control.
-   */
-  public static final String OID_AUTHZID_REQUEST = "2.16.840.1.113730.3.4.16";
-
-  /**
-   * The OID for the authorization identity response control.
-   */
-  public static final String OID_AUTHZID_RESPONSE = "2.16.840.1.113730.3.4.15";
-
-
-
-  /**
-   * This class implements the authorization identity request control as
-   * defined in RFC 3829.
-   */
-  public static class Request extends Control
-  {
-    public Request()
-    {
-      super(OID_AUTHZID_RESPONSE, false);
-    }
-
-
-
-    public Request(boolean isCritical)
-    {
-      super(OID_AUTHZID_RESPONSE, isCritical);
-    }
-
-
-
-    @Override
-    public ByteString getValue()
-    {
-      return null;
-    }
-
-
-
-    @Override
-    public boolean hasValue()
-    {
-      return false;
-    }
-
-
-
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("AuthorizationIdentityRequestControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(")");
-    }
-  }
-
-
-
-  public static class Response extends Control
-  {
-    // The authorization ID for this control.
-    private String authorizationID;
-
-
-
-    /**
-     * Creates a new authorization identity response control with the
-     * provided information.
-     * 
-     * @param isCritical
-     *          Indicates whether this control should be considered
-     *          critical in processing the request.
-     * @param authorizationDN
-     *          The authorization DN for this control.
-     */
-    public Response(boolean isCritical, DN authorizationDN)
-    {
-      super(OID_AUTHZID_REQUEST, isCritical);
-
-      Validator.ensureNotNull(authorizationDN);
-      if (authorizationDN == null)
-      {
-        this.authorizationID = "dn:";
-      }
-      else
-      {
-        this.authorizationID = "dn:" + authorizationDN.toString();
-      }
-    }
-
-
-
-    /**
-     * Creates a new authorization identity response control with the
-     * provided information.
-     * 
-     * @param isCritical
-     *          Indicates whether this control should be considered
-     *          critical in processing the request.
-     * @param authorizationID
-     *          The authorization ID for this control.
-     */
-    public Response(boolean isCritical, String authorizationID)
-    {
-      super(OID_AUTHZID_RESPONSE, isCritical);
-
-      Validator.ensureNotNull(authorizationID);
-      this.authorizationID = authorizationID;
-    }
-
-
-
-    /**
-     * Creates a new authorization identity response control with the
-     * provided information.
-     * 
-     * @param authorizationDN
-     *          The authorization DN for this control.
-     */
-    public Response(DN authorizationDN)
-    {
-      this(false, authorizationDN);
-    }
-
-
-
-    /**
-     * Creates a new authorization identity response control with the
-     * provided information.
-     * 
-     * @param authorizationID
-     *          The authorization ID for this control.
-     */
-    public Response(String authorizationID)
-    {
-      this(false, authorizationID);
-    }
-
-
-
-    /**
-     * Retrieves the authorization ID for this authorization identity
-     * response control.
-     * 
-     * @return The authorization ID for this authorization identity
-     *         response control.
-     */
-    public String getAuthorizationID()
-    {
-      return authorizationID;
-    }
-
-
-
-    @Override
-    public ByteString getValue()
-    {
-      return ByteString.valueOf(authorizationID);
-    }
-
-
-
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    /**
-     * Appends a string representation of this authorization identity
-     * response control to the provided buffer.
-     * 
-     * @param buffer
-     *          The buffer to which the information should be appended.
-     */
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("AuthorizationIdentityResponseControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", authzID=\"");
-      buffer.append(authorizationID);
-      buffer.append("\")");
-    }
-
-  }
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private static final class RequestDecoder implements
-      ControlDecoder<Request>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Request decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value != null)
-      {
-        LocalizableMessage message = ERR_AUTHZIDREQ_CONTROL_HAS_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      return new Request(isCritical);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_AUTHZID_REQUEST;
-    }
-  }
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class ResponseDecoder implements
-      ControlDecoder<Response>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Response decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_AUTHZIDRESP_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      String authID = value.toString();
-      return new Response(isCritical, authID);
-
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_AUTHZID_RESPONSE;
-    }
-  }
-
-
-
-  /**
-   * The Control Decoder that can be used to decode the request control.
-   */
-  public static final ControlDecoder<Request> REQUEST_DECODER = new RequestDecoder();
-
-  /**
-   * The Control Decoder that can be used to decode the response
-   * control.
-   */
-  public static final ControlDecoder<Response> RESPONSE_DECODER = new ResponseDecoder();
-}
diff --git a/sdk/src/org/opends/sdk/controls/AuthorizationIdentityRequestControl.java b/sdk/src/org/opends/sdk/controls/AuthorizationIdentityRequestControl.java
new file mode 100644
index 0000000..532684d
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/AuthorizationIdentityRequestControl.java
@@ -0,0 +1,199 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_AUTHZIDREQ_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_AUTHZIDREQ_CONTROL_HAS_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The authorization request control as defined in RFC 3829. The authorization
+ * identity control extends the Lightweight Directory Access Protocol (LDAP)
+ * bind operation with a mechanism for requesting and returning the
+ * authorization identity it establishes.
+ *
+ * @see AuthorizationIdentityResponseControl
+ * @see org.opends.sdk.requests.WhoAmIExtendedRequest
+ * @see <a href="http://tools.ietf.org/html/rfc3829">RFC 3829 - Lightweight
+ *      Directory Access Protocol (LDAP) Authorization Identity Request and
+ *      Response Controls </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4532">RFC 4532 - Lightweight
+ *      Directory Access Protocol (LDAP) "Who am I?" Operation </a>
+ */
+public final class AuthorizationIdentityRequestControl implements Control
+{
+  /**
+   * The OID for the authorization identity request control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.16";
+
+  private final boolean isCritical;
+
+  private static final AuthorizationIdentityRequestControl CRITICAL_INSTANCE =
+    new AuthorizationIdentityRequestControl(true);
+
+  private static final AuthorizationIdentityRequestControl
+    NONCRITICAL_INSTANCE= new AuthorizationIdentityRequestControl(false);
+
+  /**
+   * A decoder which can be used for decoding the authorization identity request
+   * control.
+   */
+  public static final ControlDecoder<AuthorizationIdentityRequestControl>
+    DECODER = new ControlDecoder<AuthorizationIdentityRequestControl>()
+  {
+
+    public AuthorizationIdentityRequestControl decodeControl(
+        final Control control, final DecodeOptions options)
+        throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof AuthorizationIdentityRequestControl)
+      {
+        return (AuthorizationIdentityRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_AUTHZIDREQ_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (control.hasValue())
+      {
+        final LocalizableMessage message = ERR_AUTHZIDREQ_CONTROL_HAS_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new authorization identity request control having the provided
+   * criticality.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @return The new control.
+   */
+  public static AuthorizationIdentityRequestControl newControl(
+      final boolean isCritical)
+  {
+    return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+  }
+
+
+
+  // Prevent direct instantiation.
+  private AuthorizationIdentityRequestControl(final boolean isCritical)
+  {
+    this.isCritical = isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("AuthorizationIdentityRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/AuthorizationIdentityResponseControl.java b/sdk/src/org/opends/sdk/controls/AuthorizationIdentityResponseControl.java
new file mode 100644
index 0000000..b4de1fa
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/AuthorizationIdentityResponseControl.java
@@ -0,0 +1,226 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_AUTHZIDRESP_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_AUTHZIDRESP_NO_CONTROL_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The authorization response control as defined in RFC 3829. The authorization
+ * identity control extends the Lightweight Directory Access Protocol (LDAP)
+ * bind operation with a mechanism for requesting and returning the
+ * authorization identity it establishes.
+ * <p>
+ * The authorization identity is specified using an authorization ID, or {@code
+ * authzId}, as defined in RFC 4513 section 5.2.1.8.
+ *
+ * @see AuthorizationIdentityRequestControl
+ * @see org.opends.sdk.requests.WhoAmIExtendedRequest
+ * @see <a href="http://tools.ietf.org/html/rfc3829">RFC 3829 - Lightweight
+ *      Directory Access Protocol (LDAP) Authorization Identity Request and
+ *      Response Controls </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4532">RFC 4532 - Lightweight
+ *      Directory Access Protocol (LDAP) "Who am I?" Operation </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513 -
+ *      SASL Authorization Identities (authzId) </a>
+ */
+public final class AuthorizationIdentityResponseControl implements Control
+{
+
+  /**
+   * The OID for the authorization identity response control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.15";
+
+
+
+  /**
+   * Creates a new authorization identity response control using the provided
+   * authorization ID.
+   *
+   * @param authorizationID
+   *          The authorization ID for this control.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code authorizationID} was {@code null}.
+   */
+  public static AuthorizationIdentityResponseControl newControl(
+      final String authorizationID) throws NullPointerException
+  {
+    return new AuthorizationIdentityResponseControl(false, authorizationID);
+  }
+
+
+
+  // The authorization ID for this control.
+  private final String authorizationID;
+
+  private final boolean isCritical;
+
+  /**
+   * A decoder which can be used for decoding the authorization identity
+   * response control.
+   */
+  public static final ControlDecoder<AuthorizationIdentityResponseControl>
+    DECODER = new ControlDecoder<AuthorizationIdentityResponseControl>()
+  {
+
+    public AuthorizationIdentityResponseControl decodeControl(
+        final Control control, final DecodeOptions options)
+        throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof AuthorizationIdentityResponseControl)
+      {
+        return (AuthorizationIdentityResponseControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_AUTHZIDRESP_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The response control must always have a value.
+        final LocalizableMessage message = ERR_AUTHZIDRESP_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final String authID = control.getValue().toString();
+      return new AuthorizationIdentityResponseControl(control.isCritical(),
+          authID);
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  // Prevent direct instantiation.
+  private AuthorizationIdentityResponseControl(final boolean isCritical,
+      final String authorizationID)
+  {
+    Validator.ensureNotNull(authorizationID);
+    this.isCritical = isCritical;
+    this.authorizationID = authorizationID;
+  }
+
+
+
+  /**
+   * Returns the authorization ID of the user. The authorization ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @return The authorization ID of the user.
+   */
+  public String getAuthorizationID()
+  {
+    return authorizationID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return ByteString.valueOf(authorizationID);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("AuthorizationIdentityResponseControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", authzID=\"");
+    builder.append(authorizationID);
+    builder.append("\")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/Control.java b/sdk/src/org/opends/sdk/controls/Control.java
index cb034c8..880ab89 100644
--- a/sdk/src/org/opends/sdk/controls/Control.java
+++ b/sdk/src/org/opends/sdk/controls/Control.java
@@ -1,3 +1,29 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
 package org.opends.sdk.controls;
 
 
@@ -7,74 +33,64 @@
 
 
 /**
- * Created by IntelliJ IDEA. User: boli Date: Jun 29, 2009 Time:
- * 10:59:19 AM To change this template use File | Settings | File
- * Templates.
+ * Controls provide a mechanism whereby the semantics and arguments of existing
+ * LDAP operations may be extended. One or more controls may be attached to a
+ * single LDAP message. A control only affects the semantics of the message it
+ * is attached to. Controls sent by clients are termed 'request controls', and
+ * those sent by servers are termed 'response controls'.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4511">RFC 4511 - Lightweight
+ *      Directory Access Protocol (LDAP): The Protocol </a>
  */
-public abstract class Control
+public interface Control
 {
-  // The criticality for this control.
-  protected final boolean isCritical;
 
-  // The OID for this control.
-  protected final String oid;
-
-
-
-  public Control(String oid, boolean isCritical)
-  {
-    this.isCritical = isCritical;
-    this.oid = oid;
-  }
+  /**
+   * Returns the numeric OID associated with this control.
+   *
+   * @return The numeric OID associated with this control.
+   */
+  String getOID();
 
 
 
   /**
-   * Retrieves the OID for this control.
-   * 
-   * @return The OID for this control.
+   * Returns the value, if any, associated with this control. Its format is
+   * defined by the specification of this control.
+   *
+   * @return The value associated with this control, or {@code null} if there is
+   *         no value.
    */
-  public String getOID()
-  {
-    return oid;
-  }
-
-
-
-  public abstract ByteString getValue();
-
-
-
-  public abstract boolean hasValue();
+  ByteString getValue();
 
 
 
   /**
-   * Indicates whether this control should be considered critical in
-   * processing the request.
-   * 
-   * @return <CODE>true</CODE> if this code should be considered
-   *         critical, or <CODE>false</CODE> if not.
+   * Returns {@code true} if this control has a value. In some circumstances it
+   * may be useful to determine if a control has a value, without actually
+   * calculating the value and incurring any performance costs.
+   *
+   * @return {@code true} if this control has a value, or {@code false} if there
+   *         is no value.
    */
-  public boolean isCritical()
-  {
-    return isCritical;
-  }
+  boolean hasValue();
 
 
 
   /**
-   * {@inheritDoc}
+   * Returns {@code true} if it is unacceptable to perform the operation without
+   * applying the semantics of this control.
+   * <p>
+   * The criticality field only has meaning in controls attached to request
+   * messages (except UnbindRequest). For controls attached to response messages
+   * and the UnbindRequest, the criticality field SHOULD be {@code false}, and
+   * MUST be ignored by the receiving protocol peer. A value of {@code true}
+   * indicates that it is unacceptable to perform the operation without applying
+   * the semantics of the control.
+   *
+   * @return {@code true} if this control must be processed by the Directory
+   *         Server, or {@code false} if it can be ignored.
    */
-  @Override
-  public String toString()
-  {
-    StringBuilder buffer = new StringBuilder();
-    toString(buffer);
-    return buffer.toString();
-  }
+  boolean isCritical();
 
-
-
-  public abstract void toString(StringBuilder buffer);
 }
diff --git a/sdk/src/org/opends/sdk/controls/ControlDecoder.java b/sdk/src/org/opends/sdk/controls/ControlDecoder.java
index 83f34f6..2d6c32e 100644
--- a/sdk/src/org/opends/sdk/controls/ControlDecoder.java
+++ b/sdk/src/org/opends/sdk/controls/ControlDecoder.java
@@ -22,51 +22,48 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2008 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
+
 package org.opends.sdk.controls;
 
 
 
-import org.opends.sdk.ByteString;
 import org.opends.sdk.DecodeException;
-import org.opends.sdk.schema.Schema;
+import org.opends.sdk.DecodeOptions;
 
 
 
 /**
- * An interface for decoding controls.
+ * A factory interface for decoding a control as a control of specific type.
  *
- * @param <T>
- *          The type of control decoded by this decoder.
+ * @param <C>
+ *          The type of control decoded by this control decoder.
  */
-public interface ControlDecoder<T extends Control>
+public interface ControlDecoder<C extends Control>
 {
-
   /**
-   * Decodes the provided control.
+   * Decodes the provided control as a {@code Control} of type {@code C}.
    *
-   * @param isCritical
-   *          Indicates whether the control should be considered
-   *          critical.
-   * @param value
-   *          The value for the control.
-   * @param schema
-   *          The schema which should be used when decoding the control,
-   *          if required.
+   * @param control
+   *          The control to be decoded.
+   * @param options
+   *          The set of decode options which should be used when decoding the
+   *          control.
    * @return The decoded control.
    * @throws DecodeException
-   *           If the control could not be decoded.
+   *           If the control contained the wrong OID, it did not have a value,
+   *           or if its value could not be decoded.
    */
-  T decode(boolean isCritical, ByteString value, Schema schema)
+  C decodeControl(Control control, DecodeOptions options)
       throws DecodeException;
 
 
 
   /**
-   * Gets the OID of the control decoded by this decoded.
+   * Returns the numeric OID associated with this control decoder.
    *
-   * @return The OID of the control decoded by this decoded.
+   * @return The numeric OID associated with this control decoder.
    */
   String getOID();
 }
diff --git a/sdk/src/org/opends/sdk/controls/EntryChangeNotificationControl.java b/sdk/src/org/opends/sdk/controls/EntryChangeNotificationControl.java
deleted file mode 100644
index 36c713e..0000000
--- a/sdk/src/org/opends/sdk/controls/EntryChangeNotificationControl.java
+++ /dev/null
@@ -1,390 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-import static org.opends.sdk.asn1.ASN1Constants.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.*;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements the entry change notification control defined
- * in draft-ietf-ldapext-psearch. It may be included in entries returned
- * in response to a persistent search operation.
- */
-public class EntryChangeNotificationControl extends Control
-{
-  /**
-   * The OID for the entry change notification control.
-   */
-  public static final String OID_ENTRY_CHANGE_NOTIFICATION = "2.16.840.1.113730.3.4.7";
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class Decoder implements
-      ControlDecoder<EntryChangeNotificationControl>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public EntryChangeNotificationControl decode(boolean isCritical,
-        ByteString value, Schema schema) throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_ECN_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      String previousDN = null;
-      long changeNumber = -1;
-      PersistentSearchChangeType changeType;
-      ASN1Reader reader = ASN1.getReader(value);
-      try
-      {
-        reader.readStartSequence();
-        changeType = PersistentSearchChangeType.valueOf(reader
-            .readEnumerated());
-
-        if (reader.hasNextElement()
-            && (reader.peekType() == UNIVERSAL_OCTET_STRING_TYPE))
-        {
-          if (changeType != PersistentSearchChangeType.MODIFY_DN)
-          {
-            LocalizableMessage message = ERR_ECN_ILLEGAL_PREVIOUS_DN.get(String
-                .valueOf(changeType));
-            throw DecodeException.error(message);
-          }
-
-          previousDN = reader.readOctetStringAsString();
-        }
-        if (reader.hasNextElement()
-            && (reader.peekType() == UNIVERSAL_INTEGER_TYPE))
-        {
-          changeNumber = reader.readInteger();
-        }
-      }
-      catch (IOException e)
-      {
-        StaticUtils.DEBUG_LOG.throwing(
-            "EntryChangeNotificationControl.Decoder", "decode", e);
-
-        LocalizableMessage message = ERR_ECN_CANNOT_DECODE_VALUE
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message, e);
-      }
-
-      return new EntryChangeNotificationControl(isCritical, changeType,
-          previousDN, changeNumber);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_ENTRY_CHANGE_NOTIFICATION;
-    }
-
-  }
-
-
-
-  /**
-   * The Control Decoder that can be used to decode this control.
-   */
-  public static final ControlDecoder<EntryChangeNotificationControl> DECODER = new Decoder();
-
-  // The previous DN for this change notification control.
-  private String previousDN;
-
-  // The change number for this change notification control.
-  private long changeNumber;
-
-  // The change type for this change notification control.
-  private final PersistentSearchChangeType changeType;
-
-
-
-  /**
-   * Creates a new entry change notification control with the provided
-   * information.
-   * 
-   * @param isCritical
-   *          Indicates whether this control should be considered
-   *          critical in processing the request.
-   * @param changeType
-   *          The change type for this change notification control.
-   */
-  public EntryChangeNotificationControl(boolean isCritical,
-      PersistentSearchChangeType changeType)
-  {
-    super(OID_ENTRY_CHANGE_NOTIFICATION, isCritical);
-
-    Validator.ensureNotNull(changeType);
-    this.changeType = changeType;
-
-    previousDN = null;
-  }
-
-
-
-  /**
-   * Creates a new entry change notification control with the provided
-   * information.
-   * 
-   * @param isCritical
-   *          Indicates whether this control should be considered
-   *          critical in processing the request.
-   * @param changeType
-   *          The change type for this change notification control.
-   * @param previousDN
-   *          The DN that the entry had prior to a modify DN operation,
-   *          or <CODE>null</CODE> if the operation was not a modify DN.
-   * @param changeNumber
-   *          The change number for the associated change, or a negative
-   *          value if no change number is available.
-   */
-  public EntryChangeNotificationControl(boolean isCritical,
-      PersistentSearchChangeType changeType, DN previousDN,
-      long changeNumber)
-  {
-    super(OID_ENTRY_CHANGE_NOTIFICATION, isCritical);
-
-    Validator.ensureNotNull(changeType);
-    this.changeType = changeType;
-
-    if (previousDN != null)
-    {
-      this.previousDN = previousDN.toString();
-    }
-    this.changeNumber = changeNumber;
-  }
-
-
-
-  /**
-   * Creates a new entry change notification control with the provided
-   * information.
-   * 
-   * @param isCritical
-   *          Indicates whether this control should be considered
-   *          critical in processing the request.
-   * @param changeType
-   *          The change type for this change notification control.
-   * @param previousDN
-   *          The DN that the entry had prior to a modify DN operation,
-   *          or <CODE>null</CODE> if the operation was not a modify DN.
-   * @param changeNumber
-   *          The change number for the associated change, or a negative
-   *          value if no change number is available.
-   */
-  public EntryChangeNotificationControl(boolean isCritical,
-      PersistentSearchChangeType changeType, String previousDN,
-      long changeNumber)
-  {
-    super(OID_ENTRY_CHANGE_NOTIFICATION, isCritical);
-
-    Validator.ensureNotNull(changeType);
-    this.changeType = changeType;
-    this.previousDN = previousDN;
-    this.changeNumber = changeNumber;
-  }
-
-
-
-  /**
-   * Creates a new entry change notification control with the provided
-   * information.
-   * 
-   * @param changeType
-   *          The change type for this change notification control.
-   */
-  public EntryChangeNotificationControl(
-      PersistentSearchChangeType changeType)
-  {
-    this(false, changeType);
-  }
-
-
-
-  /**
-   * Creates a new entry change notification control with the provided
-   * information.
-   * 
-   * @param changeType
-   *          The change type for this change notification control.
-   * @param previousDN
-   *          The DN that the entry had prior to a modify DN operation,
-   *          or <CODE>null</CODE> if the operation was not a modify DN.
-   * @param changeNumber
-   *          The change number for the associated change, or a negative
-   *          value if no change number is available.
-   */
-  public EntryChangeNotificationControl(
-      PersistentSearchChangeType changeType, DN previousDN,
-      long changeNumber)
-  {
-    this(false, changeType, previousDN, changeNumber);
-  }
-
-
-
-  /**
-   * Creates a new entry change notification control with the provided
-   * information.
-   * 
-   * @param changeType
-   *          The change type for this change notification control.
-   * @param previousDN
-   *          The DN that the entry had prior to a modify DN operation,
-   *          or <CODE>null</CODE> if the operation was not a modify DN.
-   * @param changeNumber
-   *          The change number for the associated change, or a negative
-   *          value if no change number is available.
-   */
-  public EntryChangeNotificationControl(
-      PersistentSearchChangeType changeType, String previousDN,
-      long changeNumber)
-  {
-    this(false, changeType, previousDN, changeNumber);
-  }
-
-
-
-  /**
-   * Retrieves the change number for this entry change notification
-   * control.
-   * 
-   * @return The change number for this entry change notification
-   *         control, or a negative value if no change number is
-   *         available.
-   */
-  public long getChangeNumber()
-  {
-    return changeNumber;
-  }
-
-
-
-  /**
-   * Retrieves the change type for this entry change notification
-   * control.
-   * 
-   * @return The change type for this entry change notification control.
-   */
-  public PersistentSearchChangeType getChangeType()
-  {
-    return changeType;
-  }
-
-
-
-  /**
-   * Retrieves the previous DN for this entry change notification
-   * control.
-   * 
-   * @return The previous DN for this entry change notification control,
-   *         or <CODE>null</CODE> if there is none.
-   */
-  public String getPreviousDN()
-  {
-    return previousDN;
-  }
-
-
-
-  @Override
-  public ByteString getValue()
-  {
-    ByteStringBuilder buffer = new ByteStringBuilder();
-    ASN1Writer writer = ASN1.getWriter(buffer);
-    try
-    {
-      writeValue(writer);
-      return buffer.toByteString();
-    }
-    catch (IOException ioe)
-    {
-      // This should never happen unless there is a bug somewhere.
-      throw new RuntimeException(ioe);
-    }
-  }
-
-
-
-  @Override
-  public boolean hasValue()
-  {
-    return true;
-  }
-
-
-
-  /**
-   * Appends a string representation of this entry change notification
-   * control to the provided buffer.
-   * 
-   * @param buffer
-   *          The buffer to which the information should be appended.
-   */
-  @Override
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("EntryChangeNotificationControl(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(", changeType=");
-    buffer.append(changeType.toString());
-    buffer.append(", previousDN=\"");
-    buffer.append(previousDN);
-    buffer.append("\"");
-    buffer.append(", changeNumber=");
-    buffer.append(changeNumber);
-    buffer.append(")");
-  }
-
-
-
-  /**
-   * Writes this control's value to an ASN.1 writer. The value (if any)
-   * must be written as an ASN1OctetString.
-   * 
-   * @param writer
-   *          The ASN.1 output stream to write to.
-   * @throws java.io.IOException
-   *           If a problem occurs while writing to the stream.
-   */
-  public void writeValue(ASN1Writer writer) throws IOException
-  {
-    writer.writeStartSequence();
-    writer.writeInteger(changeType.intValue());
-
-    if (previousDN != null)
-    {
-      writer.writeOctetString(previousDN);
-    }
-
-    if (changeNumber > 0)
-    {
-      writer.writeInteger(changeNumber);
-    }
-    writer.writeEndSequence();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/EntryChangeNotificationResponseControl.java b/sdk/src/org/opends/sdk/controls/EntryChangeNotificationResponseControl.java
new file mode 100644
index 0000000..1c3a5b4
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/EntryChangeNotificationResponseControl.java
@@ -0,0 +1,396 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+import static org.opends.sdk.asn1.ASN1Constants.UNIVERSAL_INTEGER_TYPE;
+import static org.opends.sdk.asn1.ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.schema.Schema;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The entry change notification response control as defined in
+ * draft-ietf-ldapext-psearch. This control provides additional information
+ * about the change the caused a particular entry to be returned as the result
+ * of a persistent search.
+ *
+ * @see PersistentSearchRequestControl
+ * @see PersistentSearchChangeType
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-ietf-ldapext-psearch">draft-ietf-ldapext-psearch
+ *      - Persistent Search: A Simple LDAP Change Notification Mechanism </a>
+ */
+public final class EntryChangeNotificationResponseControl implements Control
+{
+  /**
+   * The OID for the entry change notification response control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.7";
+
+  /**
+   * A decoder which can be used for decoding the entry change notification
+   * response control.
+   */
+  public static final ControlDecoder<EntryChangeNotificationResponseControl>
+    DECODER = new ControlDecoder<EntryChangeNotificationResponseControl>()
+  {
+
+    public EntryChangeNotificationResponseControl decodeControl(
+        final Control control, final DecodeOptions options)
+        throws DecodeException
+    {
+      Validator.ensureNotNull(control, options);
+
+      if (control instanceof EntryChangeNotificationResponseControl)
+      {
+        return (EntryChangeNotificationResponseControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_ECN_CONTROL_BAD_OID.get(control
+            .getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The response control must always have a value.
+        final LocalizableMessage message = ERR_ECN_NO_CONTROL_VALUE.get();
+        throw DecodeException.error(message);
+      }
+
+      String previousDNString = null;
+      long changeNumber = -1;
+      PersistentSearchChangeType changeType;
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      try
+      {
+        reader.readStartSequence();
+
+        final int changeTypeInt = reader.readEnumerated();
+        switch (changeTypeInt)
+        {
+        case 1:
+          changeType = PersistentSearchChangeType.ADD;
+          break;
+        case 2:
+          changeType = PersistentSearchChangeType.DELETE;
+          break;
+        case 4:
+          changeType = PersistentSearchChangeType.MODIFY;
+          break;
+        case 8:
+          changeType = PersistentSearchChangeType.MODIFY_DN;
+          break;
+        default:
+          final LocalizableMessage message = ERR_ECN_BAD_CHANGE_TYPE
+              .get(changeTypeInt);
+          throw DecodeException.error(message);
+        }
+
+        if (reader.hasNextElement()
+            && (reader.peekType() == UNIVERSAL_OCTET_STRING_TYPE))
+        {
+          if (changeType != PersistentSearchChangeType.MODIFY_DN)
+          {
+            final LocalizableMessage message = ERR_ECN_ILLEGAL_PREVIOUS_DN
+                .get(String.valueOf(changeType));
+            throw DecodeException.error(message);
+          }
+
+          previousDNString = reader.readOctetStringAsString();
+        }
+        if (reader.hasNextElement()
+            && (reader.peekType() == UNIVERSAL_INTEGER_TYPE))
+        {
+          changeNumber = reader.readInteger();
+        }
+      }
+      catch (final IOException e)
+      {
+        StaticUtils.DEBUG_LOG.throwing(
+            "EntryChangeNotificationControl.Decoder", "decode", e);
+
+        final LocalizableMessage message = ERR_ECN_CANNOT_DECODE_VALUE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+
+      final Schema schema = options.getSchemaResolver().resolveSchema(
+          previousDNString);
+      DN previousDN;
+      try
+      {
+        previousDN = DN.valueOf(previousDNString, schema);
+      }
+      catch (final LocalizedIllegalArgumentException e)
+      {
+        final LocalizableMessage message = ERR_ECN_INVALID_PREVIOUS_DN
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+
+      return new EntryChangeNotificationResponseControl(control.isCritical(),
+          changeType, previousDN, changeNumber);
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new entry change notification response control with the provided
+   * change type and optional previous distinguished name and change number.
+   *
+   * @param type
+   *          The change type for this change notification control.
+   * @param previousName
+   *          The distinguished name that the entry had prior to a modify DN
+   *          operation, or <CODE>null</CODE> if the operation was not a modify
+   *          DN.
+   * @param changeNumber
+   *          The change number for the associated change, or a negative value
+   *          if no change number is available.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code type} was {@code null}.
+   */
+  public static EntryChangeNotificationResponseControl newControl(
+      final PersistentSearchChangeType type, final DN previousName,
+      final long changeNumber) throws NullPointerException
+  {
+    return new EntryChangeNotificationResponseControl(false, type,
+        previousName, changeNumber);
+  }
+
+
+
+  /**
+   * Creates a new entry change notification response control with the provided
+   * change type and optional previous distinguished name and change number. The
+   * previous distinguished name, if provided, will be decoded using the default
+   * schema.
+   *
+   * @param type
+   *          The change type for this change notification control.
+   * @param previousName
+   *          The distinguished name that the entry had prior to a modify DN
+   *          operation, or <CODE>null</CODE> if the operation was not a modify
+   *          DN.
+   * @param changeNumber
+   *          The change number for the associated change, or a negative value
+   *          if no change number is available.
+   * @return The new control.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code previousName} is not a valid LDAP string representation
+   *           of a DN.
+   * @throws NullPointerException
+   *           If {@code type} was {@code null}.
+   */
+  public static EntryChangeNotificationResponseControl newControl(
+      final PersistentSearchChangeType type, final String previousName,
+      final long changeNumber) throws LocalizedIllegalArgumentException,
+      NullPointerException
+  {
+    return new EntryChangeNotificationResponseControl(false, type, DN
+        .valueOf(previousName), changeNumber);
+  }
+
+
+
+  // The previous DN for this change notification control.
+  private final DN previousName;
+
+  // The change number for this change notification control.
+  private final long changeNumber;
+
+  // The change type for this change notification control.
+  private final PersistentSearchChangeType changeType;
+
+  private final boolean isCritical;
+
+
+
+  private EntryChangeNotificationResponseControl(final boolean isCritical,
+      final PersistentSearchChangeType changeType, final DN previousName,
+      final long changeNumber)
+  {
+    Validator.ensureNotNull(changeType);
+    this.isCritical = isCritical;
+    this.changeType = changeType;
+    this.previousName = previousName;
+    this.changeNumber = changeNumber;
+  }
+
+
+
+  /**
+   * Returns the change number for this entry change notification control.
+   *
+   * @return The change number for this entry change notification control, or a
+   *         negative value if no change number is available.
+   */
+  public long getChangeNumber()
+  {
+    return changeNumber;
+  }
+
+
+
+  /**
+   * Returns the change type for this entry change notification control.
+   *
+   * @return The change type for this entry change notification control.
+   */
+  public PersistentSearchChangeType getChangeType()
+  {
+    return changeType;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * Returns the distinguished name that the entry had prior to a modify DN
+   * operation, or <CODE>null</CODE> if the operation was not a modify DN.
+   *
+   * @return The distinguished name that the entry had prior to a modify DN
+   *         operation.
+   */
+  public DN getPreviousName()
+  {
+    return previousName;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      writer.writeInteger(changeType.intValue());
+
+      if (previousName != null)
+      {
+        writer.writeOctetString(previousName.toString());
+      }
+
+      if (changeNumber > 0)
+      {
+        writer.writeInteger(changeNumber);
+      }
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("EntryChangeNotificationResponseControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", changeType=");
+    builder.append(changeType.toString());
+    builder.append(", previousDN=\"");
+    builder.append(previousName);
+    builder.append("\"");
+    builder.append(", changeNumber=");
+    builder.append(changeNumber);
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/GenericControl.java b/sdk/src/org/opends/sdk/controls/GenericControl.java
index 406a07f..0f681d3 100644
--- a/sdk/src/org/opends/sdk/controls/GenericControl.java
+++ b/sdk/src/org/opends/sdk/controls/GenericControl.java
@@ -22,9 +22,8 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
-
 package org.opends.sdk.controls;
 
 
@@ -32,84 +31,144 @@
 import org.opends.sdk.ByteString;
 
 import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
 
 
 
 /**
- * A generic raw request. A raw control is a control whose parameters
- * have not been fully decoded.
- * <p>
- * TODO: this should be hooked into the remaining controls class
- * hierarchy.
- * <p>
- * TODO: push ASN1 encoding into ASN1 package.
+ * A generic control which can be used to represent arbitrary raw request and
+ * response controls.
  */
-public final class GenericControl extends Control
+public final class GenericControl implements Control
 {
 
-  // The control value.
+  /**
+   * Creates a new control having the same OID, criticality, and value as the
+   * provided control.
+   *
+   * @param control
+   *          The control to be copied.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code control} was {@code null}.
+   */
+  public static GenericControl newControl(final Control control)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(control);
+
+    if (control instanceof GenericControl)
+    {
+      return (GenericControl) control;
+    }
+
+    return new GenericControl(control.getOID(), control.isCritical(), control
+        .getValue());
+  }
+
+
+
+  /**
+   * Creates a new non-critical control having the provided OID and no value.
+   *
+   * @param oid
+   *          The numeric OID associated with this control.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code oid} was {@code null}.
+   */
+  public static GenericControl newControl(final String oid)
+      throws NullPointerException
+  {
+    return new GenericControl(oid, false, null);
+  }
+
+
+
+  /**
+   * Creates a new control having the provided OID and criticality, but no
+   * value.
+   *
+   * @param oid
+   *          The numeric OID associated with this control.
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code oid} was {@code null}.
+   */
+  public static GenericControl newControl(final String oid,
+      final boolean isCritical) throws NullPointerException
+  {
+    return new GenericControl(oid, isCritical, null);
+  }
+
+
+
+  /**
+   * Creates a new control having the provided OID, criticality, and value.
+   * <p>
+   * If {@code value} is not an instance of {@code ByteString} then it will be
+   * converted using the {@link ByteString#valueOf(Object)} method.
+   *
+   * @param oid
+   *          The numeric OID associated with this control.
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param value
+   *          The value associated with this control, or {@code null} if there
+   *          is no value. Its format is defined by the specification of this
+   *          control.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code oid} was {@code null}.
+   */
+  public static GenericControl newControl(final String oid,
+      final boolean isCritical, final Object value) throws NullPointerException
+  {
+    return new GenericControl(oid, isCritical, (value == null) ? null
+        : ByteString.valueOf(value));
+  }
+
+
+
+  private final String oid;
+
+  private final boolean isCritical;
+
   private final ByteString value;
 
 
 
-  /**
-   * Creates a new control with the specified OID. It will not be
-   * critical, and will not have a value.
-   * 
-   * @param oid
-   *          The OID for this control.
-   */
-  public GenericControl(String oid)
+  // Prevent direct instantiation.
+  private GenericControl(final String oid, final boolean isCritical,
+      final ByteString value)
   {
-    this(oid, false, null);
-  }
-
-
-
-  /**
-   * Creates a new raw control with the specified OID and criticality.
-   * It will not have a value.
-   * 
-   * @param oid
-   *          The OID for this control.
-   * @param isCritical
-   *          Indicates whether this control should be considered
-   *          critical.
-   */
-  public GenericControl(String oid, boolean isCritical)
-  {
-    this(oid, isCritical, null);
-  }
-
-
-
-  /**
-   * Creates a new raw control with the specified OID, criticality, and
-   * value.
-   * 
-   * @param oid
-   *          The OID for this control.
-   * @param isCritical
-   *          Indicates whether this control should be considered
-   *          critical.
-   * @param value
-   *          The value for this control.
-   */
-  public GenericControl(String oid, boolean isCritical, ByteString value)
-  {
-    super(oid, isCritical);
+    Validator.ensureNotNull(oid);
+    this.oid = oid;
+    this.isCritical = isCritical;
     this.value = value;
   }
 
 
 
   /**
-   * Retrieves the value for this control.
-   * 
-   * @return The value for this control, or <CODE>null</CODE> if there
-   *         is no value.
+   * {@inheritDoc}
    */
-  @Override
+  public String getOID()
+  {
+    return oid;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
   public ByteString getValue()
   {
     return value;
@@ -118,41 +177,43 @@
 
 
   /**
-   * Indicates whether this control has a value.
-   * 
-   * @return <CODE>true</CODE> if this control has a value, or
-   *         <CODE>false</CODE> if it does not.
+   * {@inheritDoc}
    */
-  @Override
   public boolean hasValue()
   {
-    return (value != null);
+    return value != null;
   }
 
 
 
   /**
-   * Appends a string representation of this control to the provided
-   * buffer.
-   * 
-   * @param buffer
-   *          The buffer to which the information should be appended.
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
    */
   @Override
-  public void toString(StringBuilder buffer)
+  public String toString()
   {
-    buffer.append("Control(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-
+    final StringBuilder builder = new StringBuilder();
+    builder.append("Control(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
     if (value != null)
     {
-      buffer.append(", value=");
-      StaticUtils.toHexPlusAscii(value, buffer, 4);
+      builder.append(", value=");
+      StaticUtils.toHexPlusAscii(value, builder, 4);
     }
-
-    buffer.append(")");
+    builder.append(")");
+    return builder.toString();
   }
 
 }
diff --git a/sdk/src/org/opends/sdk/controls/GetEffectiveRightsRequestControl.java b/sdk/src/org/opends/sdk/controls/GetEffectiveRightsRequestControl.java
index 8820f0a..b5d77eb 100644
--- a/sdk/src/org/opends/sdk/controls/GetEffectiveRightsRequestControl.java
+++ b/sdk/src/org/opends/sdk/controls/GetEffectiveRightsRequestControl.java
@@ -1,8 +1,35 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
 package org.opends.sdk.controls;
 
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
 
 import java.io.IOException;
 import java.util.*;
@@ -13,221 +40,343 @@
 import org.opends.sdk.asn1.ASN1Writer;
 import org.opends.sdk.schema.AttributeType;
 import org.opends.sdk.schema.Schema;
+import org.opends.sdk.schema.UnknownSchemaElementException;
 
 import com.sun.opends.sdk.util.Validator;
 
 
 
 /**
- * This class partially implements the geteffectiverights control as
- * defined
- * in draft-ietf-ldapext-acl-model-08.txt. The main differences are:
- * - The response control is not supported. Instead the dseecompat
- * geteffectiverights control implementation creates attributes
- * containing
- * right information strings and adds those attributes to the
- * entry being returned. The attribute type names are dynamically
- * created;
- * see the dseecompat's AciGetEffectiveRights class for details.
- * - The dseecompat implementation allows additional attribute types
- * in the request control for which rights information can be returned.
- * These are known as the specified attribute types.
- * The dseecompat request control value is the following: <BR>
- * 
- * <PRE>
+ * A partial implementation of the get effective rights request control as
+ * defined in draft-ietf-ldapext-acl-model. The main differences are:
+ * <ul>
+ * <li>The response control is not supported. Instead the OpenDS implementation
+ * creates attributes containing effective rights information with the entry
+ * being returned.
+ * <li>The attribute type names are dynamically created.
+ * <li>The set of attributes for which effective rights information is to be
+ * requested can be included in the control.
+ * </ul>
+ * The get effective rights request control value has the following BER
+ * encoding:
+ *
+ * <pre>
  *  GetRightsControl ::= SEQUENCE {
- *    authzId    authzId
+ *    authzId    authzId  -- Only the "dn:DN" form is supported.
  *    attributes  SEQUENCE OF AttributeType
  *  }
- *   -- Only the "dn:DN form is supported.
- * 
- * </PRE>
+ * </pre>
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-ietf-ldapext-acl-model">draft-ietf-ldapext-acl-model
+ *      - Access Control Model for LDAPv3 </a>
  **/
-public class GetEffectiveRightsRequestControl extends Control
+public final class GetEffectiveRightsRequestControl implements Control
 {
   /**
-   * The OID for the get effective rights control.
+   * The OID for the get effective rights request control.
    */
-  public static final String OID_GET_EFFECTIVE_RIGHTS = "1.3.6.1.4.1.42.2.27.9.5.2";
-
-
+  public static final String OID = "1.3.6.1.4.1.42.2.27.9.5.2";
 
   /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
+   * A decoder which can be used for decoding the get effective rights request
+   * control.
    */
-  private static final class Decoder implements
-      ControlDecoder<GetEffectiveRightsRequestControl>
+  public static final ControlDecoder<GetEffectiveRightsRequestControl> DECODER =
+    new ControlDecoder<GetEffectiveRightsRequestControl>()
   {
-    /**
-     * {@inheritDoc}
-     */
-    public GetEffectiveRightsRequestControl decode(boolean isCritical,
-        ByteString value, Schema schema) throws DecodeException
+
+    public GetEffectiveRightsRequestControl decodeControl(
+        final Control control, final DecodeOptions options)
+        throws DecodeException
     {
-      // If the value is null create a GetEffectiveRightsRequestControl
-      // class with null authzDN and attribute list, else try to
-      // decode the value.
-      if (value == null)
-        return new GetEffectiveRightsRequestControl(isCritical,
-            (String) null);
-      else
+      Validator.ensureNotNull(control);
+
+      if (control instanceof GetEffectiveRightsRequestControl)
       {
-        ASN1Reader reader = ASN1.getReader(value);
-        String authzDN;
-        List<String> attrs = Collections.emptyList();
+        return (GetEffectiveRightsRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_GETEFFECTIVERIGHTS_CONTROL_BAD_OID
+            .get(control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      DN authorizationDN = null;
+      List<AttributeType> attributes = Collections.emptyList();
+
+      if (control.hasValue())
+      {
+        final ASN1Reader reader = ASN1.getReader(control.getValue());
         try
         {
           reader.readStartSequence();
-          String authzIDString = reader.readOctetStringAsString();
-          String lowerAuthzIDString = authzIDString.toLowerCase();
+          final String authzIDString = reader.readOctetStringAsString();
+          final String lowerAuthzIDString = authzIDString.toLowerCase();
+          Schema schema;
+
           // Make sure authzId starts with "dn:" and is a valid DN.
           if (lowerAuthzIDString.startsWith("dn:"))
-            authzDN = authzIDString.substring(3);
+          {
+            final String authorizationDNString = authzIDString.substring(3);
+            schema = options.getSchemaResolver().resolveSchema(
+                authorizationDNString);
+            try
+            {
+              authorizationDN = DN.valueOf(authorizationDNString, schema);
+            }
+            catch (final LocalizedIllegalArgumentException e)
+            {
+              final LocalizableMessage message = ERR_GETEFFECTIVERIGHTS_INVALID_AUTHZIDDN
+                  .get(getExceptionMessage(e));
+              throw DecodeException.error(message, e);
+            }
+          }
           else
           {
-            LocalizableMessage message = INFO_GETEFFECTIVERIGHTS_INVALID_AUTHZID
+            final LocalizableMessage message = INFO_GETEFFECTIVERIGHTS_INVALID_AUTHZID
                 .get(lowerAuthzIDString);
             throw DecodeException.error(message);
           }
+
           // There is an sequence containing an attribute list, try to
           // decode it.
           if (reader.hasNextElement())
           {
-            attrs = new LinkedList<String>();
+            attributes = new LinkedList<AttributeType>();
             reader.readStartSequence();
             while (reader.hasNextElement())
             {
-              // Decode as an octet string.
-              attrs.add(reader.readOctetStringAsString());
+              // Decode as an attribute type.
+              final String attributeName = reader.readOctetStringAsString();
+              AttributeType attributeType;
+              try
+              {
+                // FIXME: we're using the schema associated with the authzid
+                // which is not really correct. We should really use the schema
+                // associated with the entry.
+                attributeType = schema.getAttributeType(attributeName);
+              }
+              catch (final UnknownSchemaElementException e)
+              {
+                final LocalizableMessage message = ERR_GETEFFECTIVERIGHTS_UNKNOWN_ATTRIBUTE
+                    .get(attributeName);
+                throw DecodeException.error(message, e);
+              }
+              attributes.add(attributeType);
             }
             reader.readEndSequence();
+            attributes = Collections.unmodifiableList(attributes);
           }
           reader.readEndSequence();
         }
-        catch (IOException e)
+        catch (final IOException e)
         {
-          LocalizableMessage message = INFO_GETEFFECTIVERIGHTS_DECODE_ERROR.get(e
-              .getMessage());
+          final LocalizableMessage message = INFO_GETEFFECTIVERIGHTS_DECODE_ERROR
+              .get(e.getMessage());
           throw DecodeException.error(message);
         }
-
-        return new GetEffectiveRightsRequestControl(isCritical,
-            authzDN, attrs);
       }
+
+      return new GetEffectiveRightsRequestControl(control.isCritical(),
+          authorizationDN, attributes);
+
     }
 
 
 
     public String getOID()
     {
-      return OID_GET_EFFECTIVE_RIGHTS;
+      return OID;
     }
+  };
 
+
+
+  /**
+   * Creates a new get effective rights request control with the provided
+   * criticality, optional authorization name and attribute list.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param authorizationName
+   *          The distinguished name of the user for which effective rights are
+   *          to be returned, or {@code null} if the client's authentication ID
+   *          is to be used.
+   * @param attributes
+   *          The list of attributes for which effective rights are to be
+   *          returned, which may be empty indicating that no attribute rights
+   *          are to be returned.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code attributes} was {@code null}.
+   */
+  public static GetEffectiveRightsRequestControl newControl(
+      final boolean isCritical, final DN authorizationName,
+      final Collection<AttributeType> attributes) throws NullPointerException
+  {
+    Validator.ensureNotNull(attributes);
+
+    final Collection<AttributeType> copyOfAttributes = Collections
+        .unmodifiableList(new ArrayList<AttributeType>(attributes));
+    return new GetEffectiveRightsRequestControl(isCritical, authorizationName,
+        copyOfAttributes);
   }
 
 
 
   /**
-   * The Control Decoder that can be used to decode this control.
+   * Creates a new get effective rights request control with the provided
+   * criticality, optional authorization name and attribute list. The
+   * authorization name and attributes, if provided, will be decoded using the
+   * default schema.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param authorizationName
+   *          The distinguished name of the user for which effective rights are
+   *          to be returned, or {@code null} if the client's authentication ID
+   *          is to be used.
+   * @param attributes
+   *          The list of attributes for which effective rights are to be
+   *          returned, which may be empty indicating that no attribute rights
+   *          are to be returned.
+   * @return The new control.
+   * @throws UnknownSchemaElementException
+   *           If the default schema is a strict schema and one or more of the
+   *           requested attribute types were not recognized.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authorizationName} is not a valid LDAP string
+   *           representation of a DN.
+   * @throws NullPointerException
+   *           If {@code attributes} was {@code null}.
    */
-  public static final ControlDecoder<GetEffectiveRightsRequestControl> DECODER = new Decoder();
-
-  // The raw DN representing the authzId
-  private String authorizationDN = null;
-
-  // The raw DN representing the authzId
-  private List<String> attributes = null;
-
-
-
-  public GetEffectiveRightsRequestControl(boolean isCritical,
-      String authorizationDN, String... attributes)
+  public static GetEffectiveRightsRequestControl newControl(
+      final boolean isCritical, final String authorizationName,
+      final String... attributes) throws UnknownSchemaElementException,
+      LocalizedIllegalArgumentException, NullPointerException
   {
-    super(OID_GET_EFFECTIVE_RIGHTS, isCritical);
+    Validator.ensureNotNull((Object) attributes);
 
-    this.authorizationDN = authorizationDN;
-    if (attributes != null)
+    final DN dn = authorizationName == null ? null : DN
+        .valueOf(authorizationName);
+
+    List<AttributeType> copyOfAttributes;
+    if (attributes != null && attributes.length > 0)
     {
-      this.attributes = new ArrayList<String>(attributes.length);
-      this.attributes.addAll(Arrays.asList(attributes));
-    }
-    else
-    {
-      this.attributes = Collections.emptyList();
-    }
-  }
-
-
-
-  public GetEffectiveRightsRequestControl(boolean isCritical,
-      DN authorizationDN, AttributeType... attributes)
-  {
-    super(OID_GET_EFFECTIVE_RIGHTS, isCritical);
-
-    Validator.ensureNotNull(authorizationDN, attributes);
-
-    this.authorizationDN = authorizationDN.toString();
-
-    if (attributes != null)
-    {
-      for (AttributeType attr : attributes)
+      copyOfAttributes = new ArrayList<AttributeType>(attributes.length);
+      for (final String attribute : attributes)
       {
-        this.attributes = new ArrayList<String>(attributes.length);
-        this.attributes.add(attr.getNameOrOID());
+        copyOfAttributes.add(Schema.getDefaultSchema().getAttributeType(
+            attribute));
       }
+      copyOfAttributes = Collections.unmodifiableList(copyOfAttributes);
     }
     else
     {
-      this.attributes = Collections.emptyList();
+      copyOfAttributes = Collections.emptyList();
     }
+
+    return new GetEffectiveRightsRequestControl(isCritical, dn,
+        copyOfAttributes);
   }
 
 
 
-  private GetEffectiveRightsRequestControl(boolean isCritical,
-      String authorizationDN, List<String> attributes)
+  // The DN representing the authzId (may be null meaning use the client's DN).
+  private final DN authorizationName;
+
+  // The unmodifiable list of attributes to be queried (may be empty).
+  private final Collection<AttributeType> attributes;
+
+  private final boolean isCritical;
+
+
+
+  private GetEffectiveRightsRequestControl(final boolean isCritical,
+      final DN authorizationName, final Collection<AttributeType> attributes)
   {
-    super(OID_GET_EFFECTIVE_RIGHTS, isCritical);
-
-    Validator.ensureNotNull(authorizationDN, attributes);
-
-    this.authorizationDN = authorizationDN;
+    this.isCritical = isCritical;
+    this.authorizationName = authorizationName;
     this.attributes = attributes;
   }
 
 
 
+  /**
+   * Returns an unmodifiable list of attributes for which effective rights are
+   * to be returned, which may be empty indicating that no attribute rights are
+   * to be returned.
+   *
+   * @return The unmodifiable list of attributes for which effective rights are
+   *         to be returned.
+   */
+  public Collection<AttributeType> getAttributes()
+  {
+    return attributes;
+  }
+
+
+
+  /**
+   * Returns the distinguished name of the user for which effective rights are
+   * to be returned, or {@code null} if the client's authentication ID is to be
+   * used.
+   *
+   * @return The distinguished name of the user for which effective rights are
+   *         to be returned.
+   */
+  public DN getAuthorizationName()
+  {
+    return authorizationName;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
   public ByteString getValue()
   {
-    if (authorizationDN == null && attributes.isEmpty())
-    {
-      return ByteString.empty();
-    }
-
-    ByteStringBuilder buffer = new ByteStringBuilder();
-    ASN1Writer writer = ASN1.getWriter(buffer);
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
     try
     {
       writer.writeStartSequence();
-      if (authorizationDN != null)
+      if (authorizationName != null)
       {
-        writer.writeOctetString("dn:" + authorizationDN);
+        writer.writeOctetString("dn:" + authorizationName);
       }
 
       if (!attributes.isEmpty())
       {
         writer.writeStartSequence();
-        for (String attr : attributes)
+        for (final AttributeType attribute : attributes)
         {
-          writer.writeOctetString(attr);
+          writer.writeOctetString(attribute.getNameOrOID());
         }
         writer.writeEndSequence();
       }
       writer.writeEndSequence();
       return buffer.toByteString();
     }
-    catch (IOException ioe)
+    catch (final IOException ioe)
     {
       // This should never happen unless there is a bug somewhere.
       throw new RuntimeException(ioe);
@@ -236,32 +385,43 @@
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   public boolean hasValue()
   {
-    return authorizationDN != null || !attributes.isEmpty();
+    return authorizationName != null || !attributes.isEmpty();
   }
 
 
 
   /**
-   * Appends a string representation of this proxied auth v2 control to
-   * the provided buffer.
-   * 
-   * @param buffer
-   *          The buffer to which the information should be appended.
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
    */
   @Override
-  public void toString(StringBuilder buffer)
+  public String toString()
   {
-    buffer.append("GetEffectiveRightsRequestControl(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(", authorizationDN=\"");
-    buffer.append(authorizationDN);
-    buffer.append("\"");
-    buffer.append(", attributes=(");
-    buffer.append(attributes);
-    buffer.append("))");
+    final StringBuilder builder = new StringBuilder();
+    builder.append("GetEffectiveRightsRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", authorizationDN=\"");
+    builder.append(authorizationName);
+    builder.append("\"");
+    builder.append(", attributes=(");
+    builder.append(attributes);
+    builder.append("))");
+    return builder.toString();
   }
 }
diff --git a/sdk/src/org/opends/sdk/controls/ManageDsaITRequestControl.java b/sdk/src/org/opends/sdk/controls/ManageDsaITRequestControl.java
new file mode 100644
index 0000000..55a5db7
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/ManageDsaITRequestControl.java
@@ -0,0 +1,194 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_MANAGEDSAIT_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_MANAGEDSAIT_INVALID_CONTROL_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The ManageDsaIT request control as defined in RFC 3296. This control allows
+ * manipulation of referral and other special objects as normal objects.
+ * <p>
+ * When this control is present in the request, the server will not generate a
+ * referral or continuation reference based upon information held in referral
+ * objects and instead will treat the referral object as a normal entry. The
+ * server, however, is still free to return referrals for other reasons.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3296">RFC 3296 - Named
+ *      Subordinate References in Lightweight Directory Access Protocol (LDAP)
+ *      Directories </a>
+ */
+public final class ManageDsaITRequestControl implements Control
+{
+  /**
+   * The OID for the ManageDsaIT request control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.2";
+
+  private static final ManageDsaITRequestControl CRITICAL_INSTANCE = new ManageDsaITRequestControl(
+      true);
+  private static final ManageDsaITRequestControl NONCRITICAL_INSTANCE =
+    new ManageDsaITRequestControl(false);
+
+  /**
+   * A decoder which can be used for decoding the Manage DsaIT request control.
+   */
+  public static final ControlDecoder<ManageDsaITRequestControl> DECODER =
+    new ControlDecoder<ManageDsaITRequestControl>()
+  {
+
+    public ManageDsaITRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof ManageDsaITRequestControl)
+      {
+        return (ManageDsaITRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_MANAGEDSAIT_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (control.hasValue())
+      {
+        final LocalizableMessage message = ERR_MANAGEDSAIT_INVALID_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new ManageDsaIT request control having the provided criticality.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @return The new control.
+   */
+  public static ManageDsaITRequestControl newControl(final boolean isCritical)
+  {
+    return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+  }
+
+
+
+  private final boolean isCritical;
+
+
+
+  private ManageDsaITRequestControl(final boolean isCritical)
+  {
+    this.isCritical = isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("ManageDsaITRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/MatchedValuesControl.java b/sdk/src/org/opends/sdk/controls/MatchedValuesControl.java
deleted file mode 100644
index 84a175e..0000000
--- a/sdk/src/org/opends/sdk/controls/MatchedValuesControl.java
+++ /dev/null
@@ -1,350 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.opends.sdk.*;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.ldap.LDAPUtils;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements the matched values control as defined in RFC
- * 3876. It may be included in a search request to indicate that only
- * attribute values matching one or more filters contained in the
- * matched values control should be returned to the client.
- */
-public class MatchedValuesControl extends Control
-{
-  /**
-   * The OID for the matched values control used to specify which
-   * particular attribute values should be returned in a search result
-   * entry.
-   */
-  public static final String OID_MATCHED_VALUES = "1.2.826.0.1.3344810.2.3";
-
-
-
-  /**
-   * Visitor for validating matched values filters.
-   */
-  private static final class FilterValidator extends
-      AbstractFilterVisitor<LocalizedIllegalArgumentException, Filter>
-  {
-
-    @Override
-    public LocalizedIllegalArgumentException visitAndFilter(Filter p,
-        List<Filter> subFilters)
-    {
-      LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_AND.get(p.toString());
-      return new LocalizedIllegalArgumentException(message);
-    }
-
-
-
-    @Override
-    public LocalizedIllegalArgumentException visitExtensibleMatchFilter(
-        Filter p, String matchingRule, String attributeDescription,
-        ByteString assertionValue, boolean dnAttributes)
-    {
-      if (dnAttributes)
-      {
-        LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_EXT.get(p.toString());
-        return new LocalizedIllegalArgumentException(message);
-      }
-      else
-      {
-        return null;
-      }
-    }
-
-
-
-    @Override
-    public LocalizedIllegalArgumentException visitNotFilter(Filter p,
-        Filter subFilter)
-    {
-      LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_NOT.get(p.toString());
-      return new LocalizedIllegalArgumentException(message);
-    }
-
-
-
-    @Override
-    public LocalizedIllegalArgumentException visitOrFilter(Filter p,
-        List<Filter> subFilters)
-    {
-      LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_OR.get(p.toString());
-      return new LocalizedIllegalArgumentException(message);
-    }
-
-
-
-    @Override
-    public LocalizedIllegalArgumentException visitUnrecognizedFilter(
-        Filter p, byte filterTag, ByteString filterBytes)
-    {
-      LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_UNRECOGNIZED.get(p
-          .toString(), filterTag);
-      return new LocalizedIllegalArgumentException(message);
-    }
-  }
-
-
-
-  /**
-   * Decodes a matched values control from a byte string.
-   */
-  private final static class Decoder implements
-      ControlDecoder<MatchedValuesControl>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public MatchedValuesControl decode(boolean isCritical,
-        ByteString value, Schema schema) throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_MATCHEDVALUES_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      try
-      {
-        reader.readStartSequence();
-        if (!reader.hasNextElement())
-        {
-          LocalizableMessage message = ERR_MATCHEDVALUES_NO_FILTERS.get();
-          throw DecodeException.error(message);
-        }
-
-        LinkedList<Filter> filters = new LinkedList<Filter>();
-        do
-        {
-          Filter filter = LDAPUtils.decodeFilter(reader);
-
-          try
-          {
-            validateFilter(filter);
-          }
-          catch (LocalizedIllegalArgumentException e)
-          {
-            throw DecodeException
-                .error(e.getMessageObject());
-          }
-
-          filters.add(filter);
-        } while (reader.hasNextElement());
-
-        reader.readEndSequence();
-
-        return new MatchedValuesControl(isCritical, Collections
-            .unmodifiableList(filters));
-      }
-      catch (IOException e)
-      {
-        StaticUtils.DEBUG_LOG.throwing("MatchedValuesControl.Decoder",
-            "decode", e);
-
-        LocalizableMessage message = ERR_MATCHEDVALUES_CANNOT_DECODE_VALUE_AS_SEQUENCE
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getOID()
-    {
-      return OID_MATCHED_VALUES;
-    }
-
-  }
-
-
-
-  /**
-   * A control decoder which can be used to decode matched values
-   * controls.
-   */
-  public static final ControlDecoder<MatchedValuesControl> DECODER = new Decoder();
-
-  private static final FilterValidator FILTER_VALIDATOR = new FilterValidator();
-
-
-
-  private static void validateFilter(final Filter filter)
-      throws LocalizedIllegalArgumentException
-  {
-    LocalizedIllegalArgumentException e = filter.accept(
-        FILTER_VALIDATOR, filter);
-    if (e != null)
-    {
-      throw e;
-    }
-  }
-
-
-
-  private List<Filter> filters;
-
-
-
-  /**
-   * Creates a new matched values control using the default OID and the
-   * provided criticality and set of filters.
-   *
-   * @param isCritical
-   *          Indicates whether this control should be considered
-   *          critical to the operation processing.
-   * @param filters
-   *          The list of matched value filters.
-   * @throws LocalizedIllegalArgumentException
-   *           If one of the filters is not permitted by the matched
-   *           values control.
-   */
-  public MatchedValuesControl(boolean isCritical, Filter... filters)
-      throws LocalizedIllegalArgumentException
-  {
-    super(OID_MATCHED_VALUES, isCritical);
-
-    Validator.ensureNotNull((Object) filters);
-    Validator.ensureTrue(filters.length > 0, "filters is empty");
-
-    if (filters.length == 1)
-    {
-      validateFilter(filters[0]);
-      this.filters = Collections.singletonList(filters[0]);
-    }
-    else
-    {
-      LinkedList<Filter> list = new LinkedList<Filter>();
-      for (Filter filter : filters)
-      {
-        validateFilter(filter);
-        list.add(filter);
-      }
-      this.filters = Collections.unmodifiableList(list);
-    }
-  }
-
-
-
-  private MatchedValuesControl(boolean isCritical, List<Filter> filters)
-  {
-    super(OID_MATCHED_VALUES, isCritical);
-    this.filters = filters;
-  }
-
-
-
-  /**
-   * Returns an {@code Iterable} containing the list of filters
-   * associated with this matched values control.
-   *
-   * @return An {@code Iterable} containing the list of filters.
-   */
-  public Iterable<Filter> getFilters()
-  {
-    return filters;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public ByteString getValue()
-  {
-    ByteStringBuilder buffer = new ByteStringBuilder();
-    ASN1Writer writer = ASN1.getWriter(buffer);
-    try
-    {
-      writer.writeStartSequence();
-      for (Filter f : filters)
-      {
-        LDAPUtils.encodeFilter(writer, f);
-      }
-      writer.writeEndSequence();
-      return buffer.toByteString();
-    }
-    catch (IOException ioe)
-    {
-      // This should never happen unless there is a bug somewhere.
-      throw new RuntimeException(ioe);
-    }
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public boolean hasValue()
-  {
-    return true;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("MatchingValuesControl(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(")");
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/MatchedValuesRequestControl.java b/sdk/src/org/opends/sdk/controls/MatchedValuesRequestControl.java
new file mode 100644
index 0000000..b28d9b1
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/MatchedValuesRequestControl.java
@@ -0,0 +1,463 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+
+import com.sun.opends.sdk.ldap.LDAPUtils;
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The matched values request control as defined in RFC 3876. The matched values
+ * control may be included in a search request to indicate that only attribute
+ * values matching one or more filters contained in the matched values control
+ * should be returned to the client.
+ * <p>
+ * The matched values request control supports a subset of the LDAP filter type
+ * defined in RFC 4511, and is defined as follows:
+ *
+ * <pre>
+ * ValuesReturnFilter ::= SEQUENCE OF SimpleFilterItem
+ *
+ * SimpleFilterItem ::= CHOICE {
+ *        equalityMatch   [3] AttributeValueAssertion,
+ *        substrings      [4] SubstringFilter,
+ *        greaterOrEqual  [5] AttributeValueAssertion,
+ *        lessOrEqual     [6] AttributeValueAssertion,
+ *        present         [7] AttributeDescription,
+ *        approxMatch     [8] AttributeValueAssertion,
+ *        extensibleMatch [9] SimpleMatchingAssertion }
+ *
+ * SimpleMatchingAssertion ::= SEQUENCE {
+ *        matchingRule    [1] MatchingRuleId OPTIONAL,
+ *        type            [2] AttributeDescription OPTIONAL,
+ * --- at least one of the above must be present
+ *        matchValue      [3] AssertionValue}
+ * </pre>
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3876">RFC 3876 - Returning
+ *      Matched Values with the Lightweight Directory Access Protocol version 3
+ *      (LDAPv3) </a>
+ */
+public final class MatchedValuesRequestControl implements Control
+{
+  /**
+   * Visitor for validating matched values filters.
+   */
+  private static final class FilterValidator extends
+      AbstractFilterVisitor<LocalizedIllegalArgumentException, Filter>
+  {
+
+    @Override
+    public LocalizedIllegalArgumentException visitAndFilter(final Filter p,
+        final List<Filter> subFilters)
+    {
+      final LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_AND.get(p
+          .toString());
+      return new LocalizedIllegalArgumentException(message);
+    }
+
+
+
+    @Override
+    public LocalizedIllegalArgumentException visitExtensibleMatchFilter(
+        final Filter p, final String matchingRule,
+        final String attributeDescription, final ByteString assertionValue,
+        final boolean dnAttributes)
+    {
+      if (dnAttributes)
+      {
+        final LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_EXT.get(p
+            .toString());
+        return new LocalizedIllegalArgumentException(message);
+      }
+      else
+      {
+        return null;
+      }
+    }
+
+
+
+    @Override
+    public LocalizedIllegalArgumentException visitNotFilter(final Filter p,
+        final Filter subFilter)
+    {
+      final LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_NOT.get(p
+          .toString());
+      return new LocalizedIllegalArgumentException(message);
+    }
+
+
+
+    @Override
+    public LocalizedIllegalArgumentException visitOrFilter(final Filter p,
+        final List<Filter> subFilters)
+    {
+      final LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_OR.get(p
+          .toString());
+      return new LocalizedIllegalArgumentException(message);
+    }
+
+
+
+    @Override
+    public LocalizedIllegalArgumentException visitUnrecognizedFilter(
+        final Filter p, final byte filterTag, final ByteString filterBytes)
+    {
+      final LocalizableMessage message = ERR_MVFILTER_BAD_FILTER_UNRECOGNIZED
+          .get(p.toString(), filterTag);
+      return new LocalizedIllegalArgumentException(message);
+    }
+  }
+
+
+
+  /**
+   * The OID for the matched values request control used to specify which
+   * particular attribute values should be returned in a search result entry.
+   */
+  public static final String OID = "1.2.826.0.1.3344810.2.3";
+
+  /**
+   * A decoder which can be used for decoding the matched values request
+   * control.
+   */
+  public static final ControlDecoder<MatchedValuesRequestControl> DECODER =
+    new ControlDecoder<MatchedValuesRequestControl>()
+  {
+
+    public MatchedValuesRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof MatchedValuesRequestControl)
+      {
+        return (MatchedValuesRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_MATCHEDVALUES_CONTROL_BAD_OID
+            .get(control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The response control must always have a value.
+        final LocalizableMessage message = ERR_MATCHEDVALUES_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      try
+      {
+        reader.readStartSequence();
+        if (!reader.hasNextElement())
+        {
+          final LocalizableMessage message = ERR_MATCHEDVALUES_NO_FILTERS.get();
+          throw DecodeException.error(message);
+        }
+
+        final LinkedList<Filter> filters = new LinkedList<Filter>();
+        do
+        {
+          final Filter filter = LDAPUtils.decodeFilter(reader);
+
+          try
+          {
+            validateFilter(filter);
+          }
+          catch (final LocalizedIllegalArgumentException e)
+          {
+            throw DecodeException.error(e.getMessageObject());
+          }
+
+          filters.add(filter);
+        }
+        while (reader.hasNextElement());
+
+        reader.readEndSequence();
+
+        return new MatchedValuesRequestControl(control.isCritical(),
+            Collections.unmodifiableList(filters));
+      }
+      catch (final IOException e)
+      {
+        StaticUtils.DEBUG_LOG.throwing("MatchedValuesControl.Decoder",
+            "decode", e);
+
+        final LocalizableMessage message = ERR_MATCHEDVALUES_CANNOT_DECODE_VALUE_AS_SEQUENCE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message);
+      }
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+  private static final FilterValidator FILTER_VALIDATOR = new FilterValidator();
+
+
+
+  /**
+   * Creates a new matched values request control with the provided criticality
+   * and list of filters.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param filters
+   *          The list of filters of which at least one must match an attribute
+   *          value in order for the attribute value to be returned to the
+   *          client. The list must not be empty.
+   * @return The new control.
+   * @throws LocalizedIllegalArgumentException
+   *           If one or more filters failed to conform to the filter
+   *           constraints defined in RFC 3876.
+   * @throws IllegalArgumentException
+   *           If {@code filters} was empty.
+   * @throws NullPointerException
+   *           If {@code filters} was {@code null}.
+   */
+  public static MatchedValuesRequestControl newControl(
+      final boolean isCritical, final Collection<Filter> filters)
+      throws LocalizedIllegalArgumentException, IllegalArgumentException,
+      NullPointerException
+  {
+    Validator.ensureNotNull(filters);
+    Validator.ensureTrue(filters.size() > 0, "filters is empty");
+
+    List<Filter> copyOfFilters;
+    if (filters.size() == 1)
+    {
+      copyOfFilters = Collections.singletonList(validateFilter(filters
+          .iterator().next()));
+    }
+    else
+    {
+      copyOfFilters = new ArrayList<Filter>(filters.size());
+      for (final Filter filter : filters)
+      {
+        copyOfFilters.add(validateFilter(filter));
+      }
+      copyOfFilters = Collections.unmodifiableList(copyOfFilters);
+    }
+
+    return new MatchedValuesRequestControl(isCritical, copyOfFilters);
+  }
+
+
+
+  /**
+   * Creates a new matched values request control with the provided criticality
+   * and list of filters.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param firstFilter
+   *          The first matched values filter.
+   * @param remainingFilters
+   *          The remaining matched values filter, may be {@code null} or empty.
+   * @return The new control.
+   * @throws LocalizedIllegalArgumentException
+   *           If one or more filters could not be parsed, or if one or more
+   *           filters failed to conform to the filter constraints defined in
+   *           RFC 3876.
+   * @throws NullPointerException
+   *           If {@code firstFilter} was {@code null}.
+   */
+  public static MatchedValuesRequestControl newControl(
+      final boolean isCritical, final String firstFilter,
+      final String... remainingFilters)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(firstFilter);
+
+    List<Filter> filters;
+    if (remainingFilters == null || remainingFilters.length == 0)
+    {
+      filters = Collections.singletonList(validateFilter(Filter
+          .valueOf(firstFilter)));
+    }
+    else
+    {
+      filters = new ArrayList<Filter>(1 + remainingFilters.length);
+      filters.add(validateFilter(Filter.valueOf(firstFilter)));
+      for (final String filter : remainingFilters)
+      {
+        filters.add(validateFilter(Filter.valueOf(filter)));
+      }
+      filters = Collections.unmodifiableList(filters);
+    }
+
+    return new MatchedValuesRequestControl(isCritical, filters);
+  }
+
+
+
+  private static Filter validateFilter(final Filter filter)
+      throws LocalizedIllegalArgumentException
+  {
+    final LocalizedIllegalArgumentException e = filter.accept(FILTER_VALIDATOR,
+        filter);
+    if (e != null)
+    {
+      throw e;
+    }
+    return filter;
+  }
+
+
+
+  private final Collection<Filter> filters;
+
+  private final boolean isCritical;
+
+
+
+  private MatchedValuesRequestControl(final boolean isCritical,
+      final Collection<Filter> filters)
+  {
+    this.isCritical = isCritical;
+    this.filters = filters;
+  }
+
+
+
+  /**
+   * Returns an unmodifiable collection containing the list of filters
+   * associated with this matched values control.
+   *
+   * @return An unmodifiable collection containing the list of filters
+   *         associated with this matched values control.
+   */
+  public Collection<Filter> getFilters()
+  {
+    return filters;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      for (final Filter f : filters)
+      {
+        LDAPUtils.encodeFilter(writer, f);
+      }
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("MatchedValuesRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/PagedResultsControl.java b/sdk/src/org/opends/sdk/controls/PagedResultsControl.java
deleted file mode 100644
index c30b60e..0000000
--- a/sdk/src/org/opends/sdk/controls/PagedResultsControl.java
+++ /dev/null
@@ -1,256 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ByteStringBuilder;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class represents a paged results control value as defined in RFC
- * 2696. The searchControlValue is an OCTET STRING wrapping the
- * BER-encoded version of the following SEQUENCE: realSearchControlValue
- * ::= SEQUENCE { size INTEGER (0..maxInt), -- requested page size from
- * client -- result set size estimate from server cookie OCTET STRING }
- */
-public class PagedResultsControl extends Control
-{
-  /**
-   * The OID for the paged results control defined in RFC 2696.
-   */
-  public static final String OID_PAGED_RESULTS_CONTROL = "1.2.840.113556.1.4.319";
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class Decoder implements
-      ControlDecoder<PagedResultsControl>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public PagedResultsControl decode(boolean isCritical,
-        ByteString value, Schema schema) throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_NULL.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      try
-      {
-        reader.readStartSequence();
-      }
-      catch (Exception e)
-      {
-        StaticUtils.DEBUG_LOG.throwing("PagedResultsControl.Decoder",
-            "decode", e);
-
-        LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SEQUENCE
-            .get(String.valueOf(e));
-        throw DecodeException.error(message, e);
-      }
-
-      int size;
-      try
-      {
-        size = (int) reader.readInteger();
-      }
-      catch (Exception e)
-      {
-        StaticUtils.DEBUG_LOG.throwing("PagedResultsControl.Decoder",
-            "decode", e);
-
-        LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SIZE.get(String
-            .valueOf(e));
-        throw DecodeException.error(message, e);
-      }
-
-      ByteString cookie;
-      try
-      {
-        cookie = reader.readOctetString();
-      }
-      catch (Exception e)
-      {
-        StaticUtils.DEBUG_LOG.throwing("PagedResultsControl.Decoder",
-            "decode", e);
-
-        LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_COOKIE
-            .get(String.valueOf(e));
-        throw DecodeException.error(message, e);
-      }
-
-      try
-      {
-        reader.readEndSequence();
-      }
-      catch (Exception e)
-      {
-        StaticUtils.DEBUG_LOG.throwing("PagedResultsControl.Decoder",
-            "decode", e);
-
-        LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SEQUENCE
-            .get(String.valueOf(e));
-        throw DecodeException.error(message, e);
-      }
-
-      return new PagedResultsControl(isCritical, size, cookie);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_PAGED_RESULTS_CONTROL;
-    }
-  }
-
-
-
-  /**
-   * The Control Decoder that can be used to decode this control.
-   */
-  public static final ControlDecoder<PagedResultsControl> DECODER = new Decoder();
-
-  /**
-   * The control value size element, which is either the requested page
-   * size from the client, or the result set size estimate from the
-   * server.
-   */
-  private final int size;
-
-  /**
-   * The control value cookie element.
-   */
-  private final ByteString cookie;
-
-
-
-  /**
-   * Creates a new paged results control with the specified information.
-   * 
-   * @param isCritical
-   *          Indicates whether this control should be considered
-   *          critical in processing the request.
-   * @param size
-   *          The size element.
-   * @param cookie
-   *          The cookie element.
-   */
-  public PagedResultsControl(boolean isCritical, int size,
-      ByteString cookie)
-  {
-    super(OID_PAGED_RESULTS_CONTROL, isCritical);
-
-    Validator.ensureNotNull(cookie);
-    this.size = size;
-    this.cookie = cookie;
-  }
-
-
-
-  /**
-   * Creates a new paged results control with the specified information.
-   * 
-   * @param size
-   *          The size element.
-   * @param cookie
-   *          The cookie element.
-   */
-  public PagedResultsControl(int size, ByteString cookie)
-  {
-    this(false, size, cookie);
-  }
-
-
-
-  /**
-   * Get the control value cookie element.
-   * 
-   * @return The control value cookie element.
-   */
-  public ByteString getCookie()
-  {
-    return cookie;
-  }
-
-
-
-  /**
-   * Get the control value size element, which is either the requested
-   * page size from the client, or the result set size estimate from the
-   * server.
-   * 
-   * @return The control value size element.
-   */
-  public int getSize()
-  {
-    return size;
-  }
-
-
-
-  @Override
-  public ByteString getValue()
-  {
-    ByteStringBuilder buffer = new ByteStringBuilder();
-    ASN1Writer writer = ASN1.getWriter(buffer);
-    try
-    {
-      writer.writeStartSequence();
-      writer.writeInteger(size);
-      writer.writeOctetString(cookie);
-      writer.writeEndSequence();
-      return buffer.toByteString();
-    }
-    catch (IOException ioe)
-    {
-      // This should never happen unless there is a bug somewhere.
-      throw new RuntimeException(ioe);
-    }
-  }
-
-
-
-  @Override
-  public boolean hasValue()
-  {
-    return true;
-  }
-
-
-
-  @Override
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("PagedResultsControl(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(", size=");
-    buffer.append(size);
-    buffer.append(", cookie=");
-    buffer.append(cookie);
-    buffer.append(")");
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/PasswordExpiredControl.java b/sdk/src/org/opends/sdk/controls/PasswordExpiredControl.java
deleted file mode 100644
index 4d7fc40..0000000
--- a/sdk/src/org/opends/sdk/controls/PasswordExpiredControl.java
+++ /dev/null
@@ -1,138 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.schema.Schema;
-
-
-
-
-/**
- * This class implements the Netscape password expired control. The
- * value for this control should be a string that indicates the length
- * of time until the password expires, but because it is already expired
- * it will always be "0".
- */
-public class PasswordExpiredControl extends Control
-{
-  /**
-   * The OID for the Netscape password expired control.
-   */
-  public static final String OID_NS_PASSWORD_EXPIRED = "2.16.840.1.113730.3.4.4";
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class Decoder implements
-      ControlDecoder<PasswordExpiredControl>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public PasswordExpiredControl decode(boolean isCritical,
-        ByteString value, Schema schema) throws DecodeException
-    {
-      if (value != null)
-      {
-        try
-        {
-          Integer.parseInt(value.toString());
-        }
-        catch (Exception e)
-        {
-          LocalizableMessage message = ERR_PWEXPIRED_CONTROL_INVALID_VALUE.get();
-          throw DecodeException.error(message);
-        }
-      }
-
-      return new PasswordExpiredControl(isCritical);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_NS_PASSWORD_EXPIRED;
-    }
-
-  }
-
-
-
-  private final static ByteString CONTROL_VALUE = ByteString
-      .valueOf("0");
-
-  /**
-   * The Control Decoder that can be used to decode this control.
-   */
-  public static final ControlDecoder<PasswordExpiredControl> DECODER = new Decoder();
-
-
-
-  /**
-   * Creates a new instance of the password expired control with the
-   * default settings.
-   */
-  public PasswordExpiredControl()
-  {
-    this(false);
-  }
-
-
-
-  /**
-   * Creates a new instance of the password expired control with the
-   * provided information.
-   * 
-   * @param isCritical
-   *          Indicates whether support for this control should be
-   *          considered a critical part of the client processing.
-   */
-  public PasswordExpiredControl(boolean isCritical)
-  {
-    super(OID_NS_PASSWORD_EXPIRED, isCritical);
-  }
-
-
-
-  @Override
-  public ByteString getValue()
-  {
-    return CONTROL_VALUE;
-  }
-
-
-
-  @Override
-  public boolean hasValue()
-  {
-    return true;
-  }
-
-
-
-  /**
-   * Appends a string representation of this password expired control to
-   * the provided buffer.
-   * 
-   * @param buffer
-   *          The buffer to which the information should be appended.
-   */
-  @Override
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("PasswordExpiredControl(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(")");
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/PasswordExpiredResponseControl.java b/sdk/src/org/opends/sdk/controls/PasswordExpiredResponseControl.java
new file mode 100644
index 0000000..81ff574
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/PasswordExpiredResponseControl.java
@@ -0,0 +1,194 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_PWEXPIRED_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_PWEXPIRED_CONTROL_INVALID_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The Netscape password expired response control as defined in
+ * draft-vchu-ldap-pwd-policy. This control indicates to a client that their
+ * password has expired and must be changed. This control always has a value
+ * which is the string {@code "0"}.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-vchu-ldap-pwd-policy">draft-vchu-ldap-pwd-policy
+ *      - Password Policy for LDAP Directories </a>
+ */
+public final class PasswordExpiredResponseControl implements Control
+{
+  /**
+   * The OID for the Netscape password expired response control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.4";
+
+  private final boolean isCritical;
+
+  private static final PasswordExpiredResponseControl CRITICAL_INSTANCE =
+    new PasswordExpiredResponseControl(true);
+  private static final PasswordExpiredResponseControl NONCRITICAL_INSTANCE =
+    new PasswordExpiredResponseControl(false);
+
+  /**
+   * A decoder which can be used for decoding the password expired response
+   * control.
+   */
+  public static final ControlDecoder<PasswordExpiredResponseControl> DECODER =
+    new ControlDecoder<PasswordExpiredResponseControl>()
+  {
+
+    public PasswordExpiredResponseControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof PasswordExpiredResponseControl)
+      {
+        return (PasswordExpiredResponseControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_PWEXPIRED_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (control.hasValue())
+      {
+        try
+        {
+          Integer.parseInt(control.getValue().toString());
+        }
+        catch (final Exception e)
+        {
+          final LocalizableMessage message = ERR_PWEXPIRED_CONTROL_INVALID_VALUE
+              .get();
+          throw DecodeException.error(message);
+        }
+      }
+
+      return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+  private final static ByteString CONTROL_VALUE = ByteString.valueOf("0");
+
+
+
+  /**
+   * Creates a new Netscape password expired response control.
+   *
+   * @return The new control.
+   */
+  public static PasswordExpiredResponseControl newControl()
+  {
+    return NONCRITICAL_INSTANCE;
+  }
+
+
+
+  private PasswordExpiredResponseControl(final boolean isCritical)
+  {
+    this.isCritical = isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return CONTROL_VALUE;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PasswordExpiredResponseControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/PasswordExpiringControl.java b/sdk/src/org/opends/sdk/controls/PasswordExpiringControl.java
deleted file mode 100644
index 1b2c71e..0000000
--- a/sdk/src/org/opends/sdk/controls/PasswordExpiringControl.java
+++ /dev/null
@@ -1,175 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-
-
-
-/**
- * This class implements the Netscape password expiring control, which
- * serves as a warning to clients that the user's password is about to
- * expire. The only element contained in the control value is a string
- * representation of the number of seconds until expiration.
- */
-public class PasswordExpiringControl extends Control
-{
-  /**
-   * The OID for the Netscape password expiring control.
-   */
-  public static final String OID_NS_PASSWORD_EXPIRING = "2.16.840.1.113730.3.4.5";
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class Decoder implements
-      ControlDecoder<PasswordExpiringControl>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public PasswordExpiringControl decode(boolean isCritical,
-        ByteString value, Schema schema) throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_PWEXPIRING_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      int secondsUntilExpiration;
-      try
-      {
-        secondsUntilExpiration = Integer.parseInt(value.toString());
-      }
-      catch (Exception e)
-      {
-        StaticUtils.DEBUG_LOG.throwing(
-            "PasswordExpiringControl.Decoder", "decode", e);
-
-        LocalizableMessage message = ERR_PWEXPIRING_CANNOT_DECODE_SECONDS_UNTIL_EXPIRATION
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message);
-      }
-
-      return new PasswordExpiringControl(isCritical,
-          secondsUntilExpiration);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_NS_PASSWORD_EXPIRING;
-    }
-
-  }
-
-
-
-  /**
-   * The Control Decoder that can be used to decode this control.
-   */
-  public static final ControlDecoder<PasswordExpiringControl> DECODER = new Decoder();
-
-  // The length of time in seconds until the password actually expires.
-  private final int secondsUntilExpiration;
-
-
-
-  /**
-   * Creates a new instance of the password expiring control with the
-   * provided information.
-   * 
-   * @param isCritical
-   *          Indicates whether support for this control should be
-   *          considered a critical part of the client processing.
-   * @param secondsUntilExpiration
-   *          The length of time in seconds until the password actually
-   *          expires.
-   */
-  public PasswordExpiringControl(boolean isCritical,
-      int secondsUntilExpiration)
-  {
-    super(OID_NS_PASSWORD_EXPIRING, isCritical);
-
-    this.secondsUntilExpiration = secondsUntilExpiration;
-  }
-
-
-
-  /**
-   * Creates a new instance of the password expiring control with the
-   * provided information.
-   * 
-   * @param secondsUntilExpiration
-   *          The length of time in seconds until the password actually
-   *          expires.
-   */
-  public PasswordExpiringControl(int secondsUntilExpiration)
-  {
-    this(false, secondsUntilExpiration);
-  }
-
-
-
-  /**
-   * Retrieves the length of time in seconds until the password actually
-   * expires.
-   * 
-   * @return The length of time in seconds until the password actually
-   *         expires.
-   */
-  public int getSecondsUntilExpiration()
-  {
-    return secondsUntilExpiration;
-  }
-
-
-
-  @Override
-  public ByteString getValue()
-  {
-    return ByteString.valueOf(String.valueOf(secondsUntilExpiration));
-  }
-
-
-
-  @Override
-  public boolean hasValue()
-  {
-    return true;
-  }
-
-
-
-  /**
-   * Appends a string representation of this password expiring control
-   * to the provided buffer.
-   * 
-   * @param buffer
-   *          The buffer to which the information should be appended.
-   */
-  @Override
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("PasswordExpiringControl(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(", secondsUntilExpiration=");
-    buffer.append(secondsUntilExpiration);
-    buffer.append(")");
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/PasswordExpiringResponseControl.java b/sdk/src/org/opends/sdk/controls/PasswordExpiringResponseControl.java
new file mode 100644
index 0000000..c9dcc25
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/PasswordExpiringResponseControl.java
@@ -0,0 +1,229 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_PWEXPIRING_CANNOT_DECODE_SECONDS_UNTIL_EXPIRATION;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_PWEXPIRING_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_PWEXPIRING_NO_CONTROL_VALUE;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The Netscape password expiring response control as defined in
+ * draft-vchu-ldap-pwd-policy. This control serves as a warning to clients that
+ * the user's password is about to expire. The only element contained in the
+ * control value is a string representation of the number of seconds until
+ * expiration.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-vchu-ldap-pwd-policy">draft-vchu-ldap-pwd-policy
+ *      - Password Policy for LDAP Directories </a>
+ */
+public final class PasswordExpiringResponseControl implements Control
+{
+  /**
+   * The OID for the Netscape password expiring response control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.5";
+
+  /**
+   * A decoder which can be used for decoding the password expiring response
+   * control.
+   */
+  public static final ControlDecoder<PasswordExpiringResponseControl> DECODER =
+    new ControlDecoder<PasswordExpiringResponseControl>()
+  {
+
+    public PasswordExpiringResponseControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof PasswordExpiringResponseControl)
+      {
+        return (PasswordExpiringResponseControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_PWEXPIRING_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        final LocalizableMessage message = ERR_PWEXPIRING_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      int secondsUntilExpiration;
+      try
+      {
+        secondsUntilExpiration = Integer
+            .parseInt(control.getValue().toString());
+      }
+      catch (final Exception e)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PasswordExpiringControl.Decoder",
+            "decode", e);
+
+        final LocalizableMessage message = ERR_PWEXPIRING_CANNOT_DECODE_SECONDS_UNTIL_EXPIRATION
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message);
+      }
+
+      return new PasswordExpiringResponseControl(control.isCritical(),
+          secondsUntilExpiration);
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new Netscape password expiring response control with the provided
+   * amount of time until expiration.
+   *
+   * @param secondsUntilExpiration
+   *          The length of time in seconds until the password actually expires.
+   * @return The new control.
+   */
+  public static PasswordExpiringResponseControl newControl(
+      final int secondsUntilExpiration)
+  {
+    return new PasswordExpiringResponseControl(false, secondsUntilExpiration);
+  }
+
+
+
+  // The length of time in seconds until the password actually expires.
+  private final int secondsUntilExpiration;
+
+  private final boolean isCritical;
+
+
+
+  private PasswordExpiringResponseControl(final boolean isCritical,
+      final int secondsUntilExpiration)
+  {
+    this.isCritical = isCritical;
+    this.secondsUntilExpiration = secondsUntilExpiration;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * Returns the length of time in seconds until the password actually expires.
+   *
+   * @return The length of time in seconds until the password actually expires.
+   */
+  public int getSecondsUntilExpiration()
+  {
+    return secondsUntilExpiration;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return ByteString.valueOf(String.valueOf(secondsUntilExpiration));
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PasswordExpiringResponseControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", secondsUntilExpiration=");
+    builder.append(secondsUntilExpiration);
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/PasswordPolicyControl.java b/sdk/src/org/opends/sdk/controls/PasswordPolicyControl.java
deleted file mode 100644
index 9f24331..0000000
--- a/sdk/src/org/opends/sdk/controls/PasswordPolicyControl.java
+++ /dev/null
@@ -1,412 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ByteStringBuilder;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements the password policy control defined in
- * draft-behera-ldap-password-policy.
- */
-public class PasswordPolicyControl
-{
-  /**
-   * The OID for the password policy control from
-   * draft-behera-ldap-password-policy.
-   */
-  public static final String OID_PASSWORD_POLICY_CONTROL = "1.3.6.1.4.1.42.2.27.8.5.1";
-
-
-
-  /**
-   * This class implements the password policy request control defined
-   * in draft-behera-ldap-password-policy. It does not have a value.
-   */
-  public static class Request extends Control
-  {
-    public Request()
-    {
-      super(OID_PASSWORD_POLICY_CONTROL, false);
-    }
-
-
-
-    public Request(boolean isCritical)
-    {
-      super(OID_PASSWORD_POLICY_CONTROL, isCritical);
-    }
-
-
-
-    @Override
-    public ByteString getValue()
-    {
-      return null;
-    }
-
-
-
-    @Override
-    public boolean hasValue()
-    {
-      return false;
-    }
-
-
-
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("PasswordPolicyRequestControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * This class implements the password policy response control defined
-   * in draft-behera-ldap-password-policy. The value may have zero, one,
-   * or two elements, which may include flags to indicate a warning
-   * and/or an error.
-   */
-  public static class Response extends Control
-  {
-    // The warning value for this password policy response control.
-    private int warningValue;
-
-    // The error type for this password policy response control.
-    private PasswordPolicyErrorType errorType;
-
-    // The warning type for the password policy response control.
-    private PasswordPolicyWarningType warningType;
-
-
-
-    /**
-     * Creates a new instance of the password policy response control
-     * with the default OID and criticality, and without either a
-     * warning or an error flag.
-     */
-    public Response()
-    {
-      this(false);
-    }
-
-
-
-    /**
-     * Creates a new instance of the password policy response control
-     * with the default OID and criticality, and without either a
-     * warning or an error flag.
-     * 
-     * @param isCritical
-     *          Indicates whether support for this control should be
-     *          considered a critical part of the client processing.
-     */
-    public Response(boolean isCritical)
-    {
-      super(OID_PASSWORD_POLICY_CONTROL, isCritical);
-
-      warningType = null;
-      errorType = null;
-      warningValue = -1;
-    }
-
-
-
-    /**
-     * Retrieves the password policy error type contained in this
-     * control.
-     * 
-     * @return The password policy error type contained in this control,
-     *         or <CODE>null</CODE> if there is no error type.
-     */
-    public PasswordPolicyErrorType getErrorType()
-    {
-      return errorType;
-    }
-
-
-
-    @Override
-    public ByteString getValue()
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-      try
-      {
-        writer.writeStartSequence();
-        if (warningType != null)
-        {
-          // Just write the CHOICE element as a single element SEQUENCE.
-          writer.writeStartSequence(TYPE_WARNING_ELEMENT);
-          writer.writeInteger((byte) (0x80 | warningType.intValue()),
-              warningValue);
-          writer.writeEndSequence();
-        }
-
-        if (errorType != null)
-        {
-          writer.writeInteger(TYPE_ERROR_ELEMENT, errorType.intValue());
-        }
-        writer.writeEndSequence();
-        return buffer.toByteString();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-    }
-
-
-
-    /**
-     * Retrieves the password policy warning type contained in this
-     * control.
-     * 
-     * @return The password policy warning type contained in this
-     *         control, or <CODE>null</CODE> if there is no warning
-     *         type.
-     */
-    public PasswordPolicyWarningType getWarningType()
-    {
-      return warningType;
-    }
-
-
-
-    /**
-     * Retrieves the password policy warning value for this control. The
-     * value is undefined if there is no warning type.
-     * 
-     * @return The password policy warning value for this control.
-     */
-    public int getWarningValue()
-    {
-      return warningValue;
-    }
-
-
-
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    public Response setError(PasswordPolicyErrorType error)
-    {
-      Validator.ensureNotNull(error);
-      this.errorType = error;
-      return this;
-    }
-
-
-
-    public Response setWarning(PasswordPolicyWarningType type, int value)
-    {
-      Validator.ensureNotNull(type);
-      this.warningType = type;
-      this.warningValue = value;
-      return this;
-    }
-
-
-
-    /**
-     * Appends a string representation of this password policy response
-     * control to the provided buffer.
-     * 
-     * @param buffer
-     *          The buffer to which the information should be appended.
-     */
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("PasswordPolicyResponseControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", warningType=");
-      buffer.append(warningType);
-      buffer.append(", warningValue=");
-      buffer.append(warningValue);
-      buffer.append(", errorType=");
-      buffer.append(errorType);
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private static final class RequestDecoder implements
-      ControlDecoder<Request>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Request decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value != null)
-      {
-        LocalizableMessage message = ERR_PWPOLICYREQ_CONTROL_HAS_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      return new Request(isCritical);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_PASSWORD_POLICY_CONTROL;
-    }
-  }
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class ResponseDecoder implements
-      ControlDecoder<Response>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Response decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        // The response control must always have a value.
-        LocalizableMessage message = ERR_PWPOLICYRES_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      try
-      {
-        PasswordPolicyWarningType warningType = null;
-        PasswordPolicyErrorType errorType = null;
-        int warningValue = -1;
-
-        reader.readStartSequence();
-
-        if (reader.hasNextElement()
-            && (reader.peekType() == TYPE_WARNING_ELEMENT))
-        {
-          // Its a CHOICE element. Read as sequence to retrieve
-          // nested element.
-          reader.readStartSequence();
-          warningType = PasswordPolicyWarningType.valueOf(0x7F & reader
-              .peekType());
-          warningValue = (int) reader.readInteger();
-          if (warningType == null)
-          {
-            LocalizableMessage message = ERR_PWPOLICYRES_INVALID_WARNING_TYPE
-                .get(byteToHex(reader.peekType()));
-            throw DecodeException.error(message);
-          }
-          reader.readEndSequence();
-        }
-        if (reader.hasNextElement()
-            && (reader.peekType() == TYPE_ERROR_ELEMENT))
-        {
-          int errorValue = (int) reader.readInteger();
-          errorType = PasswordPolicyErrorType.valueOf(errorValue);
-          if (errorType == null)
-          {
-            LocalizableMessage message = ERR_PWPOLICYRES_INVALID_ERROR_TYPE
-                .get(errorValue);
-            throw DecodeException.error(message);
-          }
-        }
-
-        reader.readEndSequence();
-
-        Response response = new Response(isCritical);
-        if (warningType != null)
-        {
-          response.setWarning(warningType, warningValue);
-        }
-        if (errorType != null)
-        {
-          response.setError(errorType);
-        }
-        return response;
-      }
-      catch (IOException e)
-      {
-        StaticUtils.DEBUG_LOG.throwing(
-            "PasswordPolicyControl.ResponseDecoder", "decode", e);
-
-        LocalizableMessage message = ERR_PWPOLICYRES_DECODE_ERROR
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message);
-      }
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_PASSWORD_POLICY_CONTROL;
-    }
-
-  }
-
-
-
-  /**
-   * The BER type value for the warning element of the control value.
-   */
-  private static final byte TYPE_WARNING_ELEMENT = (byte) 0xA0;
-
-  /**
-   * The BER type value for the error element of the control value.
-   */
-  private static final byte TYPE_ERROR_ELEMENT = (byte) 0x81;
-
-  /**
-   * The Control Decoder that can be used to decode the request control.
-   */
-  public static final ControlDecoder<Request> REQUEST_DECODER = new RequestDecoder();
-
-  /**
-   * The Control Decoder that can be used to decode the response
-   * control.
-   */
-  public static final ControlDecoder<Response> RESPONSE_DECODER = new ResponseDecoder();
-}
diff --git a/sdk/src/org/opends/sdk/controls/PasswordPolicyErrorType.java b/sdk/src/org/opends/sdk/controls/PasswordPolicyErrorType.java
index da0142b..afa8740 100644
--- a/sdk/src/org/opends/sdk/controls/PasswordPolicyErrorType.java
+++ b/sdk/src/org/opends/sdk/controls/PasswordPolicyErrorType.java
@@ -1,94 +1,103 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
 package org.opends.sdk.controls;
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.opends.sdk.LocalizableMessage;
-
-
-
-
 /**
- * This enumeration defines the set of password policy warnings that may
- * be included in the password policy response control defined in
- * draft-behera-ldap-password-policy.
+ * A password policy error type as defined in draft-behera-ldap-password-policy
+ * is used to indicate problems concerning a user's account or password.
+ *
+ * @see PasswordPolicyRequestControl
+ * @see PasswordPolicyResponseControl
+ * @see PasswordPolicyWarningType
+ * @see <a href="http://tools.ietf.org/html/draft-behera-ldap-password-policy">
+ *      draft-behera-ldap-password-policy - Password Policy for LDAP Directories
+ *      </a>
  */
-public class PasswordPolicyErrorType
+public enum PasswordPolicyErrorType
 {
-  private static final PasswordPolicyErrorType[] ELEMENTS = new PasswordPolicyErrorType[9];
 
-  public static final PasswordPolicyErrorType PASSWORD_EXPIRED = register(
-      0, INFO_PWPERRTYPE_DESCRIPTION_PASSWORD_EXPIRED.get());
+  /**
+   * Indicates that the password has expired and must be reset.
+   */
+  PASSWORD_EXPIRED(0, "passwordExpired"),
 
-  public static final PasswordPolicyErrorType ACCOUNT_LOCKED = register(
-      1, INFO_PWPERRTYPE_DESCRIPTION_ACCOUNT_LOCKED.get());
+  /**
+   * Indicates that the user's account has been locked.
+   */
+  ACCOUNT_LOCKED(1, "accountLocked"),
 
-  public static final PasswordPolicyErrorType CHANGE_AFTER_RESET = register(
-      2, INFO_PWPERRTYPE_DESCRIPTION_CHANGE_AFTER_RESET.get());
+  /**
+   * Indicates that the password must be changed before the user will be allowed
+   * to perform any operation other than bind and modify.
+   */
+  CHANGE_AFTER_RESET(2, "changeAfterReset"),
 
-  public static final PasswordPolicyErrorType PASSWORD_MOD_NOT_ALLOWED = register(
-      3, INFO_PWPERRTYPE_DESCRIPTION_PASSWORD_MOD_NOT_ALLOWED.get());
+  /**
+   * Indicates that a user is restricted from changing her password.
+   */
+  PASSWORD_MOD_NOT_ALLOWED(3, "passwordModNotAllowed"),
 
-  public static final PasswordPolicyErrorType MUST_SUPPLY_OLD_PASSWORD = register(
-      4, INFO_PWPERRTYPE_DESCRIPTION_MUST_SUPPLY_OLD_PASSWORD.get());
+  /**
+   * Indicates that the old password must be supplied in order to modify the
+   * password.
+   */
+  MUST_SUPPLY_OLD_PASSWORD(4, "mustSupplyOldPassword"),
 
-  public static final PasswordPolicyErrorType INSUFFICIENT_PASSWORD_QUALITY = register(
-      5, INFO_PWPERRTYPE_DESCRIPTION_INSUFFICIENT_PASSWORD_QUALITY
-          .get());
+  /**
+   * Indicates that a password doesn't pass quality checking.
+   */
+  INSUFFICIENT_PASSWORD_QUALITY(5, "insufficientPasswordQuality"),
 
-  public static final PasswordPolicyErrorType PASSWORD_TOO_SHORT = register(
-      6, INFO_PWPERRTYPE_DESCRIPTION_PASSWORD_TOO_SHORT.get());
+  /**
+   * Indicates that a password is not long enough.
+   */
+  PASSWORD_TOO_SHORT(6, "passwordTooShort"),
 
-  public static final PasswordPolicyErrorType PASSWORD_TOO_YOUNG = register(
-      7, INFO_PWPERRTYPE_DESCRIPTION_PASSWORD_TOO_YOUNG.get());
+  /**
+   * Indicates that the age of the password to be modified is not yet old
+   * enough.
+   */
+  PASSWORD_TOO_YOUNG(7, "passwordTooYoung"),
 
-  public static final PasswordPolicyErrorType PASSWORD_IN_HISTORY = register(
-      8, INFO_PWPERRTYPE_DESCRIPTION_PASSWORD_IN_HISTORY.get());
-
-
-
-  public static PasswordPolicyErrorType valueOf(int intValue)
-  {
-    PasswordPolicyErrorType e = ELEMENTS[intValue];
-    if (e == null)
-    {
-      e = new PasswordPolicyErrorType(intValue, LocalizableMessage
-          .raw("undefined(" + intValue + ")"));
-    }
-    return e;
-  }
-
-
-
-  public static List<PasswordPolicyErrorType> values()
-  {
-    return Arrays.asList(ELEMENTS);
-  }
-
-
-
-  private static PasswordPolicyErrorType register(int intValue,
-      LocalizableMessage name)
-  {
-    PasswordPolicyErrorType t = new PasswordPolicyErrorType(intValue,
-        name);
-    ELEMENTS[intValue] = t;
-    return t;
-  }
-
-
+  /**
+   * Indicates that a password has already been used and the user must choose a
+   * different one.
+   */
+  PASSWORD_IN_HISTORY(8, "passwordInHistory");
 
   private final int intValue;
 
-  private final LocalizableMessage name;
+  private final String name;
 
 
 
-  private PasswordPolicyErrorType(int intValue, LocalizableMessage name)
+  private PasswordPolicyErrorType(final int intValue, final String name)
   {
     this.intValue = intValue;
     this.name = name;
@@ -96,34 +105,25 @@
 
 
 
-  @Override
-  public boolean equals(Object o)
-  {
-    return (this == o)
-        || ((o instanceof PasswordPolicyErrorType) && (this.intValue == ((PasswordPolicyErrorType) o).intValue));
-
-  }
-
-
-
-  @Override
-  public int hashCode()
-  {
-    return intValue;
-  }
-
-
-
-  public int intValue()
-  {
-    return intValue;
-  }
-
-
-
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public String toString()
   {
-    return name.toString();
+    return name;
   }
+
+
+
+  /**
+   * Returns the integer value for this password policy error type.
+   *
+   * @return The integer value for this password policy error type.
+   */
+  int intValue()
+  {
+    return intValue;
+  }
+
 }
diff --git a/sdk/src/org/opends/sdk/controls/PasswordPolicyRequestControl.java b/sdk/src/org/opends/sdk/controls/PasswordPolicyRequestControl.java
new file mode 100644
index 0000000..eb96ab7
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/PasswordPolicyRequestControl.java
@@ -0,0 +1,195 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_PWPOLICYREQ_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_PWPOLICYREQ_CONTROL_HAS_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The password policy request control as defined in
+ * draft-behera-ldap-password-policy.
+ * <p>
+ * This control may be sent with any request in order to convey to the server
+ * that this client is aware of, and can process the password policy response
+ * control. When a server receives this control, it will return the password
+ * policy response control when appropriate and with the proper data.
+ *
+ * @see PasswordPolicyResponseControl
+ * @see <a href="http://tools.ietf.org/html/draft-behera-ldap-password-policy">
+ *         draft-behera-ldap-password-policy - Password Policy for LDAP Directories </a>
+ */
+public final class PasswordPolicyRequestControl implements Control
+{
+  /**
+   * The OID for the password policy control from
+   * draft-behera-ldap-password-policy.
+   */
+  public static final String OID = "1.3.6.1.4.1.42.2.27.8.5.1";
+
+  private final boolean isCritical;
+
+  private static final PasswordPolicyRequestControl CRITICAL_INSTANCE =
+    new PasswordPolicyRequestControl(true);
+  private static final PasswordPolicyRequestControl NONCRITICAL_INSTANCE =
+    new PasswordPolicyRequestControl(false);
+
+  /**
+   * A decoder which can be used for decoding the password policy request
+   * control.
+   */
+  public static final ControlDecoder<PasswordPolicyRequestControl> DECODER =
+    new ControlDecoder<PasswordPolicyRequestControl>()
+  {
+
+    public PasswordPolicyRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof PasswordPolicyRequestControl)
+      {
+        return (PasswordPolicyRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_PWPOLICYREQ_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (control.hasValue())
+      {
+        final LocalizableMessage message = ERR_PWPOLICYREQ_CONTROL_HAS_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new password policy request control having the provided
+   * criticality.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @return The new control.
+   */
+  public static PasswordPolicyRequestControl newControl(final boolean isCritical)
+  {
+    return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+  }
+
+
+
+  private PasswordPolicyRequestControl(final boolean isCritical)
+  {
+    this.isCritical = isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PasswordPolicyRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/PasswordPolicyResponseControl.java b/sdk/src/org/opends/sdk/controls/PasswordPolicyResponseControl.java
new file mode 100644
index 0000000..742ca3c
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/PasswordPolicyResponseControl.java
@@ -0,0 +1,418 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.util.StaticUtils.byteToHex;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The password policy response control as defined in
+ * draft-behera-ldap-password-policy.
+ * <p>
+ * If the client has sent a passwordPolicyRequest control, the server (when
+ * solicited by the inclusion of the request control) sends this control with
+ * the following operation responses: bindResponse, modifyResponse, addResponse,
+ * compareResponse and possibly extendedResponse, to inform of various
+ * conditions, and MAY be sent with other operations (in the case of the
+ * changeAfterReset error).
+ *
+ * @see PasswordPolicyRequestControl
+ * @see PasswordPolicyWarningType
+ * @see PasswordPolicyErrorType
+ * @see <a href="http://tools.ietf.org/html/draft-behera-ldap-password-policy">
+ *         draft-behera-ldap-password-policy - Password Policy for LDAP
+ *         Directories </a>
+ */
+public final class PasswordPolicyResponseControl implements Control
+{
+  /**
+   * The OID for the password policy control from
+   * draft-behera-ldap-password-policy.
+   */
+  public static final String OID = PasswordPolicyRequestControl.OID;
+
+  private final int warningValue;
+
+  private final PasswordPolicyErrorType errorType;
+
+  private final PasswordPolicyWarningType warningType;
+
+  /**
+   * A decoder which can be used for decoding the password policy response
+   * control.
+   */
+  public static final ControlDecoder<PasswordPolicyResponseControl> DECODER =
+    new ControlDecoder<PasswordPolicyResponseControl>()
+  {
+
+    public PasswordPolicyResponseControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof PasswordPolicyResponseControl)
+      {
+        return (PasswordPolicyResponseControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_PWPOLICYRES_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The response control must always have a value.
+        final LocalizableMessage message = ERR_PWPOLICYRES_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      try
+      {
+        PasswordPolicyWarningType warningType = null;
+        PasswordPolicyErrorType errorType = null;
+        int warningValue = -1;
+
+        reader.readStartSequence();
+
+        if (reader.hasNextElement()
+            && (reader.peekType() == TYPE_WARNING_ELEMENT))
+        {
+          // Its a CHOICE element. Read as sequence to retrieve
+          // nested element.
+          reader.readStartSequence();
+          final int warningChoiceValue = (0x7F & reader.peekType());
+          if (warningChoiceValue < 0
+              || warningChoiceValue >= PasswordPolicyWarningType.values().length)
+          {
+            final LocalizableMessage message = ERR_PWPOLICYRES_INVALID_WARNING_TYPE
+                .get(byteToHex(reader.peekType()));
+            throw DecodeException.error(message);
+          }
+          else
+          {
+            warningType = PasswordPolicyWarningType.values()[warningChoiceValue];
+          }
+          warningValue = (int) reader.readInteger();
+          reader.readEndSequence();
+        }
+
+        if (reader.hasNextElement()
+            && (reader.peekType() == TYPE_ERROR_ELEMENT))
+        {
+          final int errorValue = reader.readEnumerated();
+          if (errorValue < 0
+              || errorValue >= PasswordPolicyErrorType.values().length)
+          {
+            final LocalizableMessage message = ERR_PWPOLICYRES_INVALID_ERROR_TYPE
+                .get(errorValue);
+            throw DecodeException.error(message);
+          }
+          else
+          {
+            errorType = PasswordPolicyErrorType.values()[errorValue];
+          }
+        }
+
+        reader.readEndSequence();
+
+        return new PasswordPolicyResponseControl(control.isCritical(),
+            warningType, warningValue, errorType);
+      }
+      catch (final IOException e)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PasswordPolicyControl.ResponseDecoder",
+            "decode", e);
+
+        final LocalizableMessage message = ERR_PWPOLICYRES_DECODE_ERROR
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message);
+      }
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new password policy response control with the provided error.
+   *
+   * @param errorType
+   *          The password policy error type.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code errorType} was {@code null}.
+   */
+  public static PasswordPolicyResponseControl newControl(
+      final PasswordPolicyErrorType errorType) throws NullPointerException
+  {
+    Validator.ensureNotNull(errorType);
+
+    return new PasswordPolicyResponseControl(false, null, -1, errorType);
+  }
+
+
+
+  /**
+   * Creates a new password policy response control with the provided warning.
+   *
+   * @param warningType
+   *          The password policy warning type.
+   * @param warningValue
+   *          The password policy warning value.
+   * @return The new control.
+   * @throws IllegalArgumentException
+   *           If {@code warningValue} was negative.
+   * @throws NullPointerException
+   *           If {@code warningType} was {@code null}.
+   */
+  public static PasswordPolicyResponseControl newControl(
+      final PasswordPolicyWarningType warningType, final int warningValue)
+      throws IllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(warningType);
+    Validator.ensureTrue(warningValue >= 0, "warningValue is negative");
+
+    return new PasswordPolicyResponseControl(false, warningType, warningValue,
+        null);
+  }
+
+
+
+  /**
+   * Creates a new password policy response control with the provided warning
+   * and error.
+   *
+   * @param warningType
+   *          The password policy warning type.
+   * @param warningValue
+   *          The password policy warning value.
+   * @param errorType
+   *          The password policy error type.
+   * @return The new control.
+   * @throws IllegalArgumentException
+   *           If {@code warningValue} was negative.
+   * @throws NullPointerException
+   *           If {@code warningType} or {@code errorType} was {@code null}.
+   */
+  public static PasswordPolicyResponseControl newControl(
+      final PasswordPolicyWarningType warningType, final int warningValue,
+      final PasswordPolicyErrorType errorType) throws IllegalArgumentException,
+      NullPointerException
+  {
+    Validator.ensureNotNull(warningType, errorType);
+    Validator.ensureTrue(warningValue >= 0, "warningValue is negative");
+
+    return new PasswordPolicyResponseControl(false, warningType, warningValue,
+        errorType);
+  }
+
+
+
+  private final boolean isCritical;
+
+  /**
+   * The BER type value for the warning element of the control value.
+   */
+  private static final byte TYPE_WARNING_ELEMENT = (byte) 0xA0;
+
+  /**
+   * The BER type value for the error element of the control value.
+   */
+  private static final byte TYPE_ERROR_ELEMENT = (byte) 0x81;
+
+
+
+  private PasswordPolicyResponseControl(final boolean isCritical,
+      final PasswordPolicyWarningType warningType, final int warningValue,
+      final PasswordPolicyErrorType errorType)
+  {
+    this.isCritical = isCritical;
+    this.warningType = warningType;
+    this.warningValue = warningValue;
+    this.errorType = errorType;
+  }
+
+
+
+  /**
+   * Returns the password policy error type, if available.
+   *
+   * @return The password policy error type, or {@code null} if this control
+   *         does not contain a error.
+   */
+  public PasswordPolicyErrorType getErrorType()
+  {
+    return errorType;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      if (warningType != null)
+      {
+        // Just write the CHOICE element as a single element SEQUENCE.
+        writer.writeStartSequence(TYPE_WARNING_ELEMENT);
+        writer.writeInteger((byte) (0x80 | warningType.intValue()),
+            warningValue);
+        writer.writeEndSequence();
+      }
+
+      if (errorType != null)
+      {
+        writer.writeInteger(TYPE_ERROR_ELEMENT, errorType.intValue());
+      }
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * Returns the password policy warning type, if available.
+   *
+   * @return The password policy warning type, or {@code null} if this control
+   *         does not contain a warning.
+   */
+  public PasswordPolicyWarningType getWarningType()
+  {
+    return warningType;
+  }
+
+
+
+  /**
+   * Returns the password policy warning value, if available. The value is
+   * undefined if this control does not contain a warning.
+   *
+   * @return The password policy warning value, or {@code -1} if this control
+   *         does not contain a warning.
+   */
+  public int getWarningValue()
+  {
+    return warningValue;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PasswordPolicyResponseControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    if (warningType != null)
+    {
+      builder.append(", warningType=");
+      builder.append(warningType);
+      builder.append(", warningValue=");
+      builder.append(warningValue);
+    }
+    if (errorType != null)
+    {
+      builder.append(", errorType=");
+      builder.append(errorType);
+    }
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/PasswordPolicyWarningType.java b/sdk/src/org/opends/sdk/controls/PasswordPolicyWarningType.java
index 702378e..d79a22d 100644
--- a/sdk/src/org/opends/sdk/controls/PasswordPolicyWarningType.java
+++ b/sdk/src/org/opends/sdk/controls/PasswordPolicyWarningType.java
@@ -1,72 +1,67 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
 package org.opends.sdk.controls;
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.opends.sdk.LocalizableMessage;
-
-
-
-
 /**
- * This enumeration defines the set of password policy warnings that may
- * be included in the password policy response control defined in
- * draft-behera-ldap-password-policy.
+ * A password policy warning type as defined in
+ * draft-behera-ldap-password-policy is used to indicate the current state of a
+ * user's password. More specifically, the number of seconds before a password
+ * will expire, or the remaining number of times a user will be allowed to
+ * authenticate with an expired password.
+ *
+ * @see PasswordPolicyRequestControl
+ * @see PasswordPolicyResponseControl
+ * @see PasswordPolicyErrorType
+ * @see <a href="http://tools.ietf.org/html/draft-behera-ldap-password-policy">
+ *         draft-behera-ldap-password-policy - Password Policy for LDAP
+ *         Directories </a>
  */
-public class PasswordPolicyWarningType
+public enum PasswordPolicyWarningType
 {
-  private static final PasswordPolicyWarningType[] ELEMENTS = new PasswordPolicyWarningType[2];
+  /**
+   * Indicates the number of seconds before a password will expire.
+   */
+  TIME_BEFORE_EXPIRATION(0, "timeBeforeExpiration"),
 
-  public static final PasswordPolicyWarningType TIME_BEFORE_EXPIRATION = register(
-      0, INFO_PWPWARNTYPE_DESCRIPTION_TIME_BEFORE_EXPIRATION.get());
-
-  public static final PasswordPolicyWarningType GRACE_LOGINS_REMAINING = register(
-      1, INFO_PWPWARNTYPE_DESCRIPTION_GRACE_LOGINS_REMAINING.get());
-
-
-
-  public static PasswordPolicyWarningType valueOf(int intValue)
-  {
-    PasswordPolicyWarningType e = ELEMENTS[intValue];
-    if (e == null)
-    {
-      e = new PasswordPolicyWarningType(intValue, LocalizableMessage
-          .raw("undefined(" + intValue + ")"));
-    }
-    return e;
-  }
-
-
-
-  public static List<PasswordPolicyWarningType> values()
-  {
-    return Arrays.asList(ELEMENTS);
-  }
-
-
-
-  private static PasswordPolicyWarningType register(int intValue,
-      LocalizableMessage name)
-  {
-    PasswordPolicyWarningType t = new PasswordPolicyWarningType(
-        intValue, name);
-    ELEMENTS[intValue] = t;
-    return t;
-  }
-
-
+  /**
+   * Indicates the remaining number of times a user will be allowed to
+   * authenticate with an expired password.
+   */
+  GRACE_LOGINS_REMAINING(1, "graceAuthNsRemaining");
 
   private final int intValue;
 
-  private final LocalizableMessage name;
+  private final String name;
 
 
 
-  private PasswordPolicyWarningType(int intValue, LocalizableMessage name)
+  private PasswordPolicyWarningType(final int intValue, final String name)
   {
     this.intValue = intValue;
     this.name = name;
@@ -74,34 +69,24 @@
 
 
 
-  @Override
-  public boolean equals(Object o)
-  {
-    return (this == o)
-        || ((o instanceof PasswordPolicyWarningType) && (this.intValue == ((PasswordPolicyWarningType) o).intValue));
-
-  }
-
-
-
-  @Override
-  public int hashCode()
-  {
-    return intValue;
-  }
-
-
-
-  public int intValue()
-  {
-    return intValue;
-  }
-
-
-
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public String toString()
   {
-    return name.toString();
+    return name;
+  }
+
+
+
+  /**
+   * Returns the integer value for this password policy warning type.
+   *
+   * @return The integer value for this password policy warning type.
+   */
+  int intValue()
+  {
+    return intValue;
   }
 }
diff --git a/sdk/src/org/opends/sdk/controls/PermissiveModifyRequestControl.java b/sdk/src/org/opends/sdk/controls/PermissiveModifyRequestControl.java
new file mode 100644
index 0000000..3a55a36
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/PermissiveModifyRequestControl.java
@@ -0,0 +1,189 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_PERMISSIVE_MODIFY_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_PERMISSIVE_MODIFY_INVALID_CONTROL_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The Microsoft defined permissive modify request control. The OID for this
+ * control is 1.2.840.113556.1.4.1413, and it does not have a value.
+ */
+public final class PermissiveModifyRequestControl implements Control
+{
+  /**
+   * The OID for the permissive modify request control.
+   */
+  public static final String OID = "1.2.840.113556.1.4.1413";
+
+  private static final PermissiveModifyRequestControl CRITICAL_INSTANCE =
+    new PermissiveModifyRequestControl(true);
+
+  private static final PermissiveModifyRequestControl NONCRITICAL_INSTANCE =
+    new PermissiveModifyRequestControl(false);
+
+  /**
+   * A decoder which can be used for decoding the permissive modify request
+   * control.
+   */
+  public static final ControlDecoder<PermissiveModifyRequestControl> DECODER =
+    new ControlDecoder<PermissiveModifyRequestControl>()
+  {
+
+    public PermissiveModifyRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof PermissiveModifyRequestControl)
+      {
+        return (PermissiveModifyRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_PERMISSIVE_MODIFY_CONTROL_BAD_OID
+            .get(control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (control.hasValue())
+      {
+        final LocalizableMessage message = ERR_PERMISSIVE_MODIFY_INVALID_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new permissive modify request control having the provided
+   * criticality.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @return The new control.
+   */
+  public static PermissiveModifyRequestControl newControl(
+      final boolean isCritical)
+  {
+    return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+  }
+
+
+
+  private final boolean isCritical;
+
+
+
+  private PermissiveModifyRequestControl(final boolean isCritical)
+  {
+    this.isCritical = isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PermissiveModifyRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/PersistentSearchChangeType.java b/sdk/src/org/opends/sdk/controls/PersistentSearchChangeType.java
index 2f4b99f..d36f1b3 100644
--- a/sdk/src/org/opends/sdk/controls/PersistentSearchChangeType.java
+++ b/sdk/src/org/opends/sdk/controls/PersistentSearchChangeType.java
@@ -1,108 +1,99 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
 package org.opends.sdk.controls;
 
 
 
-import java.util.Arrays;
-import java.util.List;
-
-
-
 /**
- * This enumeration defines the set of possible change types that may be
- * used in conjunction with the persistent search control, as defined in
- * draft-ietf-ldapext-psearch.
+ * A persistent search change type as defined in draft-ietf-ldapext-psearch is
+ * used to indicate the type of update operation that caused an entry change
+ * notification to occur.
+ *
+ * @see PersistentSearchRequestControl
+ * @see EntryChangeNotificationResponseControl
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-ietf-ldapext-psearch">draft-ietf-ldapext-psearch
+ *      - Persistent Search: A Simple LDAP Change Notification Mechanism </a>
  */
-public final class PersistentSearchChangeType
+public enum PersistentSearchChangeType
 {
-  private static final PersistentSearchChangeType[] ELEMENTS = new PersistentSearchChangeType[4];
+  /**
+   * Indicates that an Add operation triggered the entry change notification.
+   */
+  ADD(1, "add"),
 
-  public static final PersistentSearchChangeType ADD = register(1,
-      "add", 0);
+  /**
+   * Indicates that an Delete operation triggered the entry change notification.
+   */
+  DELETE(2, "delete"),
 
-  public static final PersistentSearchChangeType DELETE = register(2,
-      "delete", 1);
+  /**
+   * Indicates that an Modify operation triggered the entry change notification.
+   */
+  MODIFY(4, "modify"),
 
-  public static final PersistentSearchChangeType MODIFY = register(4,
-      "modify", 2);
-
-  public static final PersistentSearchChangeType MODIFY_DN = register(
-      8, "modify DN", 3);
-
-
-
-  public static PersistentSearchChangeType valueOf(int intValue)
-  {
-    PersistentSearchChangeType e = ELEMENTS[intValue];
-    if (e == null)
-    {
-      e = new PersistentSearchChangeType(intValue, "undefined("
-          + intValue + ")");
-    }
-    return e;
-  }
-
-
-
-  public static List<PersistentSearchChangeType> values()
-  {
-    return Arrays.asList(ELEMENTS);
-  }
-
-
-
-  private static PersistentSearchChangeType register(int intValue,
-      String name, int index)
-  {
-    PersistentSearchChangeType t = new PersistentSearchChangeType(
-        intValue, name);
-    ELEMENTS[index] = t;
-    return t;
-  }
-
-
-
-  private final int intValue;
+  /**
+   * Indicates that an Modify DN operation triggered the entry change
+   * notification.
+   */
+  MODIFY_DN(8, "modifyDN");
 
   private final String name;
 
+  private final int intValue;
 
 
-  private PersistentSearchChangeType(int intValue, String name)
+
+  private PersistentSearchChangeType(final int intValue, final String name)
   {
-    this.intValue = intValue;
     this.name = name;
+    this.intValue = intValue;
   }
 
 
 
-  @Override
-  public boolean equals(Object o)
-  {
-    return (this == o)
-        || ((o instanceof PersistentSearchChangeType) && (this.intValue == ((PersistentSearchChangeType) o).intValue));
-
-  }
-
-
-
-  @Override
-  public int hashCode()
-  {
-    return intValue;
-  }
-
-
-
-  public int intValue()
-  {
-    return intValue;
-  }
-
-
-
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public String toString()
   {
     return name;
   }
+
+
+
+  /**
+   * Returns the integer value for this change type.
+   *
+   * @return The integer value for this change type.
+   */
+  int intValue()
+  {
+    return intValue;
+  }
 }
diff --git a/sdk/src/org/opends/sdk/controls/PersistentSearchControl.java b/sdk/src/org/opends/sdk/controls/PersistentSearchControl.java
deleted file mode 100644
index 1ad08ec..0000000
--- a/sdk/src/org/opends/sdk/controls/PersistentSearchControl.java
+++ /dev/null
@@ -1,328 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ByteStringBuilder;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-
-
-
-/**
- * This class implements the persistent search control defined in
- * draft-ietf-ldapext-psearch. It makes it possible for clients to be
- * notified of changes to information in the Directory Server as they
- * occur.
- */
-public class PersistentSearchControl extends Control
-{
-  /**
-   * The OID for the persistent search control.
-   */
-  public static final String OID_PERSISTENT_SEARCH = "2.16.840.1.113730.3.4.3";
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class Decoder implements
-      ControlDecoder<PersistentSearchControl>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public PersistentSearchControl decode(boolean isCritical,
-        ByteString value, Schema schema) throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_PSEARCH_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      boolean changesOnly;
-      boolean returnECs;
-      int changeTypes;
-      try
-      {
-        reader.readStartSequence();
-
-        changeTypes = (int) reader.readInteger();
-        changesOnly = reader.readBoolean();
-        returnECs = reader.readBoolean();
-
-        reader.readEndSequence();
-      }
-      catch (IOException e)
-      {
-        StaticUtils.DEBUG_LOG.throwing(
-            "PersistentSearchControl.Decoder", "decode", e);
-
-        LocalizableMessage message = ERR_PSEARCH_CANNOT_DECODE_VALUE
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message, e);
-      }
-
-      return new PersistentSearchControl(isCritical, changeTypes,
-          changesOnly, returnECs);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_PERSISTENT_SEARCH;
-    }
-
-  }
-
-
-
-  /**
-   * The Control Decoder that can be used to decode this control.
-   */
-  public static final ControlDecoder<PersistentSearchControl> DECODER = new Decoder();
-
-  // Indicates whether to only return entries that have been updated
-  // since the
-  // beginning of the search.
-  private final boolean changesOnly;
-
-  // Indicates whether entries returned as a result of changes to
-  // directory data
-  // should include the entry change notification control.
-  private final boolean returnECs;
-
-  // The logical OR of change types associated with this control.
-  private int changeTypes;
-
-
-
-  /**
-   * Creates a new persistent search control with the provided
-   * information.
-   * 
-   * @param isCritical
-   *          Indicates whether the control should be considered
-   *          critical for the operation processing.
-   * @param changesOnly
-   *          Indicates whether to only return changes that match the
-   *          associated search criteria, or to also return all existing
-   *          entries that match the filter.
-   * @param returnECs
-   *          Indicates whether to include the entry change notification
-   *          control in updated entries that match the associated
-   *          search criteria.
-   * @param changeTypes
-   *          The change types for which to provide notification to the
-   *          client.
-   */
-  public PersistentSearchControl(boolean isCritical,
-      boolean changesOnly, boolean returnECs,
-      PersistentSearchChangeType... changeTypes)
-  {
-    super(OID_PERSISTENT_SEARCH, isCritical);
-
-    this.changeTypes = 0;
-    this.changesOnly = changesOnly;
-    this.returnECs = returnECs;
-
-    if (changeTypes != null)
-    {
-      for (PersistentSearchChangeType type : changeTypes)
-      {
-        this.changeTypes |= type.intValue();
-      }
-    }
-  }
-
-
-
-  /**
-   * Creates a new persistent search control with the provided
-   * information.
-   * 
-   * @param changesOnly
-   *          Indicates whether to only return changes that match the
-   *          associated search criteria, or to also return all existing
-   *          entries that match the filter.
-   * @param returnECs
-   *          Indicates whether to include the entry change notification
-   *          control in updated entries that match the associated
-   *          search criteria.
-   * @param changeTypes
-   *          The set of change types for which to provide notification
-   *          to the client.
-   */
-  public PersistentSearchControl(boolean changesOnly,
-      boolean returnECs, PersistentSearchChangeType... changeTypes)
-  {
-    this(true, changesOnly, returnECs, changeTypes);
-  }
-
-
-
-  private PersistentSearchControl(boolean isCritical, int changeTypes,
-      boolean changesOnly, boolean returnECs)
-  {
-    super(OID_PERSISTENT_SEARCH, isCritical);
-
-    this.changeTypes = changeTypes;
-    this.changesOnly = changesOnly;
-    this.returnECs = returnECs;
-  }
-
-
-
-  public PersistentSearchControl addChangeType(
-      PersistentSearchChangeType type)
-  {
-    changeTypes |= type.intValue();
-    return this;
-  }
-
-
-
-  /**
-   * Indicates if the change type is included in this persistent search
-   * control.
-   * 
-   * @param type
-   *          The change type whose presence is to be tested.
-   * @return <code>true</code> if the change type is included or
-   *         <code>false</code> otherwise.
-   */
-  public boolean containsChangeType(PersistentSearchChangeType type)
-  {
-    return (changeTypes & type.intValue()) == type.intValue();
-  }
-
-
-
-  /**
-   * Indicates whether to only return changes that match the associated
-   * search criteria, or to also return all existing entries that match
-   * the filter.
-   * 
-   * @return <CODE>true</CODE> if only changes to matching entries
-   *         should be returned, or <CODE>false</CODE> if existing
-   *         matches should also be included.
-   */
-  public boolean getChangesOnly()
-  {
-    return changesOnly;
-  }
-
-
-
-  /**
-   * Indicates whether to include the entry change notification control
-   * in entries returned to the client as the result of a change in the
-   * Directory Server data.
-   * 
-   * @return <CODE>true</CODE> if entry change notification controls
-   *         should be included in applicable entries, or
-   *         <CODE>false</CODE> if not.
-   */
-  public boolean getReturnECs()
-  {
-    return returnECs;
-  }
-
-
-
-  @Override
-  public ByteString getValue()
-  {
-    ByteStringBuilder buffer = new ByteStringBuilder();
-    ASN1Writer writer = ASN1.getWriter(buffer);
-    try
-    {
-      writer.writeStartSequence();
-      writer.writeInteger(changeTypes);
-      writer.writeBoolean(changesOnly);
-      writer.writeBoolean(returnECs);
-      writer.writeEndSequence();
-      return buffer.toByteString();
-    }
-    catch (IOException ioe)
-    {
-      // This should never happen unless there is a bug somewhere.
-      throw new RuntimeException(ioe);
-    }
-  }
-
-
-
-  @Override
-  public boolean hasValue()
-  {
-    return true;
-  }
-
-
-
-  public PersistentSearchControl removeChangeType(
-      PersistentSearchChangeType type)
-  {
-    changeTypes &= ~type.intValue();
-    return this;
-  }
-
-
-
-  /**
-   * Appends a string representation of this persistent search control
-   * to the provided buffer.
-   * 
-   * @param buffer
-   *          The buffer to which the information should be appended.
-   */
-  @Override
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("PersistentSearchControl(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(", changeTypes=[");
-
-    boolean comma = false;
-    for (PersistentSearchChangeType type : PersistentSearchChangeType
-        .values())
-    {
-      if (containsChangeType(type))
-      {
-        if (comma)
-        {
-          buffer.append(", ");
-        }
-        buffer.append(type);
-        comma = true;
-      }
-    }
-
-    buffer.append("](");
-    buffer.append(changeTypes);
-    buffer.append("), changesOnly=");
-    buffer.append(changesOnly);
-    buffer.append(", returnECs=");
-    buffer.append(returnECs);
-    buffer.append(")");
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/PersistentSearchRequestControl.java b/sdk/src/org/opends/sdk/controls/PersistentSearchRequestControl.java
new file mode 100644
index 0000000..d4513c1
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/PersistentSearchRequestControl.java
@@ -0,0 +1,414 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_PSEARCH_BAD_CHANGE_TYPES;
+import static com.sun.opends.sdk.messages.Messages.ERR_PSEARCH_CANNOT_DECODE_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_PSEARCH_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_PSEARCH_NO_CONTROL_VALUE;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The persistent search request control as defined in
+ * draft-ietf-ldapext-psearch. This control allows a client to receive
+ * notification of changes that occur in an LDAP server.
+ *
+ * @see EntryChangeNotificationResponseControl
+ * @see PersistentSearchChangeType
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-ietf-ldapext-psearch">draft-ietf-ldapext-psearch
+ *      - Persistent Search: A Simple LDAP Change Notification Mechanism </a>
+ */
+public final class PersistentSearchRequestControl implements Control
+{
+  /**
+   * The OID for the persistent search request control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.3";
+
+  /**
+   * A decoder which can be used for decoding the persistent search request
+   * control.
+   */
+  public static final ControlDecoder<PersistentSearchRequestControl> DECODER =
+    new ControlDecoder<PersistentSearchRequestControl>()
+  {
+
+    public PersistentSearchRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof PersistentSearchRequestControl)
+      {
+        return (PersistentSearchRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_PSEARCH_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The control must always have a value.
+        final LocalizableMessage message = ERR_PSEARCH_NO_CONTROL_VALUE.get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      boolean changesOnly;
+      boolean returnECs;
+      int changeTypes;
+
+      try
+      {
+        reader.readStartSequence();
+
+        changeTypes = (int) reader.readInteger();
+        changesOnly = reader.readBoolean();
+        returnECs = reader.readBoolean();
+
+        reader.readEndSequence();
+      }
+      catch (final IOException e)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PersistentSearchControl.Decoder",
+            "decode", e);
+
+        final LocalizableMessage message = ERR_PSEARCH_CANNOT_DECODE_VALUE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+
+      final Set<PersistentSearchChangeType> changeTypeSet = EnumSet
+          .noneOf(PersistentSearchChangeType.class);
+
+      if ((changeTypes & 15) != 0)
+      {
+        final LocalizableMessage message = ERR_PSEARCH_BAD_CHANGE_TYPES
+            .get(changeTypes);
+        throw DecodeException.error(message);
+      }
+
+      if ((changeTypes & 1) != 0)
+      {
+        changeTypeSet.add(PersistentSearchChangeType.ADD);
+      }
+
+      if ((changeTypes & 2) != 0)
+      {
+        changeTypeSet.add(PersistentSearchChangeType.DELETE);
+      }
+
+      if ((changeTypes & 4) != 0)
+      {
+        changeTypeSet.add(PersistentSearchChangeType.MODIFY);
+      }
+
+      if ((changeTypes & 8) != 0)
+      {
+        changeTypeSet.add(PersistentSearchChangeType.MODIFY_DN);
+      }
+
+      return new PersistentSearchRequestControl(control.isCritical(),
+          changesOnly, returnECs, Collections.unmodifiableSet(changeTypeSet));
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new persistent search request control.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored
+   * @param changesOnly
+   *          Indicates whether or not only updated entries should be returned
+   *          (added, modified, deleted, or subject to a modifyDN operation). If
+   *          this parameter is {@code false} then the search will initially
+   *          return all the existing entries which match the filter.
+   * @param returnECs
+   *          Indicates whether or not the entry change notification control
+   *          should be included in updated entries that match the associated
+   *          search criteria.
+   * @param changeTypes
+   *          The types of update operation for which change notifications
+   *          should be returned.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code changeTypes} was {@code null}.
+   */
+  public static PersistentSearchRequestControl newControl(
+      final boolean isCritical, final boolean changesOnly,
+      final boolean returnECs,
+      final Collection<PersistentSearchChangeType> changeTypes)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(changeTypes);
+
+    final Set<PersistentSearchChangeType> copyOfChangeTypes = EnumSet
+        .noneOf(PersistentSearchChangeType.class);
+    copyOfChangeTypes.addAll(changeTypes);
+    return new PersistentSearchRequestControl(isCritical, changesOnly,
+        returnECs, Collections.unmodifiableSet(copyOfChangeTypes));
+  }
+
+
+
+  /**
+   * Creates a new persistent search request control.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored
+   * @param changesOnly
+   *          Indicates whether or not only updated entries should be returned
+   *          (added, modified, deleted, or subject to a modifyDN operation). If
+   *          this parameter is {@code false} then the search will initially
+   *          return all the existing entries which match the filter.
+   * @param returnECs
+   *          Indicates whether or not the entry change notification control
+   *          should be included in updated entries that match the associated
+   *          search criteria.
+   * @param changeTypes
+   *          The types of update operation for which change notifications
+   *          should be returned.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code changeTypes} was {@code null}.
+   */
+  public static PersistentSearchRequestControl newControl(
+      final boolean isCritical, final boolean changesOnly,
+      final boolean returnECs, final PersistentSearchChangeType... changeTypes)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull((Object) changeTypes);
+
+    return newControl(isCritical, changesOnly, returnECs, Arrays
+        .asList(changeTypes));
+  }
+
+
+
+  // Indicates whether to only return entries that have been updated
+  // since the beginning of the search.
+  private final boolean changesOnly;
+
+  // Indicates whether entries returned as a result of changes to
+  // directory data should include the entry change notification control.
+  private final boolean returnECs;
+
+  // The logical OR of change types associated with this control.
+  private final Set<PersistentSearchChangeType> changeTypes;
+
+  private final boolean isCritical;
+
+
+
+  private PersistentSearchRequestControl(final boolean isCritical,
+      final boolean changesOnly, final boolean returnECs,
+      final Set<PersistentSearchChangeType> changeTypes)
+  {
+    this.isCritical = isCritical;
+    this.changesOnly = changesOnly;
+    this.returnECs = returnECs;
+    this.changeTypes = changeTypes;
+  }
+
+
+
+  /**
+   * Returns an unmodifiable set containing the types of update operation for
+   * which change notifications should be returned.
+   *
+   * @return An unmodifiable set containing the types of update operation for
+   *         which change notifications should be returned.
+   */
+  public Set<PersistentSearchChangeType> getChangeTypes()
+  {
+    return changeTypes;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+
+      int changeTypesInt = 0;
+      for (final PersistentSearchChangeType changeType : changeTypes)
+      {
+        changeTypesInt |= changeType.intValue();
+      }
+      writer.writeInteger(changeTypesInt);
+
+      writer.writeBoolean(changesOnly);
+      writer.writeBoolean(returnECs);
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * Returns {@code true} if only updated entries should be returned (added,
+   * modified, deleted, or subject to a modifyDN operation), otherwise {@code
+   * false} if the search will initially return all the existing entries which
+   * match the filter.
+   *
+   * @return {@code true} if only updated entries should be returned (added,
+   *         modified, deleted, or subject to a modifyDN operation), otherwise
+   *         {@code false} if the search will initially return all the existing
+   *         entries which match the filter.
+   */
+  public boolean isChangesOnly()
+  {
+    return changesOnly;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * Returns {@code true} if the entry change notification control should be
+   * included in updated entries that match the associated search criteria.
+   *
+   * @return {@code true} if the entry change notification control should be
+   *         included in updated entries that match the associated search
+   *         criteria.
+   */
+  public boolean isReturnECs()
+  {
+    return returnECs;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PersistentSearchRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", changeTypes=[");
+
+    boolean comma = false;
+    for (final PersistentSearchChangeType type : changeTypes)
+    {
+      if (comma)
+      {
+        builder.append(", ");
+      }
+      builder.append(type);
+      comma = true;
+    }
+
+    builder.append("](");
+    builder.append(changeTypes);
+    builder.append("), changesOnly=");
+    builder.append(changesOnly);
+    builder.append(", returnECs=");
+    builder.append(returnECs);
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/PostReadControl.java b/sdk/src/org/opends/sdk/controls/PostReadControl.java
deleted file mode 100644
index d15ed28..0000000
--- a/sdk/src/org/opends/sdk/controls/PostReadControl.java
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ByteStringBuilder;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.ldap.LDAPUtils;
-import org.opends.sdk.responses.SearchResultEntry;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements the post-read control as defined in RFC 4527.
- * This control makes it possible to retrieve an entry in the state that
- * it held immediately after an add, modify, or modify DN operation. It
- * may specify a specific set of attributes that should be included in
- * that entry.
- */
-public class PostReadControl
-{
-  /**
-   * The IANA-assigned OID for the LDAP readentry control used for
-   * retrieving an
-   * entry in the state it had immediately after an update was applied.
-   */
-  public static final String OID_LDAP_READENTRY_POSTREAD = "1.3.6.1.1.13.2";
-
-
-
-  /**
-   * This class implements the post-read request control as defined in
-   * RFC 4527. This control makes it possible to retrieve an entry in
-   * the state that it held immediately after an add, modify, or modify
-   * DN operation. It may specify a specific set of attributes that
-   * should be included in that entry. The entry will be encoded in a
-   * corresponding response control.
-   */
-  public static class Request extends Control
-  {
-    // The set of raw attributes to return in the entry.
-    private final Set<String> attributes;
-
-
-
-    /**
-     * Creates a new post-read request control with the provided
-     * information.
-     *
-     * @param isCritical
-     *          Indicates whether support for this control should be
-     *          considered a critical part of the server processing.
-     * @param attributeDescriptions
-     *          The names of the attributes to be included with the
-     *          response control.
-     */
-    public Request(boolean isCritical, String... attributeDescriptions)
-    {
-      super(OID_LDAP_READENTRY_POSTREAD, isCritical);
-
-      this.attributes = new LinkedHashSet<String>();
-      if (attributeDescriptions != null)
-      {
-        this.attributes.addAll(Arrays.asList(attributeDescriptions));
-      }
-    }
-
-
-
-    private Request(boolean isCritical, Set<String> attributes)
-    {
-      super(OID_LDAP_READENTRY_POSTREAD, isCritical);
-
-      this.attributes = attributes;
-    }
-
-
-
-    /**
-     * Adds the provided attribute name to the list of attributes to be
-     * included in the response control. Attributes that are sub-types
-     * of listed attributes are implicitly included.
-     *
-     * @param attributeDescription
-     *          The name of the attribute to be included in the response
-     *          control.
-     * @return This post-read control.
-     * @throws NullPointerException
-     *           If {@code attributeDescription} was {@code null}.
-     */
-    public Request addAttribute(String attributeDescription)
-        throws NullPointerException
-    {
-      Validator.ensureNotNull(attributeDescription);
-      attributes.add(attributeDescription);
-      return this;
-    }
-
-
-
-    /**
-     * Returns an {@code Iterable} containing the list of attributes to
-     * be included with the response control. Attributes that are
-     * sub-types of listed attributes are implicitly included.
-     *
-     * @return An {@code Iterable} containing the list of attributes.
-     */
-    public Iterable<String> getAttributes()
-    {
-      return attributes;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public ByteString getValue()
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-      try
-      {
-        writer.writeStartSequence();
-        if (attributes != null)
-        {
-          for (String attr : attributes)
-          {
-            writer.writeOctetString(attr);
-          }
-        }
-        writer.writeEndSequence();
-        return buffer.toByteString();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("PostReadRequestControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", attributes=");
-      buffer.append(attributes);
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * This class implements the post-read response control as defined in
-   * RFC 4527. This control holds the search result entry representing
-   * the state of the entry immediately after an add, modify, or modify
-   * DN operation.
-   */
-  public static class Response extends Control
-  {
-    private final SearchResultEntry entry;
-
-
-
-    /**
-     * Creates a new post-read response control with the provided
-     * information.
-     *
-     * @param isCritical
-     *          Indicates whether support for this control should be
-     *          considered a critical part of the server processing.
-     * @param searchEntry
-     *          The search result entry to include in the response
-     *          control.
-     */
-    public Response(boolean isCritical, SearchResultEntry searchEntry)
-    {
-      super(OID_LDAP_READENTRY_POSTREAD, isCritical);
-
-      this.entry = searchEntry;
-    }
-
-
-
-    /**
-     * Creates a new post-read response control with the provided
-     * information.
-     *
-     * @param searchEntry
-     *          The search result entry to include in the response
-     *          control.
-     */
-    public Response(SearchResultEntry searchEntry)
-    {
-      this(false, searchEntry);
-    }
-
-
-
-    /**
-     * Returns the search result entry associated with this post-read
-     * response control.
-     *
-     * @return The search result entry associated with this post-read
-     *         response control.
-     */
-    public SearchResultEntry getSearchEntry()
-    {
-      return entry;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public ByteString getValue()
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-      try
-      {
-        LDAPUtils.encodeSearchResultEntry(writer, entry);
-        return buffer.toByteString();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("PostReadResponseControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", entry=");
-      buffer.append(entry);
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * Decodes a post-read request control from a byte string.
-   */
-  private final static class RequestDecoder implements
-      ControlDecoder<Request>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Request decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_POSTREADREQ_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      LinkedHashSet<String> attributes = new LinkedHashSet<String>();
-      try
-      {
-        reader.readStartSequence();
-        while (reader.hasNextElement())
-        {
-          attributes.add(reader.readOctetStringAsString());
-        }
-        reader.readEndSequence();
-      }
-      catch (Exception ae)
-      {
-        StaticUtils.DEBUG_LOG.throwing(
-            "PersistentSearchControl.RequestDecoder", "decode", ae);
-
-        LocalizableMessage message = ERR_POSTREADREQ_CANNOT_DECODE_VALUE.get(ae
-            .getMessage());
-        throw DecodeException.error(message, ae);
-      }
-
-      return new Request(isCritical, attributes);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getOID()
-    {
-      return OID_LDAP_READENTRY_POSTREAD;
-    }
-  }
-
-
-
-  /**
-   * Decodes a post-read response control from a byte string.
-   */
-  private final static class ResponseDecoder implements
-      ControlDecoder<Response>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Response decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_POSTREADRESP_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      SearchResultEntry searchEntry;
-      try
-      {
-        searchEntry = LDAPUtils.decodeSearchResultEntry(reader, schema);
-      }
-      catch (IOException le)
-      {
-        StaticUtils.DEBUG_LOG.throwing(
-            "PersistentSearchControl.ResponseDecoder", "decode", le);
-
-        LocalizableMessage message = ERR_POSTREADRESP_CANNOT_DECODE_VALUE.get(le
-            .getMessage());
-        throw DecodeException.error(message, le);
-      }
-
-      return new Response(isCritical, searchEntry);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getOID()
-    {
-      return OID_LDAP_READENTRY_POSTREAD;
-    }
-
-  }
-
-
-
-  /**
-   * A control decoder which can be used to decode post-read request
-   * controls.
-   */
-  public static final ControlDecoder<Request> REQUEST_DECODER = new RequestDecoder();
-
-  /**
-   * A control decoder which can be used to decode post-read respoens
-   * controls.
-   */
-  public static final ControlDecoder<Response> RESPONSE_DECODER = new ResponseDecoder();
-}
diff --git a/sdk/src/org/opends/sdk/controls/PostReadRequestControl.java b/sdk/src/org/opends/sdk/controls/PostReadRequestControl.java
new file mode 100644
index 0000000..dc4e2c3
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/PostReadRequestControl.java
@@ -0,0 +1,354 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_POSTREADREQ_CANNOT_DECODE_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_POSTREADREQ_NO_CONTROL_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_POSTREAD_CONTROL_BAD_OID;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The post-read request control as defined in RFC 4527. This control allows the
+ * client to read the target entry of an update operation immediately after the
+ * modifications are applied. These reads are done as an atomic part of the
+ * update operation.
+ *
+ * @see PostReadResponseControl
+ * @see <a href="http://tools.ietf.org/html/rfc4527">RFC 4527 - Lightweight
+ *      Directory Access Protocol (LDAP) Read Entry Controls </a>
+ */
+public final class PostReadRequestControl implements Control
+{
+  /**
+   * The IANA-assigned OID for the LDAP post-read request control used for
+   * retrieving an entry in the state it had immediately after an update was
+   * applied.
+   */
+  public static final String OID = "1.3.6.1.1.13.2";
+
+  // The set of raw attributes to return in the entry.
+  private final Set<String> attributes;
+
+  private final boolean isCritical;
+
+  private static final PostReadRequestControl CRITICAL_EMPTY_INSTANCE =
+    new PostReadRequestControl(true, Collections.<String> emptySet());
+
+  private static final PostReadRequestControl NONCRITICAL_EMPTY_INSTANCE =
+    new PostReadRequestControl(false, Collections.<String> emptySet());
+
+  /**
+   * A decoder which can be used for decoding the post-read request control.
+   */
+  public static final ControlDecoder<PostReadRequestControl> DECODER =
+    new ControlDecoder<PostReadRequestControl>()
+  {
+
+    public PostReadRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof PostReadRequestControl)
+      {
+        return (PostReadRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_POSTREAD_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The control must always have a value.
+        final LocalizableMessage message = ERR_POSTREADREQ_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      Set<String> attributes;
+      try
+      {
+        reader.readStartSequence();
+        if (reader.hasNextElement())
+        {
+          final String firstAttribute = reader.readOctetStringAsString();
+          if (reader.hasNextElement())
+          {
+            attributes = new LinkedHashSet<String>();
+            attributes.add(firstAttribute);
+            do
+            {
+              attributes.add(reader.readOctetStringAsString());
+            }
+            while (reader.hasNextElement());
+            attributes = Collections.unmodifiableSet(attributes);
+          }
+          else
+          {
+            attributes = Collections.singleton(firstAttribute);
+          }
+        }
+        else
+        {
+          attributes = Collections.emptySet();
+        }
+        reader.readEndSequence();
+      }
+      catch (final Exception ae)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PostReadRequestControl",
+            "decodeControl", ae);
+
+        final LocalizableMessage message = ERR_POSTREADREQ_CANNOT_DECODE_VALUE
+            .get(ae.getMessage());
+        throw DecodeException.error(message, ae);
+      }
+
+      if (attributes.isEmpty())
+      {
+        return control.isCritical() ? CRITICAL_EMPTY_INSTANCE
+            : NONCRITICAL_EMPTY_INSTANCE;
+      }
+      else
+      {
+        return new PostReadRequestControl(control.isCritical(), attributes);
+      }
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new post-read request control.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored
+   * @param attributes
+   *          The list of attributes to be included with the response control.
+   *          Attributes that are sub-types of listed attributes are implicitly
+   *          included. The list may be empty, indicating that all user
+   *          attributes should be returned.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code attributes} was {@code null}.
+   */
+  public static PostReadRequestControl newControl(final boolean isCritical,
+      final Collection<String> attributes) throws NullPointerException
+  {
+    Validator.ensureNotNull(attributes);
+
+    if (attributes.isEmpty())
+    {
+      return isCritical ? CRITICAL_EMPTY_INSTANCE : NONCRITICAL_EMPTY_INSTANCE;
+    }
+    else if (attributes.size() == 1)
+    {
+      return new PostReadRequestControl(isCritical, Collections
+          .singleton(attributes.iterator().next()));
+    }
+    else
+    {
+      final Set<String> attributeSet = new LinkedHashSet<String>(attributes);
+      return new PostReadRequestControl(isCritical, Collections
+          .unmodifiableSet(attributeSet));
+    }
+  }
+
+
+
+  /**
+   * Creates a new post-read request control.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored
+   * @param attributes
+   *          The list of attributes to be included with the response control.
+   *          Attributes that are sub-types of listed attributes are implicitly
+   *          included. The list may be empty, indicating that all user
+   *          attributes should be returned.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code attributes} was {@code null}.
+   */
+  public static PostReadRequestControl newControl(final boolean isCritical,
+      final String... attributes) throws NullPointerException
+  {
+    Validator.ensureNotNull((Object) attributes);
+
+    if (attributes.length == 0)
+    {
+      return isCritical ? CRITICAL_EMPTY_INSTANCE : NONCRITICAL_EMPTY_INSTANCE;
+    }
+    else if (attributes.length == 1)
+    {
+      return new PostReadRequestControl(isCritical, Collections
+          .singleton(attributes[0]));
+    }
+    else
+    {
+      final Set<String> attributeSet = new LinkedHashSet<String>(Arrays
+          .asList(attributes));
+      return new PostReadRequestControl(isCritical, Collections
+          .unmodifiableSet(attributeSet));
+    }
+  }
+
+
+
+  private PostReadRequestControl(final boolean isCritical,
+      final Set<String> attributes)
+  {
+    this.isCritical = isCritical;
+    this.attributes = attributes;
+  }
+
+
+
+  /**
+   * Returns an unmodifiable set containing the names of attributes to be
+   * included with the response control. Attributes that are sub-types of listed
+   * attributes are implicitly included. The returned set may be empty,
+   * indicating that all user attributes should be returned.
+   *
+   * @return An unmodifiable set containing the names of attributes to be
+   *         included with the response control.
+   */
+  public Set<String> getAttributes()
+  {
+    return attributes;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      if (attributes != null)
+      {
+        for (final String attr : attributes)
+        {
+          writer.writeOctetString(attr);
+        }
+      }
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PostReadRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", attributes=");
+    builder.append(attributes);
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/PostReadResponseControl.java b/sdk/src/org/opends/sdk/controls/PostReadResponseControl.java
new file mode 100644
index 0000000..ecbb514
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/PostReadResponseControl.java
@@ -0,0 +1,259 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_POSTREADRESP_CANNOT_DECODE_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_POSTREADRESP_NO_CONTROL_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_POSTREAD_CONTROL_BAD_OID;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.responses.Responses;
+import org.opends.sdk.responses.SearchResultEntry;
+
+import com.sun.opends.sdk.ldap.LDAPUtils;
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The post-read response control as defined in RFC 4527. This control is
+ * returned by the server in response to a successful update operation which
+ * included a post-read request control. The control contains a Search Result
+ * Entry containing, subject to access controls and other constraints, values of
+ * the requested attributes.
+ *
+ * @see PostReadRequestControl
+ * @see <a href="http://tools.ietf.org/html/rfc4527">RFC 4527 - Lightweight
+ *      Directory Access Protocol (LDAP) Read Entry Controls </a>
+ */
+public final class PostReadResponseControl implements Control
+{
+  /**
+   * The IANA-assigned OID for the LDAP post-read response control used for
+   * retrieving an entry in the state it had immediately after an update was
+   * applied.
+   */
+  public static final String OID = PostReadRequestControl.OID;
+
+  /**
+   * A decoder which can be used for decoding the post-read response control.
+   */
+  public static final ControlDecoder<PostReadResponseControl> DECODER =
+    new ControlDecoder<PostReadResponseControl>()
+  {
+
+    public PostReadResponseControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof PostReadResponseControl)
+      {
+        return (PostReadResponseControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_POSTREAD_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The control must always have a value.
+        final LocalizableMessage message = ERR_POSTREADRESP_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      SearchResultEntry searchEntry;
+      try
+      {
+        searchEntry = LDAPUtils.decodeSearchResultEntry(reader, options);
+      }
+      catch (final IOException le)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PostReadResponseControl",
+            "decodeControl", le);
+
+        final LocalizableMessage message = ERR_POSTREADRESP_CANNOT_DECODE_VALUE
+            .get(le.getMessage());
+        throw DecodeException.error(message, le);
+      }
+
+      /**
+       * FIXME: the RFC states that the control contains a SearchResultEntry
+       * rather than an Entry. Can we assume that the response will not contain
+       * a nested set of controls?
+       */
+      return new PostReadResponseControl(control.isCritical(), Types
+          .unmodifiableEntry(searchEntry));
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new post-read response control.
+   *
+   * @param entry
+   *          The entry whose contents reflect the state of the updated entry
+   *          immediately after the update operation was performed.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code entry} was {@code null}.
+   */
+  public static PostReadResponseControl newControl(final Entry entry)
+      throws NullPointerException
+  {
+    /**
+     * FIXME: all other control implementations are fully immutable. We should
+     * really do a defensive copy here in order to be consistent, rather than
+     * just wrap it. Also, the RFC states that the control contains a
+     * SearchResultEntry rather than an Entry. Can we assume that the response
+     * will not contain a nested set of controls?
+     */
+    return new PostReadResponseControl(false, Types.unmodifiableEntry(entry));
+  }
+
+
+
+  private final Entry entry;
+
+  private final boolean isCritical;
+
+
+
+  private PostReadResponseControl(final boolean isCritical, final Entry entry)
+  {
+    this.isCritical = isCritical;
+    this.entry = entry;
+  }
+
+
+
+  /**
+   * Returns an unmodifiable entry whose contents reflect the state of the
+   * updated entry immediately after the update operation was performed.
+   *
+   * @return The unmodifiable entry whose contents reflect the state of the
+   *         updated entry immediately after the update operation was performed.
+   */
+  public Entry getEntry()
+  {
+    return entry;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      LDAPUtils.encodeSearchResultEntry(writer, Responses
+          .newSearchResultEntry(entry));
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PostReadResponseControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", entry=");
+    builder.append(entry);
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/PreReadControl.java b/sdk/src/org/opends/sdk/controls/PreReadControl.java
deleted file mode 100644
index e99101a..0000000
--- a/sdk/src/org/opends/sdk/controls/PreReadControl.java
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ByteStringBuilder;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.ldap.LDAPUtils;
-import org.opends.sdk.responses.SearchResultEntry;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements the pre-read request control as defined in RFC
- * 4527. This control makes it possible to retrieve an entry in the
- * state that it held immediately before a modify, delete, or modify DN
- * operation. It may specify a specific set of attributes that should be
- * included in that entry.
- */
-public class PreReadControl
-{
-  /**
-   * The IANA-assigned OID for the LDAP readentry control used for
-   * retrieving an
-   * entry in the state it had immediately before an update was applied.
-   */
-  public static final String OID_LDAP_READENTRY_PREREAD = "1.3.6.1.1.13.1";
-
-
-
-  /**
-   * This class implements the pre-read request control as defined in
-   * RFC 4527. This control makes it possible to retrieve an entry in
-   * the state that it held immediately before a modify, delete, or
-   * modify DN operation. It may specify a specific set of attributes
-   * that should be included in that entry. The entry will be encoded in
-   * a corresponding response control.
-   */
-  public static class Request extends Control
-  {
-    // The set of raw attributes to return in the entry.
-    private final Set<String> attributes;
-
-
-
-    /**
-     * Creates a new pre-read request control with the provided
-     * information.
-     *
-     * @param isCritical
-     *          Indicates whether support for this control should be
-     *          considered a critical part of the server processing.
-     * @param attributeDescriptions
-     *          The names of the attributes to be included with the
-     *          response control.
-     */
-    public Request(boolean isCritical, String... attributeDescriptions)
-    {
-      super(OID_LDAP_READENTRY_PREREAD, isCritical);
-
-      this.attributes = new LinkedHashSet<String>();
-      if (attributeDescriptions != null)
-      {
-        this.attributes.addAll(Arrays.asList(attributeDescriptions));
-      }
-    }
-
-
-
-    private Request(boolean isCritical, Set<String> attributes)
-    {
-      super(OID_LDAP_READENTRY_PREREAD, isCritical);
-
-      this.attributes = attributes;
-    }
-
-
-
-    /**
-     * Adds the provided attribute name to the list of attributes to be
-     * included in the request control. Attributes that are sub-types
-     * of listed attributes are implicitly included.
-     *
-     * @param attributeDescription
-     *          The name of the attribute to be included in the response
-     *          control.
-     * @return This post-read control.
-     * @throws NullPointerException
-     *           If {@code attributeDescription} was {@code null}.
-     */
-    public Request addAttribute(String attributeDescription)
-        throws NullPointerException
-    {
-      Validator.ensureNotNull(attributeDescription);
-      attributes.add(attributeDescription);
-      return this;
-    }
-
-
-
-    /**
-     * Returns an {@code Iterable} containing the list of attributes to
-     * be included with the response control. Attributes that are
-     * sub-types of listed attributes are implicitly included.
-     *
-     * @return An {@code Iterable} containing the list of attributes.
-     */
-    public Iterable<String> getAttributes()
-    {
-      return attributes;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public ByteString getValue()
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-      try
-      {
-        writer.writeStartSequence();
-        if (attributes != null)
-        {
-          for (String attr : attributes)
-          {
-            writer.writeOctetString(attr);
-          }
-        }
-        writer.writeEndSequence();
-        return buffer.toByteString();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("PreReadRequestControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", attributes=");
-      buffer.append(attributes);
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * This class implements the pre-read response control as defined in
-   * RFC 4527. This control holds the search result entry representing
-   * the state of the entry immediately before an add, modify, or modify
-   * DN operation.
-   */
-  public static class Response extends Control
-  {
-    private final SearchResultEntry entry;
-
-
-
-    /**
-     * Creates a new pre-read response control with the provided
-     * information.
-     *
-     * @param isCritical
-     *          Indicates whether support for this control should be
-     *          considered a critical part of the server processing.
-     * @param searchEntry
-     *          The search result entry to include in the response
-     *          control.
-     */
-    public Response(boolean isCritical, SearchResultEntry searchEntry)
-    {
-      super(OID_LDAP_READENTRY_PREREAD, isCritical);
-
-      this.entry = searchEntry;
-    }
-
-
-
-    /**
-     * Creates a new pre-read response control with the provided
-     * information.
-     *
-     * @param searchEntry
-     *          The search result entry to include in the response
-     *          control.
-     */
-    public Response(SearchResultEntry searchEntry)
-    {
-      this(false, searchEntry);
-    }
-
-
-
-    /**
-     * Returns the search result entry associated with this post-read
-     * response control.
-     *
-     * @return The search result entry associated with this post-read
-     *         response control.
-     */
-    public SearchResultEntry getSearchEntry()
-    {
-      return entry;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public ByteString getValue()
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-      try
-      {
-        LDAPUtils.encodeSearchResultEntry(writer, entry);
-        return buffer.toByteString();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("PreReadResponseControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", entry=");
-      buffer.append(entry);
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * Decodes a pre-read request control from a byte string.
-   */
-  private final static class RequestDecoder implements
-      ControlDecoder<Request>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Request decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_PREREADREQ_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      LinkedHashSet<String> attributes = new LinkedHashSet<String>();
-      try
-      {
-        reader.readStartSequence();
-        while (reader.hasNextElement())
-        {
-          attributes.add(reader.readOctetStringAsString());
-        }
-        reader.readEndSequence();
-      }
-      catch (Exception ae)
-      {
-        StaticUtils.DEBUG_LOG.throwing("PreReadControl.RequestDecoder",
-            "decode", ae);
-
-        LocalizableMessage message = ERR_PREREADREQ_CANNOT_DECODE_VALUE.get(ae
-            .getMessage());
-        throw DecodeException.error(message, ae);
-      }
-
-      return new Request(isCritical, attributes);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getOID()
-    {
-      return OID_LDAP_READENTRY_PREREAD;
-    }
-  }
-
-
-
-  /**
-   * Decodes a pre-read response control from a byte string.
-   */
-  private final static class ResponseDecoder implements
-      ControlDecoder<Response>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Response decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_PREREADRESP_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      SearchResultEntry searchEntry;
-      try
-      {
-        searchEntry = LDAPUtils.decodeSearchResultEntry(reader, schema);
-      }
-      catch (IOException le)
-      {
-        StaticUtils.DEBUG_LOG.throwing(
-            "PersistentSearchControl.ResponseDecoder", "decode", le);
-
-        LocalizableMessage message = ERR_PREREADRESP_CANNOT_DECODE_VALUE.get(le
-            .getMessage());
-        throw DecodeException.error(message, le);
-      }
-
-      return new Response(isCritical, searchEntry);
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getOID()
-    {
-      return OID_LDAP_READENTRY_PREREAD;
-    }
-
-  }
-
-
-
-  /**
-   * A control decoder which can be used to decode pre-read request
-   * controls.
-   */
-  public static final ControlDecoder<Request> REQUEST_DECODER = new RequestDecoder();
-
-  /**
-   * A control decoder which can be used to decode pre-read respoens
-   * controls.
-   */
-  public static final ControlDecoder<Response> RESPONSE_DECODER = new ResponseDecoder();
-}
diff --git a/sdk/src/org/opends/sdk/controls/PreReadRequestControl.java b/sdk/src/org/opends/sdk/controls/PreReadRequestControl.java
new file mode 100644
index 0000000..9310876
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/PreReadRequestControl.java
@@ -0,0 +1,354 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_PREREADREQ_CANNOT_DECODE_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_PREREADREQ_NO_CONTROL_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_PREREAD_CONTROL_BAD_OID;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The pre-read request control as defined in RFC 4527. This control allows the
+ * client to read the target entry of an update operation immediately before the
+ * modifications are applied. These reads are done as an atomic part of the
+ * update operation.
+ *
+ * @see PreReadResponseControl
+ * @see <a href="http://tools.ietf.org/html/rfc4527">RFC 4527 - Lightweight
+ *      Directory Access Protocol (LDAP) Read Entry Controls </a>
+ */
+public final class PreReadRequestControl implements Control
+{
+  /**
+   * The IANA-assigned OID for the LDAP pre-read request control used for
+   * retrieving an entry in the state it had immediately before an update was
+   * applied.
+   */
+  public static final String OID = "1.3.6.1.1.13.1";
+
+  // The set of raw attributes to return in the entry.
+  private final Set<String> attributes;
+
+  private final boolean isCritical;
+
+  private static final PreReadRequestControl CRITICAL_EMPTY_INSTANCE = new PreReadRequestControl(
+      true, Collections.<String> emptySet());
+
+  private static final PreReadRequestControl NONCRITICAL_EMPTY_INSTANCE = new PreReadRequestControl(
+      false, Collections.<String> emptySet());
+
+  /**
+   * A decoder which can be used for decoding the pre-read request control.
+   */
+  public static final ControlDecoder<PreReadRequestControl> DECODER =
+    new ControlDecoder<PreReadRequestControl>()
+  {
+
+    public PreReadRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof PreReadRequestControl)
+      {
+        return (PreReadRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_PREREAD_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The control must always have a value.
+        final LocalizableMessage message = ERR_PREREADREQ_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      Set<String> attributes;
+      try
+      {
+        reader.readStartSequence();
+        if (reader.hasNextElement())
+        {
+          final String firstAttribute = reader.readOctetStringAsString();
+          if (reader.hasNextElement())
+          {
+            attributes = new LinkedHashSet<String>();
+            attributes.add(firstAttribute);
+            do
+            {
+              attributes.add(reader.readOctetStringAsString());
+            }
+            while (reader.hasNextElement());
+            attributes = Collections.unmodifiableSet(attributes);
+          }
+          else
+          {
+            attributes = Collections.singleton(firstAttribute);
+          }
+        }
+        else
+        {
+          attributes = Collections.emptySet();
+        }
+        reader.readEndSequence();
+      }
+      catch (final Exception ae)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PreReadRequestControl",
+            "decodeControl", ae);
+
+        final LocalizableMessage message = ERR_PREREADREQ_CANNOT_DECODE_VALUE
+            .get(ae.getMessage());
+        throw DecodeException.error(message, ae);
+      }
+
+      if (attributes.isEmpty())
+      {
+        return control.isCritical() ? CRITICAL_EMPTY_INSTANCE
+            : NONCRITICAL_EMPTY_INSTANCE;
+      }
+      else
+      {
+        return new PreReadRequestControl(control.isCritical(), attributes);
+      }
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new pre-read request control.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored
+   * @param attributes
+   *          The list of attributes to be included with the response control.
+   *          Attributes that are sub-types of listed attributes are implicitly
+   *          included. The list may be empty, indicating that all user
+   *          attributes should be returned.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code attributes} was {@code null}.
+   */
+  public static PreReadRequestControl newControl(final boolean isCritical,
+      final Collection<String> attributes) throws NullPointerException
+  {
+    Validator.ensureNotNull(attributes);
+
+    if (attributes.isEmpty())
+    {
+      return isCritical ? CRITICAL_EMPTY_INSTANCE : NONCRITICAL_EMPTY_INSTANCE;
+    }
+    else if (attributes.size() == 1)
+    {
+      return new PreReadRequestControl(isCritical, Collections
+          .singleton(attributes.iterator().next()));
+    }
+    else
+    {
+      final Set<String> attributeSet = new LinkedHashSet<String>(attributes);
+      return new PreReadRequestControl(isCritical, Collections
+          .unmodifiableSet(attributeSet));
+    }
+  }
+
+
+
+  /**
+   * Creates a new pre-read request control.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored
+   * @param attributes
+   *          The list of attributes to be included with the response control.
+   *          Attributes that are sub-types of listed attributes are implicitly
+   *          included. The list may be empty, indicating that all user
+   *          attributes should be returned.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code attributes} was {@code null}.
+   */
+  public static PreReadRequestControl newControl(final boolean isCritical,
+      final String... attributes) throws NullPointerException
+  {
+    Validator.ensureNotNull((Object) attributes);
+
+    if (attributes.length == 0)
+    {
+      return isCritical ? CRITICAL_EMPTY_INSTANCE : NONCRITICAL_EMPTY_INSTANCE;
+    }
+    else if (attributes.length == 1)
+    {
+      return new PreReadRequestControl(isCritical, Collections
+          .singleton(attributes[0]));
+    }
+    else
+    {
+      final Set<String> attributeSet = new LinkedHashSet<String>(Arrays
+          .asList(attributes));
+      return new PreReadRequestControl(isCritical, Collections
+          .unmodifiableSet(attributeSet));
+    }
+  }
+
+
+
+  private PreReadRequestControl(final boolean isCritical,
+      final Set<String> attributes)
+  {
+    this.isCritical = isCritical;
+    this.attributes = attributes;
+  }
+
+
+
+  /**
+   * Returns an unmodifiable set containing the names of attributes to be
+   * included with the response control. Attributes that are sub-types of listed
+   * attributes are implicitly included. The returned set may be empty,
+   * indicating that all user attributes should be returned.
+   *
+   * @return An unmodifiable set containing the names of attributes to be
+   *         included with the response control.
+   */
+  public Set<String> getAttributes()
+  {
+    return attributes;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      if (attributes != null)
+      {
+        for (final String attr : attributes)
+        {
+          writer.writeOctetString(attr);
+        }
+      }
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PreReadRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", attributes=");
+    builder.append(attributes);
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/PreReadResponseControl.java b/sdk/src/org/opends/sdk/controls/PreReadResponseControl.java
new file mode 100644
index 0000000..2854ca1
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/PreReadResponseControl.java
@@ -0,0 +1,260 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_PREREADRESP_CANNOT_DECODE_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_PREREADRESP_NO_CONTROL_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_PREREAD_CONTROL_BAD_OID;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.responses.Responses;
+import org.opends.sdk.responses.SearchResultEntry;
+
+import com.sun.opends.sdk.ldap.LDAPUtils;
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The pre-read response control as defined in RFC 4527. This control is
+ * returned by the server in response to a successful update operation which
+ * included a pre-read request control. The control contains a Search Result
+ * Entry containing, subject to access controls and other constraints, values of
+ * the requested attributes.
+ *
+ * @see PreReadRequestControl
+ * @see <a href="http://tools.ietf.org/html/rfc4527">RFC 4527 - Lightweight
+ *      Directory Access Protocol (LDAP) Read Entry Controls </a>
+ */
+public final class PreReadResponseControl implements Control
+{
+  /**
+   * The IANA-assigned OID for the LDAP pre-read response control used for
+   * retrieving an entry in the state it had immediately before an update was
+   * applied.
+   */
+  public static final String OID = PreReadRequestControl.OID;
+
+  /**
+   * A decoder which can be used for decoding the pre-read response control.
+   */
+  public static final ControlDecoder<PreReadResponseControl> DECODER =
+    new ControlDecoder<PreReadResponseControl>()
+  {
+
+    public PreReadResponseControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof PreReadResponseControl)
+      {
+        return (PreReadResponseControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_PREREAD_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The control must always have a value.
+        final LocalizableMessage message = ERR_PREREADRESP_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      SearchResultEntry searchEntry;
+      try
+      {
+        searchEntry = LDAPUtils.decodeSearchResultEntry(reader, options);
+      }
+      catch (final IOException le)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PreReadResponseControl",
+            "decodeControl", le);
+
+        final LocalizableMessage message = ERR_PREREADRESP_CANNOT_DECODE_VALUE
+            .get(le.getMessage());
+        throw DecodeException.error(message, le);
+      }
+
+      /**
+       * FIXME: the RFC states that the control contains a SearchResultEntry
+       * rather than an Entry. Can we assume that the response will not contain
+       * a nested set of controls?
+       */
+      return new PreReadResponseControl(control.isCritical(), Types
+          .unmodifiableEntry(searchEntry));
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new pre-read response control.
+   *
+   * @param entry
+   *          The entry whose contents reflect the state of the updated entry
+   *          immediately before the update operation was performed.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code entry} was {@code null}.
+   */
+  public static PreReadResponseControl newControl(final Entry entry)
+      throws NullPointerException
+  {
+    /**
+     * FIXME: all other control implementations are fully immutable. We should
+     * really do a defensive copy here in order to be consistent, rather than
+     * just wrap it. Also, the RFC states that the control contains a
+     * SearchResultEntry rather than an Entry. Can we assume that the response
+     * will not contain a nested set of controls?
+     */
+    return new PreReadResponseControl(false, Types.unmodifiableEntry(entry));
+  }
+
+
+
+  private final Entry entry;
+
+  private final boolean isCritical;
+
+
+
+  private PreReadResponseControl(final boolean isCritical, final Entry entry)
+  {
+    this.isCritical = isCritical;
+    this.entry = entry;
+  }
+
+
+
+  /**
+   * Returns an unmodifiable entry whose contents reflect the state of the
+   * updated entry immediately before the update operation was performed.
+   *
+   * @return The unmodifiable entry whose contents reflect the state of the
+   *         updated entry immediately before the update operation was
+   *         performed.
+   */
+  public Entry getEntry()
+  {
+    return entry;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      LDAPUtils.encodeSearchResultEntry(writer, Responses
+          .newSearchResultEntry(entry));
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PreReadResponseControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", entry=");
+    builder.append(entry);
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/ProxiedAuthV1Control.java b/sdk/src/org/opends/sdk/controls/ProxiedAuthV1Control.java
deleted file mode 100644
index e1ecf82..0000000
--- a/sdk/src/org/opends/sdk/controls/ProxiedAuthV1Control.java
+++ /dev/null
@@ -1,211 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements version 1 of the proxied authorization control
- * as defined in early versions of draft-weltman-ldapv3-proxy (this
- * implementation is based on the "-04" revision). It makes it possible
- * for one user to request that an operation be performed under the
- * authorization of another. The target user is specified as a DN in the
- * control value, which distinguishes it from later versions of the
- * control (which used a different OID) in which the target user was
- * specified using an authorization ID.
- */
-public class ProxiedAuthV1Control extends Control
-{
-  /**
-   * The OID for the proxied authorization v1 control.
-   */
-  public static final String OID_PROXIED_AUTH_V1 = "2.16.840.1.113730.3.4.12";
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class Decoder implements
-      ControlDecoder<ProxiedAuthV1Control>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public ProxiedAuthV1Control decode(boolean isCritical,
-        ByteString value, Schema schema) throws DecodeException
-    {
-      if (!isCritical)
-      {
-        LocalizableMessage message = ERR_PROXYAUTH1_CONTROL_NOT_CRITICAL.get();
-        throw DecodeException.error(message);
-      }
-
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_PROXYAUTH1_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      String authorizationDN;
-      try
-      {
-        reader.readStartSequence();
-        authorizationDN = reader.readOctetStringAsString();
-        reader.readEndSequence();
-      }
-      catch (IOException e)
-      {
-        StaticUtils.DEBUG_LOG.throwing("ProxiedAuthV1Control.Decoder",
-            "decode", e);
-
-        LocalizableMessage message = ERR_PROXYAUTH1_CANNOT_DECODE_VALUE
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message, e);
-      }
-
-      return new ProxiedAuthV1Control(authorizationDN);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_PROXIED_AUTH_V1;
-    }
-
-  }
-
-
-
-  /**
-   * The Control Decoder that can be used to decode this control.
-   */
-  public static final ControlDecoder<ProxiedAuthV1Control> DECODER = new Decoder();
-
-  // The raw, unprocessed authorization DN from the control value.
-  private String authorizationDN;
-
-
-
-  /**
-   * Creates a new instance of the proxied authorization v1 control with
-   * the provided information.
-   * 
-   * @param authorizationDN
-   *          The authorization DN from the control value. It must not
-   *          be {@code null}.
-   */
-  public ProxiedAuthV1Control(DN authorizationDN)
-  {
-    super(OID_PROXIED_AUTH_V1, true);
-
-    Validator.ensureNotNull(authorizationDN);
-    this.authorizationDN = authorizationDN.toString();
-  }
-
-
-
-  /**
-   * Creates a new instance of the proxied authorization v1 control with
-   * the provided information.
-   * 
-   * @param authorizationDN
-   *          The raw, unprocessed authorization DN from the control
-   *          value. It must not be {@code null}.
-   */
-  public ProxiedAuthV1Control(String authorizationDN)
-  {
-    super(OID_PROXIED_AUTH_V1, true);
-
-    Validator.ensureNotNull(authorizationDN);
-    this.authorizationDN = authorizationDN;
-  }
-
-
-
-  /**
-   * Retrieves the raw, unprocessed authorization DN from the control
-   * value.
-   * 
-   * @return The raw, unprocessed authorization DN from the control
-   *         value.
-   */
-  public String getAuthorizationDN()
-  {
-    return authorizationDN;
-  }
-
-
-
-  @Override
-  public ByteString getValue()
-  {
-    return ByteString.valueOf(authorizationDN);
-  }
-
-
-
-  @Override
-  public boolean hasValue()
-  {
-    return true;
-  }
-
-
-
-  public ProxiedAuthV1Control setAuthorizationDN(DN authorizationDN)
-  {
-    Validator.ensureNotNull(authorizationDN);
-    this.authorizationDN = authorizationDN.toString();
-    return this;
-  }
-
-
-
-  public ProxiedAuthV1Control setAuthorizationDN(String authorizationDN)
-  {
-    Validator.ensureNotNull(authorizationDN);
-    this.authorizationDN = authorizationDN;
-    return this;
-  }
-
-
-
-  /**
-   * Appends a string representation of this proxied auth v1 control to
-   * the provided buffer.
-   * 
-   * @param buffer
-   *          The buffer to which the information should be appended.
-   */
-  @Override
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("ProxiedAuthorizationV1Control(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(", authorizationDN=\"");
-    buffer.append(authorizationDN);
-    buffer.append("\")");
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/ProxiedAuthV1RequestControl.java b/sdk/src/org/opends/sdk/controls/ProxiedAuthV1RequestControl.java
new file mode 100644
index 0000000..80d9394
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/ProxiedAuthV1RequestControl.java
@@ -0,0 +1,294 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.schema.Schema;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The proxy authorization v1 request control as defined in
+ * draft-weltman-ldapv3-proxy-04. This control allows a user to request that an
+ * operation be performed using the authorization of another user. The target
+ * user is specified as a DN in the control value, which distinguishes it from
+ * later versions of the control (which used a different OID) in which the
+ * target user was specified using an authorization ID.
+ * <p>
+ * This control implementation is based on version 1 of the proxied
+ * authorization control as defined in early versions of
+ * draft-weltman-ldapv3-proxy (this implementation is based on the "-04"
+ * revision) and is intended for use in legacy applications. New applications
+ * should use the v2 version of this control in preference.
+ *
+ * @see <a href="http://tools.ietf.org/html/draft-weltman-ldapv3-proxy-04">
+ *         draft-weltman-ldapv3-proxy-04 - LDAP Proxied Authorization Control </a>
+ */
+public final class ProxiedAuthV1RequestControl implements Control
+{
+  /**
+   * The OID for the proxied authorization v1 control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.12";
+
+  /**
+   * A decoder which can be used for decoding the proxied authorization v1
+   * request control.
+   */
+  public static final ControlDecoder<ProxiedAuthV1RequestControl> DECODER =
+    new ControlDecoder<ProxiedAuthV1RequestControl>()
+  {
+
+    public ProxiedAuthV1RequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof ProxiedAuthV1RequestControl)
+      {
+        return (ProxiedAuthV1RequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_PROXYAUTH1_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.isCritical())
+      {
+        final LocalizableMessage message = ERR_PROXYAUTH1_CONTROL_NOT_CRITICAL
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The response control must always have a value.
+        final LocalizableMessage message = ERR_PROXYAUTH1_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      String authorizationDNString;
+      try
+      {
+        reader.readStartSequence();
+        authorizationDNString = reader.readOctetStringAsString();
+        reader.readEndSequence();
+      }
+      catch (final IOException e)
+      {
+        StaticUtils.DEBUG_LOG.throwing("ProxiedAuthV1RequestControl",
+            "decodeControl", e);
+
+        final LocalizableMessage message = ERR_PROXYAUTH1_CANNOT_DECODE_VALUE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+
+      final Schema schema = options.getSchemaResolver().resolveSchema(
+          authorizationDNString);
+      DN authorizationDN;
+      try
+      {
+        authorizationDN = DN.valueOf(authorizationDNString, schema);
+      }
+      catch (final LocalizedIllegalArgumentException e)
+      {
+        final LocalizableMessage message = ERR_PROXYAUTH1_INVALID_AUTHZIDDN
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+
+      return new ProxiedAuthV1RequestControl(authorizationDN);
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new proxy authorization v1 request control with the provided
+   * authorization name.
+   *
+   * @param authorizationName
+   *          The distinguished name of the user whose authorization is to be
+   *          used when performing the operation.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code authorizationName} was {@code null}.
+   */
+  public static ProxiedAuthV1RequestControl newControl(
+      final DN authorizationName) throws NullPointerException
+  {
+    Validator.ensureNotNull(authorizationName);
+    return new ProxiedAuthV1RequestControl(authorizationName);
+  }
+
+
+
+  /**
+   * Creates a new proxy authorization v1 request control with the provided
+   * authorization name decoded using the default schema.
+   *
+   * @param authorizationName
+   *          The distinguished name of the user whose authorization is to be
+   *          used when performing the operation.
+   * @return The new control.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authorizationName} is not a valid LDAP string
+   *           representation of a DN.
+   * @throws NullPointerException
+   *           If {@code authorizationName} was {@code null}.
+   */
+  public static ProxiedAuthV1RequestControl newControl(
+      final String authorizationName) throws LocalizedIllegalArgumentException,
+      NullPointerException
+  {
+    Validator.ensureNotNull(authorizationName);
+    return new ProxiedAuthV1RequestControl(DN.valueOf(authorizationName));
+  }
+
+
+
+  private final DN authorizationName;
+
+
+
+  private ProxiedAuthV1RequestControl(final DN authorizationName)
+  {
+    this.authorizationName = authorizationName;
+  }
+
+
+
+  /**
+   * Returns the distinguished name of the user whose authorization is to be
+   * used when performing the operation.
+   *
+   * @return The distinguished name of the user whose authorization is to be
+   *         used when performing the operation.
+   */
+  public DN getAuthorizationDNName()
+  {
+    return authorizationName;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      writer.writeOctetString(authorizationName.toString());
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder buffer = new StringBuilder();
+    buffer.append("ProxiedAuthorizationV1Control(oid=");
+    buffer.append(getOID());
+    buffer.append(", criticality=");
+    buffer.append(isCritical());
+    buffer.append(", proxyDN=\"");
+    buffer.append(authorizationName);
+    buffer.append("\")");
+    return buffer.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/ProxiedAuthV2Control.java b/sdk/src/org/opends/sdk/controls/ProxiedAuthV2Control.java
deleted file mode 100644
index b1f2eb5..0000000
--- a/sdk/src/org/opends/sdk/controls/ProxiedAuthV2Control.java
+++ /dev/null
@@ -1,215 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements version 2 of the proxied authorization control
- * as defined in RFC 4370. It makes it possible for one user to request
- * that an operation be performed under the authorization of another.
- * The target user is specified using an authorization ID, which may be
- * in the form "dn:" immediately followed by the DN of that user, or
- * "u:" followed by a user ID string.
- */
-public class ProxiedAuthV2Control extends Control
-{
-  /**
-   * The OID for the proxied authorization v2 control.
-   */
-  public static final String OID_PROXIED_AUTH_V2 = "2.16.840.1.113730.3.4.18";
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private static final class Decoder implements
-      ControlDecoder<ProxiedAuthV2Control>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public ProxiedAuthV2Control decode(boolean isCritical,
-        ByteString value, Schema schema) throws DecodeException
-    {
-      if (!isCritical)
-      {
-        LocalizableMessage message = ERR_PROXYAUTH2_CONTROL_NOT_CRITICAL.get();
-        throw DecodeException.error(message);
-      }
-
-      if (value == null)
-      {
-        LocalizableMessage message = ERR_PROXYAUTH2_NO_CONTROL_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      String authorizationID;
-
-      try
-      {
-        if (reader.elementAvailable())
-        {
-          // Try the legacy encoding where the value is wrapped by an
-          // extra octet string
-          authorizationID = reader.readOctetStringAsString();
-        }
-        else
-        {
-          authorizationID = value.toString();
-        }
-      }
-      catch (IOException e)
-      {
-        StaticUtils.DEBUG_LOG.throwing("ProxiedAuthV2Control.Decoder",
-            "decode", e);
-
-        LocalizableMessage message = ERR_PROXYAUTH2_CANNOT_DECODE_VALUE
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message, e);
-      }
-
-      return new ProxiedAuthV2Control(authorizationID);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_PROXIED_AUTH_V2;
-    }
-
-  }
-
-
-
-  /**
-   * The Control Decoder that can be used to decode this control.
-   */
-  public static final ControlDecoder<ProxiedAuthV2Control> DECODER = new Decoder();
-
-  // The authorization ID from the control value.
-  private String authorizationID;
-
-
-
-  /**
-   * Creates a new instance of the proxied authorization v2 control with
-   * the provided information.
-   * 
-   * @param authorizationDN
-   *          The authorization DN.
-   */
-  public ProxiedAuthV2Control(DN authorizationDN)
-  {
-    super(OID_PROXIED_AUTH_V2, true);
-
-    Validator.ensureNotNull(authorizationID);
-    this.authorizationID = "dn:" + authorizationDN.toString();
-  }
-
-
-
-  /**
-   * Creates a new instance of the proxied authorization v2 control with
-   * the provided information.
-   * 
-   * @param authorizationID
-   *          The authorization ID.
-   */
-  public ProxiedAuthV2Control(String authorizationID)
-  {
-    super(OID_PROXIED_AUTH_V2, true);
-
-    Validator.ensureNotNull(authorizationID);
-    this.authorizationID = authorizationID;
-  }
-
-
-
-  /**
-   * Retrieves the authorization ID for this proxied authorization V2
-   * control.
-   * 
-   * @return The authorization ID for this proxied authorization V2
-   *         control.
-   */
-  public String getAuthorizationID()
-  {
-    return authorizationID;
-  }
-
-
-
-  @Override
-  public ByteString getValue()
-  {
-    return ByteString.valueOf(authorizationID);
-  }
-
-
-
-  @Override
-  public boolean hasValue()
-  {
-    return true;
-  }
-
-
-
-  public ProxiedAuthV2Control setAuthorizationID(DN authorizationDN)
-  {
-    Validator.ensureNotNull(authorizationDN);
-    this.authorizationID = "dn:" + authorizationDN.toString();
-    return this;
-  }
-
-
-
-  public ProxiedAuthV2Control setAuthorizationID(String authorizationID)
-  {
-    Validator.ensureNotNull(authorizationID);
-    this.authorizationID = authorizationID;
-    return this;
-  }
-
-
-
-  /**
-   * Appends a string representation of this proxied auth v2 control to
-   * the provided buffer.
-   * 
-   * @param buffer
-   *          The buffer to which the information should be appended.
-   */
-  @Override
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("ProxiedAuthorizationV2Control(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(", authorizationDN=\"");
-    buffer.append(authorizationID);
-    buffer.append("\")");
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/ProxiedAuthV2RequestControl.java b/sdk/src/org/opends/sdk/controls/ProxiedAuthV2RequestControl.java
new file mode 100644
index 0000000..fb90c3a
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/ProxiedAuthV2RequestControl.java
@@ -0,0 +1,283 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The proxy authorization v2 request control as defined in RFC 4370. This
+ * control allows a user to request that an operation be performed using the
+ * authorization of another user.
+ * <p>
+ * The target user is specified using an authorization ID, or {@code authzId},
+ * as defined in RFC 4513 section 5.2.1.8.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4370">RFC 4370 - Lightweight
+ *      Directory Access Protocol (LDAP) Proxied Authorization Control </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513 -
+ *      SASL Authorization Identities (authzId) </a>
+ */
+public final class ProxiedAuthV2RequestControl implements Control
+{
+  /**
+   * The OID for the proxied authorization v2 control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.18";
+
+  private static final ProxiedAuthV2RequestControl ANONYMOUS = new ProxiedAuthV2RequestControl(
+      "");
+
+  /**
+   * A decoder which can be used for decoding the proxied authorization v2
+   * request control.
+   */
+  public static final ControlDecoder<ProxiedAuthV2RequestControl> DECODER =
+    new ControlDecoder<ProxiedAuthV2RequestControl>()
+  {
+
+    public ProxiedAuthV2RequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof ProxiedAuthV2RequestControl)
+      {
+        return (ProxiedAuthV2RequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_PROXYAUTH2_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.isCritical())
+      {
+        final LocalizableMessage message = ERR_PROXYAUTH2_CONTROL_NOT_CRITICAL
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The response control must always have a value.
+        final LocalizableMessage message = ERR_PROXYAUTH2_NO_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      String authorizationID;
+      try
+      {
+        if (reader.elementAvailable())
+        {
+          // Try the legacy encoding where the value is wrapped by an
+          // extra octet string
+          authorizationID = reader.readOctetStringAsString();
+        }
+        else
+        {
+          authorizationID = control.getValue().toString();
+        }
+      }
+      catch (final IOException e)
+      {
+        StaticUtils.DEBUG_LOG.throwing("ProxiedAuthV2RequestControl",
+            "decodeControl", e);
+
+        final LocalizableMessage message = ERR_PROXYAUTH2_CANNOT_DECODE_VALUE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+
+      if (authorizationID.length() == 0)
+      {
+        // Anonymous.
+        return ANONYMOUS;
+      }
+
+      final int colonIndex = authorizationID.indexOf(':');
+      if (colonIndex < 0)
+      {
+        final LocalizableMessage message = ERR_PROXYAUTH2_INVALID_AUTHZID_TYPE
+            .get(authorizationID);
+        throw DecodeException.error(message);
+      }
+
+      return new ProxiedAuthV2RequestControl(authorizationID);
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new proxy authorization v2 request control with the provided
+   * authorization ID. The authorization ID usually has the form "dn:"
+   * immediately followed by the distinguished name of the user, or "u:"
+   * followed by a user ID string, but other forms are permitted.
+   *
+   * @param authorizationID
+   *          The authorization ID of the user whose authorization is to be used
+   *          when performing the operation.
+   * @return The new control.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authorizationID} was non-empty and did not contain a
+   *           valid authorization ID type.
+   * @throws NullPointerException
+   *           If {@code authorizationName} was {@code null}.
+   */
+  public static final ProxiedAuthV2RequestControl newControl(
+      final String authorizationID) throws LocalizedIllegalArgumentException,
+      NullPointerException
+  {
+    if (authorizationID.length() == 0)
+    {
+      // Anonymous.
+      return ANONYMOUS;
+    }
+
+    final int colonIndex = authorizationID.indexOf(':');
+    if (colonIndex < 0)
+    {
+      final LocalizableMessage message = ERR_PROXYAUTH2_INVALID_AUTHZID_TYPE
+          .get(authorizationID);
+      throw new LocalizedIllegalArgumentException(message);
+    }
+
+    return new ProxiedAuthV2RequestControl(authorizationID);
+  }
+
+
+
+  // The authorization ID from the control value.
+  private final String authorizationID;
+
+
+
+  private ProxiedAuthV2RequestControl(final String authorizationID)
+  {
+    this.authorizationID = authorizationID;
+  }
+
+
+
+  /**
+   * Returns the authorization ID of the user whose authorization is to be used
+   * when performing the operation. The authorization ID usually has the form
+   * "dn:" immediately followed by the distinguished name of the user, or "u:"
+   * followed by a user ID string, but other forms are permitted.
+   *
+   * @return The authorization ID of the user whose authorization is to be used
+   *         when performing the operation.
+   */
+  public String getAuthorizationID()
+  {
+    return authorizationID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return ByteString.valueOf(authorizationID);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("ProxiedAuthorizationV2Control(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", authorizationID=\"");
+    builder.append(authorizationID);
+    builder.append("\")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/ServerSideSortControl.java b/sdk/src/org/opends/sdk/controls/ServerSideSortControl.java
deleted file mode 100644
index ddb314e..0000000
--- a/sdk/src/org/opends/sdk/controls/ServerSideSortControl.java
+++ /dev/null
@@ -1,550 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.StringTokenizer;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ByteStringBuilder;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements the server-side sort control as defined in RFC
- * 2891.
- */
-public class ServerSideSortControl
-{
-  /**
-   * The OID for the server-side sort request control.
-   */
-  public static final String OID_SERVER_SIDE_SORT_REQUEST_CONTROL = "1.2.840.113556.1.4.473";
-
-  /**
-   * The OID for the server-side sort response control.
-   */
-  public static final String OID_SERVER_SIDE_SORT_RESPONSE_CONTROL = "1.2.840.113556.1.4.474";
-
-
-
-  /**
-   * This class implements the server-side sort request control as
-   * defined in RFC 2891 section 1.1. The ASN.1 description for the
-   * control value is: <BR>
-   * <BR>
-   * 
-   * <PRE>
-   * SortKeyList ::= SEQUENCE OF SEQUENCE {
-   *            attributeType   AttributeDescription,
-   *            orderingRule    [0] MatchingRuleId OPTIONAL,
-   *            reverseOrder    [1] BOOLEAN DEFAULT FALSE }
-   * </PRE>
-   */
-  public static class Request extends Control
-  {
-    private final List<SortKey> sortKeys = new ArrayList<SortKey>();
-
-
-
-    public Request(boolean isCritical, SortKey... sortKeys)
-    {
-      super(OID_SERVER_SIDE_SORT_REQUEST_CONTROL, isCritical);
-      addSortKey(sortKeys);
-    }
-
-
-
-    public Request(boolean isCritical, String sortOrderString)
-        throws DecodeException
-    {
-      super(OID_SERVER_SIDE_SORT_REQUEST_CONTROL, isCritical);
-
-      decodeSortOrderString(sortOrderString, sortKeys);
-    }
-
-
-
-    public Request(SortKey... sortKeys)
-    {
-      this(false, sortKeys);
-    }
-
-
-
-    public Request(String sortOrderString) throws DecodeException
-    {
-      this(false, sortOrderString);
-    }
-
-
-
-    public Request addSortKey(SortKey... sortKeys)
-    {
-      if (sortKeys != null)
-      {
-        for (SortKey sortKey : sortKeys)
-        {
-          Validator.ensureNotNull(sortKey);
-          this.sortKeys.add(sortKey);
-        }
-      }
-      return this;
-    }
-
-
-
-    public Request addSortKey(String sortOrderString)
-        throws DecodeException
-    {
-      decodeSortOrderString(sortOrderString, sortKeys);
-      return this;
-    }
-
-
-
-    public Iterable<SortKey> getSortKeys()
-    {
-      return sortKeys;
-    }
-
-
-
-    @Override
-    public ByteString getValue()
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-      try
-      {
-        writer.writeStartSequence();
-        for (SortKey sortKey : sortKeys)
-        {
-          writer.writeStartSequence();
-          writer.writeOctetString(sortKey.getAttributeDescription());
-
-          if (sortKey.getOrderingRule() != null)
-          {
-            writer.writeOctetString(TYPE_ORDERING_RULE_ID, sortKey
-                .getOrderingRule());
-          }
-
-          if (!sortKey.isReverseOrder())
-          {
-            writer.writeBoolean(TYPE_REVERSE_ORDER, true);
-          }
-
-          writer.writeEndSequence();
-        }
-        writer.writeEndSequence();
-        return buffer.toByteString();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-    }
-
-
-
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("ServerSideSortRequestControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", sortKeys=");
-      buffer.append(sortKeys);
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * This class implements the server-side sort response control as
-   * defined in RFC 2891 section 1.2. The ASN.1 description for the
-   * control value is: <BR>
-   * <BR>
-   * 
-   * <PRE>
-   * SortResult ::= SEQUENCE {
-   *    sortResult  ENUMERATED {
-   *        success                   (0), -- results are sorted
-   *        operationsError           (1), -- server internal failure
-   *        timeLimitExceeded         (3), -- timelimit reached before
-   *                                       -- sorting was completed
-   *        strongAuthRequired        (8), -- refused to return sorted
-   *                                       -- results via insecure
-   *                                       -- protocol
-   *        adminLimitExceeded       (11), -- too many matching entries
-   *                                       -- for the server to sort
-   *        noSuchAttribute          (16), -- unrecognized attribute
-   *                                       -- type in sort key
-   *        inappropriateMatching    (18), -- unrecognized or
-   *                                       -- inappropriate matching
-   *                                       -- rule in sort key
-   *        insufficientAccessRights (50), -- refused to return sorted
-   *                                       -- results to this client
-   *        busy                     (51), -- too busy to process
-   *        unwillingToPerform       (53), -- unable to sort
-   *        other                    (80)
-   *        },
-   *  attributeType [0] AttributeDescription OPTIONAL }
-   * </PRE>
-   */
-  public static class Response extends Control
-  {
-    private SortResult sortResult;
-
-    private String attributeDescription;
-
-
-
-    public Response(boolean isCritical, SortResult sortResult)
-    {
-      this(isCritical, sortResult, null);
-    }
-
-
-
-    public Response(boolean isCritical, SortResult sortResult,
-        String attributeDescription)
-    {
-      super(OID_SERVER_SIDE_SORT_RESPONSE_CONTROL, isCritical);
-      Validator.ensureNotNull(sortResult);
-      this.sortResult = sortResult;
-      this.attributeDescription = attributeDescription;
-    }
-
-
-
-    public Response(SortResult sortResult)
-    {
-      this(false, sortResult, null);
-    }
-
-
-
-    public Response(SortResult sortResult, String attributeDescription)
-    {
-      this(false, sortResult, attributeDescription);
-    }
-
-
-
-    public String getAttributeDescription()
-    {
-      return attributeDescription;
-    }
-
-
-
-    public SortResult getSortResult()
-    {
-      return sortResult;
-    }
-
-
-
-    @Override
-    public ByteString getValue()
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-      try
-      {
-        writer.writeStartSequence();
-        writer.writeEnumerated(sortResult.intValue());
-        if (attributeDescription != null)
-        {
-          writer.writeOctetString(TYPE_ATTRIBUTE_TYPE,
-              attributeDescription);
-        }
-        writer.writeEndSequence();
-        return buffer.toByteString();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-    }
-
-
-
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    public Response setAttributeDescription(String attributeDescription)
-    {
-      this.attributeDescription = attributeDescription;
-      return this;
-    }
-
-
-
-    public Response setSortResult(SortResult sortResult)
-    {
-      Validator.ensureNotNull(sortResult);
-      this.sortResult = sortResult;
-      return this;
-    }
-
-
-
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("ServerSideSortResponseControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", sortResult=");
-      buffer.append(sortResult);
-      buffer.append(", attributeDescription=");
-      buffer.append(attributeDescription);
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class RequestDecoder implements
-      ControlDecoder<Request>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Request decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = INFO_SORTREQ_CONTROL_NO_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      try
-      {
-        reader.readStartSequence();
-        if (!reader.hasNextElement())
-        {
-          LocalizableMessage message = INFO_SORTREQ_CONTROL_NO_SORT_KEYS.get();
-          throw DecodeException.error(message);
-        }
-
-        Request request = new Request();
-        while (reader.hasNextElement())
-        {
-          reader.readStartSequence();
-          String attrName = reader.readOctetStringAsString();
-
-          String orderingRule = null;
-          boolean reverseOrder = false;
-          if (reader.hasNextElement()
-              && (reader.peekType() == TYPE_ORDERING_RULE_ID))
-          {
-            orderingRule = reader.readOctetStringAsString();
-          }
-          if (reader.hasNextElement()
-              && (reader.peekType() == TYPE_REVERSE_ORDER))
-          {
-            reverseOrder = reader.readBoolean();
-          }
-          reader.readEndSequence();
-
-          request.addSortKey(new SortKey(attrName, orderingRule,
-              reverseOrder));
-        }
-        reader.readEndSequence();
-
-        return request;
-      }
-      catch (IOException e)
-      {
-        LocalizableMessage message = INFO_SORTREQ_CONTROL_CANNOT_DECODE_VALUE
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message, e);
-      }
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_SERVER_SIDE_SORT_REQUEST_CONTROL;
-    }
-
-  }
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class ResponseDecoder implements
-      ControlDecoder<Response>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Response decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = INFO_SORTRES_CONTROL_NO_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      try
-      {
-        reader.readStartSequence();
-        SortResult sortResult = SortResult.valueOf(reader
-            .readEnumerated());
-
-        String attributeType = null;
-        if (reader.hasNextElement())
-        {
-          attributeType = reader.readOctetStringAsString();
-        }
-
-        return new Response(isCritical, sortResult, attributeType);
-      }
-      catch (IOException e)
-      {
-        LocalizableMessage message = INFO_SORTRES_CONTROL_CANNOT_DECODE_VALUE
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message, e);
-      }
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_SERVER_SIDE_SORT_RESPONSE_CONTROL;
-    }
-
-  }
-
-
-
-  /**
-   * The BER type to use when encoding the orderingRule element.
-   */
-  private static final byte TYPE_ORDERING_RULE_ID = (byte) 0x80;
-
-  /**
-   * The BER type to use when encoding the reverseOrder element.
-   */
-  private static final byte TYPE_REVERSE_ORDER = (byte) 0x81;
-
-  /**
-   * The BER type to use when encoding the attribute type element.
-   */
-  private static final byte TYPE_ATTRIBUTE_TYPE = (byte) 0x80;
-
-  /**
-   * The Control Decoder that can be used to decode the request control.
-   */
-  public static final ControlDecoder<Request> REQUEST_DECODER = new RequestDecoder();
-
-  /**
-   * The Control Decoder that can be used to decode the response
-   * control.
-   */
-  public static final ControlDecoder<Response> RESPONSE_DECODER = new ResponseDecoder();
-
-
-
-  private static void decodeSortOrderString(String sortOrderString,
-      List<SortKey> sortKeys) throws DecodeException
-  {
-    StringTokenizer tokenizer = new StringTokenizer(sortOrderString,
-        ",");
-
-    while (tokenizer.hasMoreTokens())
-    {
-      String token = tokenizer.nextToken().trim();
-      boolean reverseOrder = false;
-      if (token.startsWith("-"))
-      {
-        reverseOrder = true;
-        token = token.substring(1);
-      }
-      else if (token.startsWith("+"))
-      {
-        token = token.substring(1);
-      }
-
-      int colonPos = token.indexOf(':');
-      if (colonPos < 0)
-      {
-        if (token.length() == 0)
-        {
-          LocalizableMessage message = INFO_SORTREQ_CONTROL_NO_ATTR_NAME
-              .get(sortOrderString);
-          throw DecodeException.error(message);
-        }
-
-        sortKeys.add(new SortKey(token, null, reverseOrder));
-      }
-      else if (colonPos == 0)
-      {
-        LocalizableMessage message = INFO_SORTREQ_CONTROL_NO_ATTR_NAME
-            .get(sortOrderString);
-        throw DecodeException.error(message);
-      }
-      else if (colonPos == (token.length() - 1))
-      {
-        LocalizableMessage message = INFO_SORTREQ_CONTROL_NO_MATCHING_RULE
-            .get(sortOrderString);
-        throw DecodeException.error(message);
-      }
-      else
-      {
-        String attrName = token.substring(0, colonPos);
-        String ruleID = token.substring(colonPos + 1);
-
-        sortKeys.add(new SortKey(attrName, ruleID, reverseOrder));
-      }
-    }
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/ServerSideSortRequestControl.java b/sdk/src/org/opends/sdk/controls/ServerSideSortRequestControl.java
new file mode 100644
index 0000000..d6e3de4
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/ServerSideSortRequestControl.java
@@ -0,0 +1,393 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+import java.util.*;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The server-side sort request control as defined in RFC 2891. This control may
+ * be included in a search request to indicate that search result entries should
+ * be sorted by the server before being returned. The sort order is specified
+ * using one or more sort keys, the first being the primary key, and so on.
+ * <p>
+ * This controls may be useful when the client has limited functionality or for
+ * some other reason cannot sort the results but still needs them sorted. In
+ * cases where the client can sort the results client-side sorting is
+ * recommended in order to reduce load on the server. See {@link SortKey} for
+ * more an example of client-side sorting.
+ *
+ * @see ServerSideSortResponseControl
+ * @see SortKey
+ * @see <a href="http://tools.ietf.org/html/rfc2891">RFC 2891 - LDAP Control
+ *      Extension for Server Side Sorting of Search Results </a>
+ */
+public final class ServerSideSortRequestControl implements Control
+{
+  /**
+   * The OID for the server-side sort request control.
+   */
+  public static final String OID = "1.2.840.113556.1.4.473";
+
+  /**
+   * The BER type to use when encoding the orderingRule element.
+   */
+  private static final byte TYPE_ORDERING_RULE_ID = (byte) 0x80;
+
+  /**
+   * The BER type to use when encoding the reverseOrder element.
+   */
+  private static final byte TYPE_REVERSE_ORDER = (byte) 0x81;
+
+  /**
+   * A decoder which can be used for decoding the server side sort request
+   * control.
+   */
+  public static final ControlDecoder<ServerSideSortRequestControl> DECODER =
+    new ControlDecoder<ServerSideSortRequestControl>()
+  {
+
+    public ServerSideSortRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof ServerSideSortRequestControl)
+      {
+        return (ServerSideSortRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_SORTREQ_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The request control must always have a value.
+        final LocalizableMessage message = INFO_SORTREQ_CONTROL_NO_VALUE.get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      try
+      {
+        reader.readStartSequence();
+        if (!reader.hasNextElement())
+        {
+          final LocalizableMessage message = INFO_SORTREQ_CONTROL_NO_SORT_KEYS
+              .get();
+          throw DecodeException.error(message);
+        }
+
+        final List<SortKey> keys = new LinkedList<SortKey>();
+        while (reader.hasNextElement())
+        {
+          reader.readStartSequence();
+          final String attrName = reader.readOctetStringAsString();
+
+          String orderingRule = null;
+          boolean reverseOrder = false;
+          if (reader.hasNextElement()
+              && (reader.peekType() == TYPE_ORDERING_RULE_ID))
+          {
+            orderingRule = reader.readOctetStringAsString();
+          }
+          if (reader.hasNextElement()
+              && (reader.peekType() == TYPE_REVERSE_ORDER))
+          {
+            reverseOrder = reader.readBoolean();
+          }
+          reader.readEndSequence();
+
+          keys.add(new SortKey(attrName, reverseOrder, orderingRule));
+        }
+        reader.readEndSequence();
+
+        return new ServerSideSortRequestControl(control.isCritical(),
+            Collections.unmodifiableList(keys));
+      }
+      catch (final IOException e)
+      {
+        final LocalizableMessage message = INFO_SORTREQ_CONTROL_CANNOT_DECODE_VALUE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new server side sort request control with the provided
+   * criticality and list of sort keys.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param keys
+   *          The list of sort keys.
+   * @return The new control.
+   * @throws IllegalArgumentException
+   *           If {@code keys} was empty.
+   * @throws NullPointerException
+   *           If {@code keys} was {@code null}.
+   */
+  public static ServerSideSortRequestControl newControl(
+      final boolean isCritical, final Collection<SortKey> keys)
+      throws IllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(keys);
+    Validator.ensureTrue(!keys.isEmpty(), "keys must not be empty");
+
+    return new ServerSideSortRequestControl(isCritical, Collections
+        .unmodifiableList(new ArrayList<SortKey>(keys)));
+  }
+
+
+
+  /**
+   * Creates a new server side sort request control with the provided
+   * criticality and list of sort keys.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param firstKey
+   *          The first sort key.
+   * @param remainingKeys
+   *          The remaining sort keys.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code firstKey} was {@code null}.
+   */
+  public static ServerSideSortRequestControl newControl(
+      final boolean isCritical, final SortKey firstKey,
+      final SortKey... remainingKeys) throws NullPointerException
+  {
+    Validator.ensureNotNull(firstKey, remainingKeys);
+
+    final List<SortKey> keys = new ArrayList<SortKey>(1 + remainingKeys.length);
+    keys.add(firstKey);
+    for (final SortKey key : remainingKeys)
+    {
+      keys.add(key);
+    }
+    return new ServerSideSortRequestControl(isCritical, Collections
+        .unmodifiableList(keys));
+  }
+
+
+
+  /**
+   * Creates a new server side sort request control with the provided
+   * criticality and string representation of a list of sort keys. The string
+   * representation is comprised of a comma separate list of sort keys as
+   * defined in {@link SortKey#valueOf(String)}. There must be at least one sort
+   * key present in the string representation.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param sortKeys
+   *          The list of sort keys.
+   * @return The new control.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code sortKeys} is not a valid string representation of a
+   *           list of sort keys.
+   * @throws NullPointerException
+   *           If {@code sortKeys} was {@code null}.
+   */
+  public static ServerSideSortRequestControl newControl(
+      final boolean isCritical, final String sortKeys)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(sortKeys);
+
+    final List<SortKey> keys = new LinkedList<SortKey>();
+    final StringTokenizer tokenizer = new StringTokenizer(sortKeys, ",");
+    while (tokenizer.hasMoreTokens())
+    {
+      final String token = tokenizer.nextToken().trim();
+      keys.add(SortKey.valueOf(token));
+    }
+    if (keys.isEmpty())
+    {
+      final LocalizableMessage message = ERR_SORT_KEY_NO_SORT_KEYS
+          .get(sortKeys);
+      throw new LocalizedIllegalArgumentException(message);
+    }
+    return new ServerSideSortRequestControl(isCritical, Collections
+        .unmodifiableList(keys));
+  }
+
+
+
+  private final List<SortKey> sortKeys;
+
+  private final boolean isCritical;
+
+
+
+  private ServerSideSortRequestControl(final boolean isCritical,
+      final List<SortKey> keys)
+  {
+    this.isCritical = isCritical;
+    this.sortKeys = keys;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * Returns an unmodifiable list containing the sort keys associated with this
+   * server side sort request control. The list will contain at least one sort
+   * key.
+   *
+   * @return An unmodifiable list containing the sort keys associated with this
+   *         server side sort request control.
+   */
+  public List<SortKey> getSortKeys()
+  {
+    return sortKeys;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      for (final SortKey sortKey : sortKeys)
+      {
+        writer.writeStartSequence();
+        writer.writeOctetString(sortKey.getAttributeDescription());
+
+        if (sortKey.getOrderingMatchingRule() != null)
+        {
+          writer.writeOctetString(TYPE_ORDERING_RULE_ID, sortKey
+              .getOrderingMatchingRule());
+        }
+
+        if (!sortKey.isReverseOrder())
+        {
+          writer.writeBoolean(TYPE_REVERSE_ORDER, true);
+        }
+
+        writer.writeEndSequence();
+      }
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder buffer = new StringBuilder();
+    buffer.append("ServerSideSortRequestControl(oid=");
+    buffer.append(getOID());
+    buffer.append(", criticality=");
+    buffer.append(isCritical());
+    buffer.append(", sortKeys=");
+    buffer.append(sortKeys);
+    buffer.append(")");
+    return buffer.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/ServerSideSortResponseControl.java b/sdk/src/org/opends/sdk/controls/ServerSideSortResponseControl.java
new file mode 100644
index 0000000..5ef551b
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/ServerSideSortResponseControl.java
@@ -0,0 +1,376 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_SORTRES_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.INFO_SORTRES_CONTROL_CANNOT_DECODE_VALUE;
+import static com.sun.opends.sdk.messages.Messages.INFO_SORTRES_CONTROL_NO_VALUE;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.schema.Schema;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The server-side sort response control as defined in RFC 2891. This control is
+ * included with a search result in response to a server-side sort request
+ * included with a search request. The client application is assured that the
+ * search results are sorted in the specified key order if and only if the
+ * result code in this control is success. If the server omits this control from
+ * the search result, the client SHOULD assume that the sort control was ignored
+ * by the server.
+ *
+ * @see ServerSideSortRequestControl
+ * @see <a href="http://tools.ietf.org/html/rfc2891">RFC 2891 - LDAP Control
+ *      Extension for Server Side Sorting of Search Results </a>
+ */
+public final class ServerSideSortResponseControl implements Control
+{
+  /**
+   * The OID for the server-side sort response control.
+   */
+  public static final String OID = "1.2.840.113556.1.4.474";
+
+  /**
+   * A decoder which can be used for decoding the server side sort response
+   * control.
+   */
+  public static final ControlDecoder<ServerSideSortResponseControl> DECODER =
+    new ControlDecoder<ServerSideSortResponseControl>()
+  {
+
+    public ServerSideSortResponseControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control, options);
+
+      if (control instanceof ServerSideSortResponseControl)
+      {
+        return (ServerSideSortResponseControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_SORTRES_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The request control must always have a value.
+        final LocalizableMessage message = INFO_SORTRES_CONTROL_NO_VALUE.get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      try
+      {
+        reader.readStartSequence();
+
+        // FIXME: should really check that result code is one of the expected
+        // values listed in the RFC.
+        final ResultCode result = ResultCode.valueOf(reader.readEnumerated());
+
+        AttributeDescription attributeDescription = null;
+        if (reader.hasNextElement())
+        {
+          // FIXME: which schema should we use?
+          final Schema schema = options.getSchemaResolver().resolveSchema("");
+          final String ads = reader.readOctetStringAsString();
+          attributeDescription = AttributeDescription.valueOf(ads, schema);
+        }
+
+        return new ServerSideSortResponseControl(control.isCritical(), result,
+            attributeDescription);
+      }
+      catch (final IOException e)
+      {
+        final LocalizableMessage message = INFO_SORTRES_CONTROL_CANNOT_DECODE_VALUE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+      catch (final LocalizedIllegalArgumentException e)
+      {
+        final LocalizableMessage message = INFO_SORTRES_CONTROL_CANNOT_DECODE_VALUE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+  /**
+   * The BER type to use when encoding the attribute type element.
+   */
+  private static final byte TYPE_ATTRIBUTE_TYPE = (byte) 0x80;
+
+
+
+  /**
+   * Creates a new server-side response control with the provided sort result
+   * and no attribute description.
+   *
+   * @param result
+   *          The result code indicating the outcome of the server-side sort
+   *          request. {@link ResultCode#SUCCESS} if the search results were
+   *          sorted in accordance with the keys specified in the server-side
+   *          sort request control, or an error code indicating why the results
+   *          could not be sorted (such as {@link ResultCode#NO_SUCH_ATTRIBUTE}
+   *          or {@link ResultCode#INAPPROPRIATE_MATCHING}).
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code result} was {@code null}.
+   */
+  public static ServerSideSortResponseControl newControl(final ResultCode result)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(result);
+
+    return new ServerSideSortResponseControl(false, result, null);
+  }
+
+
+
+  /**
+   * Creates a new server-side response control with the provided sort result
+   * and attribute description.
+   *
+   * @param result
+   *          The result code indicating the outcome of the server-side sort
+   *          request. {@link ResultCode#SUCCESS} if the search results were
+   *          sorted in accordance with the keys specified in the server-side
+   *          sort request control, or an error code indicating why the results
+   *          could not be sorted (such as {@link ResultCode#NO_SUCH_ATTRIBUTE}
+   *          or {@link ResultCode#INAPPROPRIATE_MATCHING}).
+   * @param attributeDescription
+   *          The first attribute description specified in the list of sort keys
+   *          that was in error, may be {@code null}.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code result} was {@code null}.
+   */
+  public static ServerSideSortResponseControl newControl(
+      final ResultCode result, final AttributeDescription attributeDescription)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(result);
+
+    return new ServerSideSortResponseControl(false, result,
+        attributeDescription);
+  }
+
+
+
+  /**
+   * Creates a new server-side response control with the provided sort result
+   * and attribute description. The attribute description will be decoded using
+   * the default schema.
+   *
+   * @param result
+   *          The result code indicating the outcome of the server-side sort
+   *          request. {@link ResultCode#SUCCESS} if the search results were
+   *          sorted in accordance with the keys specified in the server-side
+   *          sort request control, or an error code indicating why the results
+   *          could not be sorted (such as {@link ResultCode#NO_SUCH_ATTRIBUTE}
+   *          or {@link ResultCode#INAPPROPRIATE_MATCHING}).
+   * @param attributeDescription
+   *          The first attribute description specified in the list of sort keys
+   *          that was in error, may be {@code null}.
+   * @return The new control.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code attributeDescription} could not be parsed using the
+   *           default schema.
+   * @throws NullPointerException
+   *           If {@code result} was {@code null}.
+   */
+  public static ServerSideSortResponseControl newControl(
+      final ResultCode result, final String attributeDescription)
+      throws LocalizedIllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(result);
+
+    if (attributeDescription != null)
+    {
+      return new ServerSideSortResponseControl(false, result,
+          AttributeDescription.valueOf(attributeDescription));
+    }
+    else
+    {
+      return new ServerSideSortResponseControl(false, result, null);
+    }
+  }
+
+
+
+  private final ResultCode result;
+
+  private final AttributeDescription attributeDescription;
+
+  private final boolean isCritical;
+
+
+
+  private ServerSideSortResponseControl(final boolean isCritical,
+      final ResultCode result, final AttributeDescription attributeDescription)
+  {
+    this.isCritical = isCritical;
+    this.result = result;
+    this.attributeDescription = attributeDescription;
+  }
+
+
+
+  /**
+   * Returns the first attribute description specified in the list of sort keys
+   * that was in error, or {@code null} if the attribute description was not
+   * included with this control.
+   *
+   * @return The first attribute description specified in the list of sort keys
+   *         that was in error.
+   */
+  public AttributeDescription getAttributeDescription()
+  {
+    return attributeDescription;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * Returns a result code indicating the outcome of the server-side sort
+   * request. This will be {@link ResultCode#SUCCESS} if the search results were
+   * sorted in accordance with the keys specified in the server-side sort
+   * request control, or an error code indicating why the results could not be
+   * sorted (such as {@link ResultCode#NO_SUCH_ATTRIBUTE} or
+   * {@link ResultCode#INAPPROPRIATE_MATCHING}).
+   *
+   * @return The result code indicating the outcome of the server-side sort
+   *         request.
+   */
+  public ResultCode getResult()
+  {
+    return result;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      writer.writeEnumerated(result.intValue());
+      if (attributeDescription != null)
+      {
+        writer.writeOctetString(TYPE_ATTRIBUTE_TYPE, attributeDescription
+            .toString());
+      }
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("ServerSideSortResponseControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", result=");
+    builder.append(result);
+    if (attributeDescription != null)
+    {
+      builder.append(", attributeDescription=");
+      builder.append(attributeDescription);
+    }
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/SimplePagedResultsControl.java b/sdk/src/org/opends/sdk/controls/SimplePagedResultsControl.java
new file mode 100644
index 0000000..bea06b7
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/SimplePagedResultsControl.java
@@ -0,0 +1,344 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.*;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The simple paged results request and response control as defined in RFC 2696.
+ * This control allows a client to control the rate at which an LDAP server
+ * returns the results of an LDAP search operation. This control may be useful
+ * when the LDAP client has limited resources and may not be able to process the
+ * entire result set from a given LDAP query, or when the LDAP client is
+ * connected over a low-bandwidth connection.
+ * <p>
+ * This control is included in the searchRequest and searchResultDone messages
+ * and has the following structure:
+ *
+ * <pre>
+ * realSearchControlValue ::= SEQUENCE {
+ *         size            INTEGER (0..maxInt),
+ *                                 -- requested page size from client
+ *                                 -- result set size estimate from server
+ *         cookie          OCTET STRING
+ * }
+ * </pre>
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc2696">RFC 2696 - LDAP Control
+ *      Extension for Simple Paged Results Manipulation </a>
+ */
+public final class SimplePagedResultsControl implements Control
+{
+  /**
+   * The OID for the paged results request/response control defined in RFC 2696.
+   */
+  public static final String OID = "1.2.840.113556.1.4.319";
+
+  /**
+   * A decoder which can be used for decoding the simple paged results control.
+   */
+  public static final ControlDecoder<SimplePagedResultsControl> DECODER =
+    new ControlDecoder<SimplePagedResultsControl>()
+  {
+
+    public SimplePagedResultsControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof SimplePagedResultsControl)
+      {
+        return (SimplePagedResultsControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_CONTROL_BAD_OID
+            .get(control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The control must always have a value.
+        final LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_NULL
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      try
+      {
+        reader.readStartSequence();
+      }
+      catch (final Exception e)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PagedResultsControl.Decoder", "decode",
+            e);
+
+        final LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SEQUENCE
+            .get(String.valueOf(e));
+        throw DecodeException.error(message, e);
+      }
+
+      int size;
+      try
+      {
+        size = (int) reader.readInteger();
+      }
+      catch (final Exception e)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PagedResultsControl.Decoder", "decode",
+            e);
+
+        final LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SIZE
+            .get(String.valueOf(e));
+        throw DecodeException.error(message, e);
+      }
+
+      ByteString cookie;
+      try
+      {
+        cookie = reader.readOctetString();
+      }
+      catch (final Exception e)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PagedResultsControl.Decoder", "decode",
+            e);
+
+        final LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_COOKIE
+            .get(String.valueOf(e));
+        throw DecodeException.error(message, e);
+      }
+
+      try
+      {
+        reader.readEndSequence();
+      }
+      catch (final Exception e)
+      {
+        StaticUtils.DEBUG_LOG.throwing("PagedResultsControl.Decoder", "decode",
+            e);
+
+        final LocalizableMessage message = ERR_LDAP_PAGED_RESULTS_DECODE_SEQUENCE
+            .get(String.valueOf(e));
+        throw DecodeException.error(message, e);
+      }
+
+      return new SimplePagedResultsControl(control.isCritical(), size, cookie);
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new simple paged results control with the provided criticality,
+   * size, and cookie.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param size
+   *          The requested page size when used in a request control from the
+   *          client, or an estimate of the result set size when used in a
+   *          response control from the server (may be 0, indicating that the
+   *          server does not know).
+   * @param cookie
+   *          An opaque cookie which is used by the server to track its position
+   *          in the set of search results. The cookie must be empty in the
+   *          initial search request sent by the client. For subsequent search
+   *          requests the client must include the cookie returned with the
+   *          previous search result, until the server returns an empty cookie
+   *          indicating that the final page of results has been returned.
+   * @return The new control.
+   * @throws NullPointerException
+   *           If {@code cookie} was {@code null}.
+   */
+  public static SimplePagedResultsControl newControl(final boolean isCritical,
+      final int size, final ByteString cookie) throws NullPointerException
+  {
+    Validator.ensureNotNull(cookie);
+    return new SimplePagedResultsControl(isCritical, size, cookie);
+  }
+
+
+
+  /**
+   * The control value size element, which is either the requested page size
+   * from the client, or the result set size estimate from the server.
+   */
+  private final int size;
+
+  /**
+   * The control value cookie element.
+   */
+  private final ByteString cookie;
+
+  private final boolean isCritical;
+
+
+
+  private SimplePagedResultsControl(final boolean isCritical, final int size,
+      final ByteString cookie)
+  {
+    this.isCritical = isCritical;
+    this.size = size;
+    this.cookie = cookie;
+  }
+
+
+
+  /**
+   * Returns the opaque cookie which is used by the server to track its position
+   * in the set of search results. The cookie must be empty in the initial
+   * search request sent by the client. For subsequent search requests the
+   * client must include the cookie returned with the previous search result,
+   * until the server returns an empty cookie indicating that the final page of
+   * results has been returned.
+   *
+   * @return The opaque cookie which is used by the server to track its position
+   *         in the set of search results.
+   */
+  public ByteString getCookie()
+  {
+    return cookie;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * Returns the requested page size when used in a request control from the
+   * client, or an estimate of the result set size when used in a response
+   * control from the server (may be 0, indicating that the server does not
+   * know).
+   *
+   * @return The requested page size when used in a request control from the
+   *         client, or an estimate of the result set size when used in a
+   *         response control from the server.
+   */
+  public int getSize()
+  {
+    return size;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      writer.writeInteger(size);
+      writer.writeOctetString(cookie);
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("SimplePagedResultsControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", size=");
+    builder.append(size);
+    builder.append(", cookie=");
+    builder.append(cookie);
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/SortKey.java b/sdk/src/org/opends/sdk/controls/SortKey.java
deleted file mode 100644
index 36f2f16..0000000
--- a/sdk/src/org/opends/sdk/controls/SortKey.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import org.opends.sdk.AttributeDescription;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class defines a data structure that may be used as a sort key.
- * It includes an attribute description and a boolean value that
- * indicates whether the sort should be ascending or descending. It may
- * also contain a specific ordering matching rule that should be used
- * for the sorting process, although if none is provided it will use the
- * default ordering matching rule for the attribute type.
- */
-public class SortKey
-{
-  private String attributeDescription;
-
-  private String orderingRule;
-
-  boolean reverseOrder;
-
-
-
-  public SortKey(AttributeDescription attributeDescription)
-  {
-    this(attributeDescription.toString(), null, false);
-  }
-
-
-
-  public SortKey(AttributeDescription attributeDescription,
-      String orderingRule)
-  {
-    this(attributeDescription.toString(), orderingRule, false);
-  }
-
-
-
-  public SortKey(AttributeDescription attributeDescription,
-      String orderingRule, boolean reverseOrder)
-  {
-    this(attributeDescription.toString(), orderingRule, reverseOrder);
-  }
-
-
-
-  public SortKey(String attributeDescription)
-  {
-    this(attributeDescription, null, false);
-  }
-
-
-
-  public SortKey(String attributeDescription, String orderingRule)
-  {
-    this(attributeDescription, orderingRule, false);
-  }
-
-
-
-  public SortKey(String attributeDescription, String orderingRule,
-      boolean reverseOrder)
-  {
-    Validator.ensureNotNull(attributeDescription);
-    this.attributeDescription = attributeDescription;
-    this.orderingRule = orderingRule;
-    this.reverseOrder = reverseOrder;
-  }
-
-
-
-  public String getAttributeDescription()
-  {
-    return attributeDescription;
-  }
-
-
-
-  public String getOrderingRule()
-  {
-    return orderingRule;
-  }
-
-
-
-  public boolean isReverseOrder()
-  {
-    return reverseOrder;
-  }
-
-
-
-  public SortKey setAttributeDescription(String attributeDescription)
-  {
-    Validator.ensureNotNull(attributeDescription);
-    this.attributeDescription = attributeDescription;
-    return this;
-  }
-
-
-
-  public SortKey setOrderingRule(String orderingRule)
-  {
-    this.orderingRule = orderingRule;
-    return this;
-  }
-
-
-
-  public void setReverseOrder(boolean reverseOrder)
-  {
-    this.reverseOrder = reverseOrder;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public String toString()
-  {
-    StringBuilder buffer = new StringBuilder();
-    toString(buffer);
-    return buffer.toString();
-  }
-
-
-
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("SortKey(attributeDescription=");
-    buffer.append(attributeDescription);
-    buffer.append(", orderingRule=");
-    buffer.append(orderingRule);
-    buffer.append(", reverseOrder=");
-    buffer.append(reverseOrder);
-    buffer.append(")");
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/SortResult.java b/sdk/src/org/opends/sdk/controls/SortResult.java
deleted file mode 100644
index ec35dca..0000000
--- a/sdk/src/org/opends/sdk/controls/SortResult.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.opends.sdk.ResultCode;
-
-
-
-/**
- * Created by IntelliJ IDEA. User: boli Date: Jun 30, 2009 Time: 4:33:56
- * PM To change this template use File | Settings | File Templates.
- */
-public class SortResult
-{
-  private static final SortResult[] ELEMENTS = new SortResult[81];
-
-  public static final SortResult SUCCESS = register(ResultCode.SUCCESS);
-
-  public static final SortResult OPERATIONS_ERROR = register(ResultCode.OPERATIONS_ERROR);
-
-  public static final SortResult TIME_LIMIT_EXCEEDED = register(ResultCode.TIME_LIMIT_EXCEEDED);
-
-  public static final SortResult STRONG_AUTH_REQUIRED = register(ResultCode.STRONG_AUTH_REQUIRED);
-
-  public static final SortResult ADMIN_LIMIT_EXCEEDED = register(ResultCode.ADMIN_LIMIT_EXCEEDED);
-
-  public static final SortResult NO_SUCH_ATTRIBUTE = register(ResultCode.NO_SUCH_ATTRIBUTE);
-
-  public static final SortResult INAPPROPRIATE_MATCHING = register(ResultCode.INAPPROPRIATE_MATCHING);
-
-  public static final SortResult INSUFFICIENT_ACCESS_RIGHTS = register(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
-  public static final SortResult BUSY = register(ResultCode.BUSY);
-
-  public static final SortResult UNWILLING_TO_PERFORM = register(ResultCode.UNWILLING_TO_PERFORM);
-
-  public static final SortResult OTHER = register(ResultCode.OTHER);
-
-
-
-  public static SortResult register(ResultCode resultCode)
-  {
-    SortResult t = new SortResult(resultCode);
-    ELEMENTS[resultCode.intValue()] = t;
-    return t;
-  }
-
-
-
-  public static SortResult valueOf(int intValue)
-  {
-    SortResult e = ELEMENTS[intValue];
-    if (e == null)
-    {
-      e = new SortResult(ResultCode.valueOf(intValue));
-    }
-    return e;
-  }
-
-
-
-  public static List<SortResult> values()
-  {
-    return Arrays.asList(ELEMENTS);
-  }
-
-
-
-  private final ResultCode resultCode;
-
-
-
-  private SortResult(ResultCode resultCode)
-  {
-    this.resultCode = resultCode;
-  }
-
-
-
-  @Override
-  public boolean equals(Object o)
-  {
-    return (this == o)
-        || ((o instanceof SortResult) && resultCode.equals(o));
-
-  }
-
-
-
-  @Override
-  public int hashCode()
-  {
-    return resultCode.hashCode();
-  }
-
-
-
-  public int intValue()
-  {
-    return resultCode.intValue();
-  }
-
-
-
-  @Override
-  public String toString()
-  {
-    return resultCode.toString();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/SubentriesRequestControl.java b/sdk/src/org/opends/sdk/controls/SubentriesRequestControl.java
new file mode 100644
index 0000000..a9eae9e
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/SubentriesRequestControl.java
@@ -0,0 +1,195 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_SUBENTRIES_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_SUBENTRIES_INVALID_CONTROL_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The sub-entries request control as defined in draft-ietf-ldup-subentry. This
+ * control may be included in a search request to indicate that sub-entries
+ * should be included in the search results.
+ * <p>
+ * In the absence of the sub-entries request control, sub-entries are not
+ * visible to search operations unless the target/base of the operation is a
+ * sub-entry. In the presence of the sub-entry request control, only sub-entries
+ * are visible.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-ietf-ldup-subentry">draft-ietf-ldup-subentry
+ *      - LDAP Subentry Schema </a>
+ */
+public final class SubentriesRequestControl implements Control
+{
+  /**
+   * The OID for the sub-entries request control.
+   */
+  public static final String OID = "1.3.6.1.4.1.7628.5.101.1";
+
+  private static final SubentriesRequestControl CRITICAL_INSTANCE = new SubentriesRequestControl(
+      true);
+  private static final SubentriesRequestControl NONCRITICAL_INSTANCE = new SubentriesRequestControl(
+      false);
+
+  /**
+   * A decoder which can be used for decoding the sub-entries request control.
+   */
+  public static final ControlDecoder<SubentriesRequestControl> DECODER =
+    new ControlDecoder<SubentriesRequestControl>()
+  {
+
+    public SubentriesRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof SubentriesRequestControl)
+      {
+        return (SubentriesRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_SUBENTRIES_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (control.hasValue())
+      {
+        final LocalizableMessage message = ERR_SUBENTRIES_INVALID_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new sub-entries request control having the provided criticality.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @return The new control.
+   */
+  public static SubentriesRequestControl newControl(final boolean isCritical)
+  {
+    return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+  }
+
+
+
+  private final boolean isCritical;
+
+
+
+  private SubentriesRequestControl(final boolean isCritical)
+  {
+    this.isCritical = isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("SubentriesRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/SubtreeDeleteControl.java b/sdk/src/org/opends/sdk/controls/SubtreeDeleteControl.java
deleted file mode 100644
index 5dc906f..0000000
--- a/sdk/src/org/opends/sdk/controls/SubtreeDeleteControl.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.schema.Schema;
-
-
-
-
-/**
- * This class implements the subtree delete control defined in
- * draft-armijo-ldap-treedelete. It makes it possible for clients to
- * delete subtrees of entries.
- */
-public class SubtreeDeleteControl extends Control
-{
-  /**
-   * The OID for the subtree delete control.
-   */
-  public static final String OID_SUBTREE_DELETE_CONTROL = "1.2.840.113556.1.4.805";
-
-
-
-  /**
-   * ControlDecoder implementation to decode this control from a
-   * ByteString.
-   */
-  private final static class Decoder implements
-      ControlDecoder<SubtreeDeleteControl>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public SubtreeDeleteControl decode(boolean isCritical,
-        ByteString value, Schema schema) throws DecodeException
-    {
-      if (value != null)
-      {
-        LocalizableMessage message = ERR_SUBTREE_DELETE_INVALID_CONTROL_VALUE
-            .get();
-        throw DecodeException.error(message);
-      }
-
-      return new SubtreeDeleteControl(isCritical);
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_SUBTREE_DELETE_CONTROL;
-    }
-
-  }
-
-
-
-  /**
-   * The Control Decoder that can be used to decode this control.
-   */
-  public static final ControlDecoder<SubtreeDeleteControl> DECODER = new Decoder();
-
-
-
-  /**
-   * Creates a new subtree delete control.
-   * 
-   * @param isCritical
-   *          Indicates whether the control should be considered
-   *          critical for the operation processing.
-   */
-  public SubtreeDeleteControl(boolean isCritical)
-  {
-    super(OID_SUBTREE_DELETE_CONTROL, isCritical);
-  }
-
-
-
-  @Override
-  public ByteString getValue()
-  {
-    return null;
-  }
-
-
-
-  @Override
-  public boolean hasValue()
-  {
-    return false;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public void toString(StringBuilder buffer)
-  {
-    buffer.append("SubtreeDeleteControl(oid=");
-    buffer.append(getOID());
-    buffer.append(", criticality=");
-    buffer.append(isCritical());
-    buffer.append(")");
-  }
-
-}
diff --git a/sdk/src/org/opends/sdk/controls/SubtreeDeleteRequestControl.java b/sdk/src/org/opends/sdk/controls/SubtreeDeleteRequestControl.java
new file mode 100644
index 0000000..f37646c
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/SubtreeDeleteRequestControl.java
@@ -0,0 +1,192 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_SUBTREE_DELETE_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.ERR_SUBTREE_DELETE_INVALID_CONTROL_VALUE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.LocalizableMessage;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The tree delete request control as defined in draft-armijo-ldap-treedelete.
+ * This control allows a client to delete an entire subtree of a container entry
+ * in a single delete operation.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-armijo-ldap-treedelete">draft-armijo-ldap-treedelete
+ *      - Tree Delete Control </a>
+ */
+public final class SubtreeDeleteRequestControl implements Control
+{
+  /**
+   * The OID for the subtree delete request control.
+   */
+  public static final String OID = "1.2.840.113556.1.4.805";
+
+  private static final SubtreeDeleteRequestControl CRITICAL_INSTANCE =
+    new SubtreeDeleteRequestControl(true);
+
+  private static final SubtreeDeleteRequestControl NONCRITICAL_INSTANCE =
+    new SubtreeDeleteRequestControl(false);
+
+  /**
+   * A decoder which can be used for decoding the sub-tree delete request
+   * control.
+   */
+  public static final ControlDecoder<SubtreeDeleteRequestControl> DECODER =
+    new ControlDecoder<SubtreeDeleteRequestControl>()
+  {
+
+    public SubtreeDeleteRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof SubtreeDeleteRequestControl)
+      {
+        return (SubtreeDeleteRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_SUBTREE_DELETE_CONTROL_BAD_OID
+            .get(control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (control.hasValue())
+      {
+        final LocalizableMessage message = ERR_SUBTREE_DELETE_INVALID_CONTROL_VALUE
+            .get();
+        throw DecodeException.error(message);
+      }
+
+      return control.isCritical() ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new tree delete request control having the provided criticality.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @return The new control.
+   */
+  public static SubtreeDeleteRequestControl newControl(final boolean isCritical)
+  {
+    return isCritical ? CRITICAL_INSTANCE : NONCRITICAL_INSTANCE;
+  }
+
+
+
+  private final boolean isCritical;
+
+
+
+  private SubtreeDeleteRequestControl(final boolean isCritical)
+  {
+    this.isCritical = isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("SubtreeDeleteRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/VLVControl.java b/sdk/src/org/opends/sdk/controls/VLVControl.java
deleted file mode 100644
index 708cbae..0000000
--- a/sdk/src/org/opends/sdk/controls/VLVControl.java
+++ /dev/null
@@ -1,652 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ByteStringBuilder;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements the virtual list view controls as defined in
- * draft-ietf-ldapext-ldapv3-vlv.
- */
-public class VLVControl
-{
-  /**
-   * The OID for the virtual list view request control.
-   */
-  public static final String OID_VLV_REQUEST_CONTROL = "2.16.840.1.113730.3.4.9";
-
-  /**
-   * The OID for the virtual list view request control.
-   */
-  public static final String OID_VLV_RESPONSE_CONTROL = "2.16.840.1.113730.3.4.10";
-
-
-
-  public static class Request extends Control
-  {
-    private int beforeCount;
-
-    private int afterCount;
-
-    private VLVTarget target;
-
-    private ByteString contextID;
-
-
-
-    /**
-     * Creates a new VLV request control that will identify the target
-     * entry by an assertion value.
-     * 
-     * @param isCritical
-     *          Indicates whether the control should be considered
-     *          critical.
-     * @param beforeCount
-     *          The number of entries before the target assertion value.
-     * @param afterCount
-     *          The number of entries after the target assertion value.
-     * @param assertionValue
-     *          The greaterThanOrEqual target assertion value that
-     *          indicates where to start the page of results.
-     * @param contextID
-     *          The context ID provided by the server in the last VLV
-     *          response for the same set of criteria, or {@code null}
-     *          if there was no previous VLV response or the server did
-     *          not include a context ID in the last response.
-     */
-    public Request(boolean isCritical, int beforeCount, int afterCount,
-        ByteString assertionValue, ByteString contextID)
-    {
-      this(isCritical, beforeCount, afterCount, VLVTarget
-          .greaterThanOrEqual(assertionValue), contextID);
-    }
-
-
-
-    /**
-     * Creates a new VLV request control that will identify the target
-     * entry by offset.
-     * 
-     * @param isCritical
-     *          Indicates whether or not the control is critical.
-     * @param beforeCount
-     *          The number of entries before the target offset to
-     *          retrieve in the results page.
-     * @param afterCount
-     *          The number of entries after the target offset to
-     *          retrieve in the results page.
-     * @param offset
-     *          The offset in the result set to target for the beginning
-     *          of the page of results.
-     * @param contentCount
-     *          The content count returned by the server in the last
-     *          phase of the VLV request, or zero for a new VLV request
-     *          session.
-     * @param contextID
-     *          The context ID provided by the server in the last VLV
-     *          response for the same set of criteria, or {@code null}
-     *          if there was no previous VLV response or the server did
-     *          not include a context ID in the last response.
-     */
-    public Request(boolean isCritical, int beforeCount, int afterCount,
-        int offset, int contentCount, ByteString contextID)
-    {
-      this(isCritical, beforeCount, afterCount, VLVTarget.byOffset(
-          offset, contentCount), contextID);
-    }
-
-
-
-    /**
-     * Creates a new VLV request control that will identify the target
-     * entry by an assertion value.
-     * 
-     * @param beforeCount
-     *          The number of entries before the target offset to
-     *          retrieve in the results page.
-     * @param afterCount
-     *          The number of entries after the target offset to
-     *          retrieve in the results page.
-     * @param greaterThanOrEqual
-     *          The greaterThanOrEqual target assertion value that
-     *          indicates where to start the page of results.
-     */
-    public Request(int beforeCount, int afterCount,
-        ByteString greaterThanOrEqual)
-    {
-      this(false, beforeCount, afterCount, greaterThanOrEqual, null);
-    }
-
-
-
-    /**
-     * Creates a new VLV request control that will identify the target
-     * entry by offset.
-     * 
-     * @param beforeCount
-     *          The number of entries before the target offset to
-     *          retrieve in the results page.
-     * @param afterCount
-     *          The number of entries after the target offset to
-     *          retrieve in the results page.
-     * @param offset
-     *          The offset in the result set to target for the beginning
-     *          of the page of results.
-     * @param contentCount
-     *          The content count returned by the server in the last
-     *          phase of the VLV request, or zero for a new VLV request
-     *          session.
-     */
-    public Request(int beforeCount, int afterCount, int offset,
-        int contentCount)
-    {
-      this(false, beforeCount, afterCount, offset, contentCount, null);
-    }
-
-
-
-    private Request(boolean isCritical, int beforeCount,
-        int afterCount, VLVTarget target, ByteString contextID)
-    {
-      super(OID_VLV_REQUEST_CONTROL, isCritical);
-
-      this.beforeCount = beforeCount;
-      this.afterCount = afterCount;
-      this.target = target;
-      this.contextID = contextID;
-    }
-
-
-
-    /**
-     * Retrieves the number of entries after the target offset or
-     * assertion value to include in the results page.
-     * 
-     * @return The number of entries after the target offset to include
-     *         in the results page.
-     */
-    public int getAfterCount()
-    {
-      return afterCount;
-    }
-
-
-
-    /**
-     * Retrieves the number of entries before the target offset or
-     * assertion value to include in the results page.
-     * 
-     * @return The number of entries before the target offset to include
-     *         in the results page.
-     */
-    public int getBeforeCount()
-    {
-      return beforeCount;
-    }
-
-
-
-    /**
-     * Retrieves a context ID value that should be used to resume a
-     * previous VLV results session.
-     * 
-     * @return A context ID value that should be used to resume a
-     *         previous VLV results session, or {@code null} if none is
-     *         available.
-     */
-    public ByteString getContextID()
-    {
-      return contextID;
-    }
-
-
-
-    public VLVTarget getTarget()
-    {
-      return target;
-    }
-
-
-
-    @Override
-    public ByteString getValue()
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-      try
-      {
-        writer.writeStartSequence();
-        writer.writeInteger(beforeCount);
-        writer.writeInteger(afterCount);
-        target.encode(writer);
-        if (contextID != null)
-        {
-          writer.writeOctetString(contextID);
-        }
-        writer.writeEndSequence();
-        return buffer.toByteString();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-    }
-
-
-
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    public Request setAfterCount(int afterCount)
-    {
-      this.afterCount = afterCount;
-      return this;
-    }
-
-
-
-    public Request setBeforeCount(int beforeCount)
-    {
-      this.beforeCount = beforeCount;
-      return this;
-    }
-
-
-
-    public Request setContextID(ByteString contextID)
-    {
-      this.contextID = contextID;
-      return this;
-    }
-
-
-
-    public Request setTarget(ByteString assertionValue)
-    {
-      Validator.ensureNotNull(assertionValue);
-      target = VLVTarget.greaterThanOrEqual(assertionValue);
-      return this;
-    }
-
-
-
-    public Request setTarget(int offset, int contentCount)
-    {
-      target = VLVTarget.byOffset(offset, contentCount);
-      return this;
-    }
-
-
-
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("VLVRequestControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", beforeCount=");
-      buffer.append(beforeCount);
-      buffer.append(", afterCount=");
-      buffer.append(afterCount);
-      buffer.append(", target=");
-      target.toString(buffer);
-      buffer.append(", contextID=");
-      buffer.append(contextID);
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * This class implements the virtual list view response controls as
-   * defined in draft-ietf-ldapext-ldapv3-vlv. The ASN.1 description for
-   * the control value is: <BR>
-   * <BR>
-   * 
-   * <PRE>
-   * VirtualListViewResponse ::= SEQUENCE {
-   *       targetPosition    INTEGER (0 .. maxInt),
-   *       contentCount     INTEGER (0 .. maxInt),
-   *       virtualListViewResult ENUMERATED {
-   *            success (0),
-   *            operationsError (1),
-   *            protocolError (3),
-   *            unwillingToPerform (53),
-   *            insufficientAccessRights (50),
-   *            timeLimitExceeded (3),
-   *            adminLimitExceeded (11),
-   *            innapropriateMatching (18),
-   *            sortControlMissing (60),
-   *            offsetRangeError (61),
-   *            other(80),
-   *            ... },
-   *       contextID     OCTET STRING OPTIONAL }
-   * </PRE>
-   */
-  public static class Response extends Control
-  {
-    private final int targetPosition;
-
-    private final int contentCount;
-
-    private final VLVResult vlvResult;
-
-    private final ByteString contextID;
-
-
-
-    /**
-     * Creates a new VLV response control with the provided information.
-     * 
-     * @param isCritical
-     *          Indicates whether the control should be considered
-     *          critical.
-     * @param targetPosition
-     *          The position of the target entry in the result set.
-     * @param contentCount
-     *          The content count estimating the total number of entries
-     *          in the result set.
-     * @param vlvResult
-     *          The result code for the VLV operation.
-     * @param contextID
-     *          The context ID for this VLV response control.
-     */
-    public Response(boolean isCritical, int targetPosition,
-        int contentCount, VLVResult vlvResult, ByteString contextID)
-    {
-      super(OID_VLV_RESPONSE_CONTROL, isCritical);
-
-      this.targetPosition = targetPosition;
-      this.contentCount = contentCount;
-      this.vlvResult = vlvResult;
-      this.contextID = contextID;
-    }
-
-
-
-    /**
-     * Creates a new VLV response control with the provided information.
-     * 
-     * @param targetPosition
-     *          The position of the target entry in the result set.
-     * @param contentCount
-     *          The content count estimating the total number of entries
-     *          in the result set.
-     * @param vlvResult
-     *          The result code for the VLV operation.
-     */
-    public Response(int targetPosition, int contentCount,
-        VLVResult vlvResult)
-    {
-      this(false, targetPosition, contentCount, vlvResult, null);
-    }
-
-
-
-    /**
-     * Retrieves the estimated total number of entries in the result
-     * set.
-     * 
-     * @return The estimated total number of entries in the result set.
-     */
-    public int getContentCount()
-    {
-      return contentCount;
-    }
-
-
-
-    /**
-     * Retrieves a context ID value that should be included in the next
-     * request to retrieve a page of the same result set.
-     * 
-     * @return A context ID value that should be included in the next
-     *         request to retrieve a page of the same result set, or
-     *         {@code null} if there is no context ID.
-     */
-    public ByteString getContextID()
-    {
-      return contextID;
-    }
-
-
-
-    /**
-     * Retrieves the position of the target entry in the result set.
-     * 
-     * @return The position of the target entry in the result set.
-     */
-    public int getTargetPosition()
-    {
-      return targetPosition;
-    }
-
-
-
-    @Override
-    public ByteString getValue()
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-      try
-      {
-        writer.writeStartSequence();
-        writer.writeInteger(targetPosition);
-        writer.writeInteger(contentCount);
-        writer.writeEnumerated(vlvResult.intValue());
-        if (contextID != null)
-        {
-          writer.writeOctetString(contextID);
-        }
-        writer.writeEndSequence();
-        return buffer.toByteString();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-    }
-
-
-
-    /**
-     * Retrieves the result code for the VLV operation.
-     * 
-     * @return The result code for the VLV operation.
-     */
-    public VLVResult getVLVResult()
-    {
-      return vlvResult;
-    }
-
-
-
-    @Override
-    public boolean hasValue()
-    {
-      return true;
-    }
-
-
-
-    /**
-     * Appends a string representation of this VLV request control to
-     * the provided buffer.
-     * 
-     * @param buffer
-     *          The buffer to which the information should be appended.
-     */
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("VLVResponseControl(oid=");
-      buffer.append(getOID());
-      buffer.append(", criticality=");
-      buffer.append(isCritical());
-      buffer.append(", targetPosition=");
-      buffer.append(targetPosition);
-      buffer.append(", contentCount=");
-      buffer.append(contentCount);
-      buffer.append(", vlvResult=");
-      buffer.append(vlvResult);
-
-      if (contextID != null)
-      {
-        buffer.append(", contextID=");
-        buffer.append(contextID);
-      }
-
-      buffer.append(")");
-    }
-  }
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class RequestDecoder implements
-      ControlDecoder<Request>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Request decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = INFO_VLVREQ_CONTROL_NO_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      try
-      {
-        reader.readStartSequence();
-
-        int beforeCount = (int) reader.readInteger();
-        int afterCount = (int) reader.readInteger();
-        VLVTarget target = VLVTarget.decode(reader);
-        ByteString contextID = null;
-        if (reader.hasNextElement())
-        {
-          contextID = reader.readOctetString();
-        }
-
-        return new Request(isCritical, beforeCount, afterCount, target,
-            contextID);
-      }
-      catch (IOException e)
-      {
-        LocalizableMessage message = INFO_VLVREQ_CONTROL_CANNOT_DECODE_VALUE
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message, e);
-      }
-    }
-
-
-
-    public String getOID()
-    {
-      return OID_VLV_REQUEST_CONTROL;
-    }
-  }
-
-
-
-  /**
-   * ControlDecoder implentation to decode this control from a
-   * ByteString.
-   */
-  private final static class ResponseDecoder implements
-      ControlDecoder<Response>
-  {
-    /**
-     * {@inheritDoc}
-     */
-    public Response decode(boolean isCritical, ByteString value, Schema schema)
-        throws DecodeException
-    {
-      if (value == null)
-      {
-        LocalizableMessage message = INFO_VLVRES_CONTROL_NO_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      ASN1Reader reader = ASN1.getReader(value);
-      try
-      {
-        reader.readStartSequence();
-
-        int targetPosition = (int) reader.readInteger();
-        int contentCount = (int) reader.readInteger();
-        VLVResult vlvResult = VLVResult
-            .valueOf(reader.readEnumerated());
-        ByteString contextID = null;
-        if (reader.hasNextElement())
-        {
-          contextID = reader.readOctetString();
-        }
-
-        return new Response(isCritical, targetPosition, contentCount,
-            vlvResult, contextID);
-      }
-      catch (IOException e)
-      {
-        LocalizableMessage message = INFO_VLVRES_CONTROL_CANNOT_DECODE_VALUE
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message, e);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getOID()
-    {
-      return OID_VLV_RESPONSE_CONTROL;
-    }
-  }
-
-
-
-  /**
-   * The Control Decoder that can be used to decode the request control.
-   */
-  public static final ControlDecoder<Request> REQUEST_DECODER = new RequestDecoder();
-
-  /**
-   * The Control Decoder that can be used to decode the response
-   * control.
-   */
-  public static final ControlDecoder<Response> RESPONSE_DECODER = new ResponseDecoder();
-}
diff --git a/sdk/src/org/opends/sdk/controls/VLVResult.java b/sdk/src/org/opends/sdk/controls/VLVResult.java
deleted file mode 100644
index a8eb7bb..0000000
--- a/sdk/src/org/opends/sdk/controls/VLVResult.java
+++ /dev/null
@@ -1,113 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.opends.sdk.ResultCode;
-
-
-
-/**
- * Created by IntelliJ IDEA. User: boli Date: Jun 30, 2009 Time: 5:25:55
- * PM To change this template use File | Settings | File Templates.
- */
-public class VLVResult
-{
-  private static final VLVResult[] ELEMENTS = new VLVResult[81];
-
-  public static final VLVResult SUCCESS = register(ResultCode.SUCCESS);
-
-  public static final VLVResult OPERATIONS_ERROR = register(ResultCode.OPERATIONS_ERROR);
-
-  public static final VLVResult PROTOCOL_ERROR = register(ResultCode.PROTOCOL_ERROR);
-
-  public static final VLVResult TIME_LIMIT_EXCEEDED = register(ResultCode.TIME_LIMIT_EXCEEDED);
-
-  public static final VLVResult ADMIN_LIMIT_EXCEEDED = register(ResultCode.ADMIN_LIMIT_EXCEEDED);
-
-  public static final VLVResult INAPPROPRIATE_MATCHING = register(ResultCode.INAPPROPRIATE_MATCHING);
-
-  public static final VLVResult INSUFFICIENT_ACCESS_RIGHTS = register(ResultCode.INSUFFICIENT_ACCESS_RIGHTS);
-
-  public static final VLVResult UNWILLING_TO_PERFORM = register(ResultCode.UNWILLING_TO_PERFORM);
-
-  public static final VLVResult SORT_CONTROL_MISSING = register(ResultCode.SORT_CONTROL_MISSING);
-
-  public static final VLVResult OFFSET_RANGE_ERROR = register(ResultCode.OFFSET_RANGE_ERROR);
-
-  public static final VLVResult OTHER = register(ResultCode.OTHER);
-
-
-
-  public static VLVResult register(ResultCode resultCode)
-  {
-    VLVResult t = new VLVResult(resultCode);
-    ELEMENTS[resultCode.intValue()] = t;
-    return t;
-  }
-
-
-
-  public static VLVResult valueOf(int intValue)
-  {
-    VLVResult e = ELEMENTS[intValue];
-    if (e == null)
-    {
-      e = new VLVResult(ResultCode.valueOf(intValue));
-    }
-    return e;
-  }
-
-
-
-  public static List<VLVResult> values()
-  {
-    return Arrays.asList(ELEMENTS);
-  }
-
-
-
-  private final ResultCode resultCode;
-
-
-
-  private VLVResult(ResultCode resultCode)
-  {
-    this.resultCode = resultCode;
-  }
-
-
-
-  @Override
-  public boolean equals(Object o)
-  {
-    return (this == o)
-        || ((o instanceof VLVResult) && resultCode.equals(o));
-
-  }
-
-
-
-  @Override
-  public int hashCode()
-  {
-    return resultCode.hashCode();
-  }
-
-
-
-  public int intValue()
-  {
-    return resultCode.intValue();
-  }
-
-
-
-  @Override
-  public String toString()
-  {
-    return resultCode.toString();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/controls/VLVTarget.java b/sdk/src/org/opends/sdk/controls/VLVTarget.java
deleted file mode 100644
index 19230fd..0000000
--- a/sdk/src/org/opends/sdk/controls/VLVTarget.java
+++ /dev/null
@@ -1,192 +0,0 @@
-package org.opends.sdk.controls;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * Created by IntelliJ IDEA. User: boli Date: Jun 30, 2009 Time: 5:40:28
- * PM To change this template use File | Settings | File Templates.
- */
-public abstract class VLVTarget
-{
-  public static final class ByOffset extends VLVTarget
-  {
-    private final int offset;
-
-    private final int contentCount;
-
-
-
-    private ByOffset(int offset, int contentCount)
-    {
-      this.offset = offset;
-      this.contentCount = contentCount;
-    }
-
-
-
-    public int getContentCount()
-    {
-      return contentCount;
-    }
-
-
-
-    public int getOffset()
-    {
-      return offset;
-    }
-
-
-
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("byOffset(offset=");
-      buffer.append(offset);
-      buffer.append(", contentCount=");
-      buffer.append(contentCount);
-      buffer.append(")");
-    }
-
-
-
-    @Override
-    void encode(ASN1Writer writer) throws IOException
-    {
-      writer.writeStartSequence(TYPE_TARGET_BYOFFSET);
-      writer.writeInteger(offset);
-      writer.writeInteger(contentCount);
-      writer.writeEndSequence();
-    }
-  }
-
-
-
-  public static final class GreaterThanOrEqual extends VLVTarget
-  {
-    private final ByteString assertionValue;
-
-
-
-    private GreaterThanOrEqual(ByteString assertionValue)
-    {
-      this.assertionValue = assertionValue;
-    }
-
-
-
-    public ByteString getAssertionValue()
-    {
-      return assertionValue;
-    }
-
-
-
-    @Override
-    public void toString(StringBuilder buffer)
-    {
-      buffer.append("greaterThanOrEqual(assertionValue=");
-      buffer.append(assertionValue);
-      buffer.append(")");
-    }
-
-
-
-    @Override
-    void encode(ASN1Writer writer) throws IOException
-    {
-      writer.writeOctetString(TYPE_TARGET_GREATERTHANOREQUAL,
-          assertionValue);
-    }
-  }
-
-
-
-  /**
-   * The BER type to use when encoding the byOffset target element.
-   */
-  private static final byte TYPE_TARGET_BYOFFSET = (byte) 0xA0;
-
-  /**
-   * The BER type to use when encoding the greaterThanOrEqual target
-   * element.
-   */
-  private static final byte TYPE_TARGET_GREATERTHANOREQUAL = (byte) 0x81;
-
-
-
-  static VLVTarget byOffset(int offset, int contentCount)
-  {
-    return new ByOffset(offset, contentCount);
-  }
-
-
-
-  static VLVTarget decode(ASN1Reader reader) throws IOException,
-      DecodeException
-  {
-    byte targetType = reader.peekType();
-    switch (targetType)
-    {
-    case TYPE_TARGET_BYOFFSET:
-      reader.readStartSequence();
-      int offset = (int) reader.readInteger();
-      int contentCount = (int) reader.readInteger();
-      reader.readEndSequence();
-      return new ByOffset(offset, contentCount);
-
-    case TYPE_TARGET_GREATERTHANOREQUAL:
-      ByteString assertionValue = reader.readOctetString();
-      return new GreaterThanOrEqual(assertionValue);
-
-    default:
-      LocalizableMessage message = INFO_VLVREQ_CONTROL_INVALID_TARGET_TYPE
-          .get(byteToHex(targetType));
-      throw DecodeException.error(message);
-    }
-  }
-
-
-
-  static VLVTarget greaterThanOrEqual(ByteString assertionValue)
-  {
-    Validator.ensureNotNull(assertionValue);
-    return new GreaterThanOrEqual(assertionValue);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public String toString()
-  {
-    StringBuilder buffer = new StringBuilder();
-    toString(buffer);
-    return buffer.toString();
-  }
-
-
-
-  public abstract void toString(StringBuilder buffer);
-
-
-
-  abstract void encode(ASN1Writer writer) throws IOException;
-}
diff --git a/sdk/src/org/opends/sdk/controls/VirtualListViewRequestControl.java b/sdk/src/org/opends/sdk/controls/VirtualListViewRequestControl.java
new file mode 100644
index 0000000..6481220
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/VirtualListViewRequestControl.java
@@ -0,0 +1,525 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_VLVREQ_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.INFO_VLVREQ_CONTROL_CANNOT_DECODE_VALUE;
+import static com.sun.opends.sdk.messages.Messages.INFO_VLVREQ_CONTROL_INVALID_TARGET_TYPE;
+import static com.sun.opends.sdk.messages.Messages.INFO_VLVREQ_CONTROL_NO_VALUE;
+import static com.sun.opends.sdk.util.StaticUtils.byteToHex;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The virtual list view request control as defined in
+ * draft-ietf-ldapext-ldapv3-vlv. This control allows a client to specify that
+ * the server return, for a given search request with associated sort keys, a
+ * contiguous subset of the search result set. This subset is specified in terms
+ * of offsets into the ordered list, or in terms of a greater than or equal
+ * assertion value.
+ * <p>
+ * This control must be used in conjunction with the server-side sort request
+ * control in order to ensure that results are returned in a consistent order.
+ * <p>
+ * This control is similar to the simple paged results request control, except
+ * that it allows the client to move backwards and forwards in the result set.
+ *
+ * @see VirtualListViewResponseControl
+ * @see ServerSideSortRequestControl
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-ldapext-ldapv3-vlv">
+ *         draft-ietf-ldapext-ldapv3-vlv - LDAP Extensions for Scrolling View
+ *         Browsing of Search Results </a>
+ */
+public final class VirtualListViewRequestControl implements Control
+{
+  /**
+   * The OID for the virtual list view request control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.9";
+
+  /**
+   * A decoder which can be used for decoding the virtual list view request
+   * control.
+   */
+  public static final ControlDecoder<VirtualListViewRequestControl> DECODER =
+    new ControlDecoder<VirtualListViewRequestControl>()
+  {
+
+    public VirtualListViewRequestControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof VirtualListViewRequestControl)
+      {
+        return (VirtualListViewRequestControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_VLVREQ_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The request control must always have a value.
+        final LocalizableMessage message = INFO_VLVREQ_CONTROL_NO_VALUE.get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      try
+      {
+        reader.readStartSequence();
+
+        final int beforeCount = (int) reader.readInteger();
+        final int afterCount = (int) reader.readInteger();
+
+        int offset = -1;
+        int contentCount = -1;
+        ByteString assertionValue = null;
+        final byte targetType = reader.peekType();
+        switch (targetType)
+        {
+        case TYPE_TARGET_BYOFFSET:
+          reader.readStartSequence();
+          offset = (int) reader.readInteger();
+          contentCount = (int) reader.readInteger();
+          reader.readEndSequence();
+          break;
+        case TYPE_TARGET_GREATERTHANOREQUAL:
+          assertionValue = reader.readOctetString();
+          break;
+        default:
+          final LocalizableMessage message = INFO_VLVREQ_CONTROL_INVALID_TARGET_TYPE
+              .get(byteToHex(targetType));
+          throw DecodeException.error(message);
+        }
+
+        ByteString contextID = null;
+        if (reader.hasNextElement())
+        {
+          contextID = reader.readOctetString();
+        }
+
+        return new VirtualListViewRequestControl(control.isCritical(),
+            beforeCount, afterCount, contentCount, offset, assertionValue,
+            contextID);
+      }
+      catch (final IOException e)
+      {
+        final LocalizableMessage message = INFO_VLVREQ_CONTROL_CANNOT_DECODE_VALUE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+  /**
+   * The BER type to use when encoding the byOffset target element.
+   */
+  private static final byte TYPE_TARGET_BYOFFSET = (byte) 0xA0;
+
+  /**
+   * The BER type to use when encoding the greaterThanOrEqual target element.
+   */
+  private static final byte TYPE_TARGET_GREATERTHANOREQUAL = (byte) 0x81;
+
+
+
+  /**
+   * Creates a new virtual list view request control that will identify the
+   * target entry by an assertion value. The assertion value is encoded
+   * according to the ORDERING matching rule for the attribute description in
+   * the sort control. The assertion value is used to determine the target entry
+   * by comparison with the values of the attribute specified as the primary
+   * sort key. The first list entry who's value is no less than (less than or
+   * equal to when the sort order is reversed) the supplied value is the target
+   * entry.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param assertionValue
+   *          The assertion value that will be used to locate the target entry.
+   * @param beforeCount
+   *          The number of entries before the target entry to be included in
+   *          the search results.
+   * @param afterCount
+   *          The number of entries after the target entry to be included in the
+   *          search results.
+   * @param contextID
+   *          The context ID provided by the server in the last virtual list
+   *          view response for the same set of criteria, or {@code null} if
+   *          there was no previous virtual list view response or the server did
+   *          not include a context ID in the last response.
+   * @return The new control.
+   * @throws IllegalArgumentException
+   *           If {@code beforeCount} or {@code afterCount} were less than
+   *           {@code 0}.
+   * @throws NullPointerException
+   *           If {@code assertionValue} was {@code null}.
+   */
+  public static VirtualListViewRequestControl newAssertionControl(
+      final boolean isCritical, final ByteString assertionValue,
+      final int beforeCount, final int afterCount, final ByteString contextID)
+      throws IllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(assertionValue);
+    Validator.ensureTrue(beforeCount >= 0, "beforeCount is less than 0");
+    Validator.ensureTrue(afterCount >= 0, "afterCount is less than 0");
+
+    return new VirtualListViewRequestControl(isCritical, beforeCount,
+        afterCount, -1, -1, assertionValue, contextID);
+  }
+
+
+
+  /**
+   * Creates a new virtual list view request control that will identify the
+   * target entry by a positional offset within the complete result set.
+   *
+   * @param isCritical
+   *          {@code true} if it is unacceptable to perform the operation
+   *          without applying the semantics of this control, or {@code false}
+   *          if it can be ignored.
+   * @param offset
+   *          The positional offset of the target entry in the result set, where
+   *          {@code 1} is the first entry.
+   * @param contentCount
+   *          The content count returned by the server in the last virtual list
+   *          view response, or {@code 0} if this is the first virtual list view
+   *          request.
+   * @param beforeCount
+   *          The number of entries before the target entry to be included in
+   *          the search results.
+   * @param afterCount
+   *          The number of entries after the target entry to be included in the
+   *          search results.
+   * @param contextID
+   *          The context ID provided by the server in the last virtual list
+   *          view response for the same set of criteria, or {@code null} if
+   *          there was no previous virtual list view response or the server did
+   *          not include a context ID in the last response.
+   * @return The new control.
+   * @throws IllegalArgumentException
+   *           If {@code beforeCount}, {@code afterCount}, or {@code
+   *           contentCount} were less than {@code 0}, or if {@code offset} was
+   *           less than {@code 1}.
+   */
+  public static VirtualListViewRequestControl newOffsetControl(
+      final boolean isCritical, final int offset, final int contentCount,
+      final int beforeCount, final int afterCount, final ByteString contextID)
+      throws IllegalArgumentException
+  {
+    Validator.ensureTrue(beforeCount >= 0, "beforeCount is less than 0");
+    Validator.ensureTrue(afterCount >= 0, "afterCount is less than 0");
+    Validator.ensureTrue(offset > 0, "beforeCount is less than 1");
+    Validator.ensureTrue(contentCount >= 0, "afterCount is less than 0");
+
+    return new VirtualListViewRequestControl(isCritical, beforeCount,
+        afterCount, offset, contentCount, null, contextID);
+  }
+
+
+
+  private final int beforeCount;
+
+  private final int afterCount;
+
+  private final ByteString contextID;
+
+  private final boolean isCritical;
+
+  private final int contentCount;
+
+  private final int offset;
+
+  private final ByteString assertionValue;
+
+
+
+  private VirtualListViewRequestControl(final boolean isCritical,
+      final int beforeCount, final int afterCount, final int contentCount,
+      final int offset, final ByteString assertionValue,
+      final ByteString contextID)
+  {
+    this.isCritical = isCritical;
+    this.beforeCount = beforeCount;
+    this.afterCount = afterCount;
+    this.contentCount = contentCount;
+    this.offset = offset;
+    this.assertionValue = assertionValue;
+    this.contextID = contextID;
+  }
+
+
+
+  /**
+   * Returns the number of entries after the target entry to be included in the
+   * search results.
+   *
+   * @return The number of entries after the target entry to be included in the
+   *         search results.
+   */
+  public int getAfterCount()
+  {
+    return afterCount;
+  }
+
+
+
+  /**
+   * Returns the assertion value that will be used to locate the target entry,
+   * if applicable.
+   *
+   * @return The assertion value that will be used to locate the target entry,
+   *         or {@code null} if this control is using a target offset.
+   */
+  public ByteString getAssertionValue()
+  {
+    return assertionValue;
+  }
+
+
+
+  /**
+   * Returns the assertion value that will be used to locate the target entry,
+   * if applicable, decoded as a UTF-8 string.
+   *
+   * @return The assertion value that will be used to locate the target entry
+   *         decoded as a UTF-8 string, or {@code null} if this control is using
+   *         a target offset.
+   */
+  public String getAssertionValueAsString()
+  {
+    return assertionValue != null ? assertionValue.toString() : null;
+  }
+
+
+
+  /**
+   * Returns the number of entries before the target entry to be included in the
+   * search results.
+   *
+   * @return The number of entries before the target entry to be included in the
+   *         search results.
+   */
+  public int getBeforeCount()
+  {
+    return beforeCount;
+  }
+
+
+
+  /**
+   * Returns the content count returned by the server in the last virtual list
+   * view response, if applicable.
+   *
+   * @return The content count returned by the server in the last virtual list
+   *         view response, which may be {@code 0} if this is the first virtual
+   *         list view request, or {@code -1} if this control is using a target
+   *         assertion.
+   */
+  public int getContentCount()
+  {
+    return contentCount;
+  }
+
+
+
+  /**
+   * Returns the context ID provided by the server in the last virtual list view
+   * response for the same set of criteria, or {@code null} if there was no
+   * previous virtual list view response or the server did not include a context
+   * ID in the last response.
+   *
+   * @return The context ID provided by the server in the last virtual list view
+   *         response, or {@code null} if unavailable.
+   */
+  public ByteString getContextID()
+  {
+    return contextID;
+  }
+
+
+
+  /**
+   * Returns the positional offset of the target entry in the result set, if
+   * applicable, where {@code 1} is the first entry.
+   *
+   * @return The positional offset of the target entry in the result set, or
+   *         {@code -1} if this control is using a target assertion.
+   */
+  public int getOffset()
+  {
+    return offset;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      writer.writeInteger(beforeCount);
+      writer.writeInteger(afterCount);
+      if (hasTargetOffset())
+      {
+        writer.writeStartSequence(TYPE_TARGET_BYOFFSET);
+        writer.writeInteger(offset);
+        writer.writeInteger(contentCount);
+        writer.writeEndSequence();
+      }
+      else
+      {
+        writer.writeOctetString(TYPE_TARGET_GREATERTHANOREQUAL, assertionValue);
+      }
+      if (contextID != null)
+      {
+        writer.writeOctetString(contextID);
+      }
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * Returns {@code true} if this control is using a target offset, or {@code
+   * false} if this control is using a target assertion.
+   *
+   * @return {@code true} if this control is using a target offset, or {@code
+   *         false} if this control is using a target assertion.
+   */
+  public boolean hasTargetOffset()
+  {
+    return assertionValue != null ? false : true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("VirtualListViewRequestControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", beforeCount=");
+    builder.append(beforeCount);
+    builder.append(", afterCount=");
+    builder.append(afterCount);
+    if (hasTargetOffset())
+    {
+      builder.append(", offset=");
+      builder.append(offset);
+      builder.append(", contentCount=");
+      builder.append(contentCount);
+    }
+    else
+    {
+      builder.append(", greaterThanOrEqual=");
+      builder.append(assertionValue);
+    }
+    if (contextID != null)
+    {
+      builder.append(", contextID=");
+      builder.append(contextID);
+    }
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/controls/VirtualListViewResponseControl.java b/sdk/src/org/opends/sdk/controls/VirtualListViewResponseControl.java
new file mode 100644
index 0000000..6ede03a
--- /dev/null
+++ b/sdk/src/org/opends/sdk/controls/VirtualListViewResponseControl.java
@@ -0,0 +1,338 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.controls;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_VLVRES_CONTROL_BAD_OID;
+import static com.sun.opends.sdk.messages.Messages.INFO_VLVRES_CONTROL_CANNOT_DECODE_VALUE;
+import static com.sun.opends.sdk.messages.Messages.INFO_VLVRES_CONTROL_NO_VALUE;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * The virtual list view response control as defined in
+ * draft-ietf-ldapext-ldapv3-vlv. This control is included with a search result
+ * in response to a virtual list view request included with a search request.
+ * <p>
+ * If the result code included with this control indicates that the virtual list
+ * view request succeeded then the content count and target position give
+ * sufficient information for the client to update a list box slider position to
+ * match the newly retrieved entries and identify the target entry.
+ * <p>
+ * The content count and context ID should be used in a subsequent virtual list
+ * view requests.
+ *
+ * @see VirtualListViewRequestControl
+ * @see <a href="http://tools.ietf.org/html/draft-ietf-ldapext-ldapv3-vlv">
+ *         draft-ietf-ldapext-ldapv3-vlv - LDAP Extensions for Scrolling View
+ *         Browsing of Search Results </a>
+ */
+public final class VirtualListViewResponseControl implements Control
+{
+  /**
+   * The OID for the virtual list view request control.
+   */
+  public static final String OID = "2.16.840.1.113730.3.4.10";
+
+  /**
+   * A decoder which can be used for decoding the virtual list view response
+   * control.
+   */
+  public static final ControlDecoder<VirtualListViewResponseControl> DECODER =
+    new ControlDecoder<VirtualListViewResponseControl>()
+  {
+
+    public VirtualListViewResponseControl decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      Validator.ensureNotNull(control);
+
+      if (control instanceof VirtualListViewResponseControl)
+      {
+        return (VirtualListViewResponseControl) control;
+      }
+
+      if (!control.getOID().equals(OID))
+      {
+        final LocalizableMessage message = ERR_VLVRES_CONTROL_BAD_OID.get(
+            control.getOID(), OID);
+        throw DecodeException.error(message);
+      }
+
+      if (!control.hasValue())
+      {
+        // The response control must always have a value.
+        final LocalizableMessage message = INFO_VLVRES_CONTROL_NO_VALUE.get();
+        throw DecodeException.error(message);
+      }
+
+      final ASN1Reader reader = ASN1.getReader(control.getValue());
+      try
+      {
+        reader.readStartSequence();
+
+        final int targetPosition = (int) reader.readInteger();
+        final int contentCount = (int) reader.readInteger();
+        final ResultCode result = ResultCode.valueOf(reader.readEnumerated());
+        ByteString contextID = null;
+        if (reader.hasNextElement())
+        {
+          contextID = reader.readOctetString();
+        }
+
+        return new VirtualListViewResponseControl(control.isCritical(),
+            targetPosition, contentCount, result, contextID);
+      }
+      catch (final IOException e)
+      {
+        final LocalizableMessage message = INFO_VLVRES_CONTROL_CANNOT_DECODE_VALUE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+    }
+
+
+
+    public String getOID()
+    {
+      return OID;
+    }
+  };
+
+
+
+  /**
+   * Creates a new virtual list view response control.
+   *
+   * @param targetPosition
+   *          The position of the target entry in the result set.
+   * @param contentCount
+   *          An estimate of the total number of entries in the result set.
+   * @param result
+   *          The result code indicating the outcome of the virtual list view
+   *          request.
+   * @param contextID
+   *          A server-defined octet string. If present, the contextID should be
+   *          sent back to the server by the client in a subsequent virtual list
+   *          request.
+   * @return The new control.
+   * @throws IllegalArgumentException
+   *           If {@code targetPosition} or {@code contentCount} were less than
+   *           {@code 0}.
+   * @throws NullPointerException
+   *           If {@code result} was {@code null}.
+   */
+  public static VirtualListViewResponseControl newControl(
+      final int targetPosition, final int contentCount,
+      final ResultCode result, final ByteString contextID)
+      throws IllegalArgumentException, NullPointerException
+  {
+    Validator.ensureNotNull(result);
+    Validator.ensureTrue(targetPosition >= 0, "targetPosition is less than 0");
+    Validator.ensureTrue(contentCount >= 0, "contentCount is less than 0");
+
+    return new VirtualListViewResponseControl(false, targetPosition,
+        contentCount, result, contextID);
+  }
+
+
+
+  private final int targetPosition;
+
+  private final int contentCount;
+
+  private final ResultCode result;
+
+  private final ByteString contextID;
+
+  private final boolean isCritical;
+
+
+
+  private VirtualListViewResponseControl(final boolean isCritical,
+      final int targetPosition, final int contentCount,
+      final ResultCode result, final ByteString contextID)
+  {
+    this.isCritical = isCritical;
+    this.targetPosition = targetPosition;
+    this.contentCount = contentCount;
+    this.result = result;
+    this.contextID = contextID;
+  }
+
+
+
+  /**
+   * Returns the estimated total number of entries in the result set.
+   *
+   * @return The estimated total number of entries in the result set.
+   */
+  public int getContentCount()
+  {
+    return contentCount;
+  }
+
+
+
+  /**
+   * Returns a server-defined octet string which, if present, should be sent
+   * back to the server by the client in a subsequent virtual list request.
+   *
+   * @return A server-defined octet string which, if present, should be sent
+   *         back to the server by the client in a subsequent virtual list
+   *         request, or {@code null} if there is no context ID.
+   */
+  public ByteString getContextID()
+  {
+    return contextID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * Returns result code indicating the outcome of the virtual list view
+   * request.
+   *
+   * @return The result code indicating the outcome of the virtual list view
+   *         request.
+   */
+  public ResultCode getResult()
+  {
+    return result;
+  }
+
+
+
+  /**
+   * Returns the position of the target entry in the result set.
+   *
+   * @return The position of the target entry in the result set.
+   */
+  public int getTargetPosition()
+  {
+    return targetPosition;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+    try
+    {
+      writer.writeStartSequence();
+      writer.writeInteger(targetPosition);
+      writer.writeInteger(contentCount);
+      writer.writeEnumerated(result.intValue());
+      if (contextID != null)
+      {
+        writer.writeOctetString(contextID);
+      }
+      writer.writeEndSequence();
+      return buffer.toByteString();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean isCritical()
+  {
+    return isCritical;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("VirtualListViewResponseControl(oid=");
+    builder.append(getOID());
+    builder.append(", criticality=");
+    builder.append(isCritical());
+    builder.append(", targetPosition=");
+    builder.append(targetPosition);
+    builder.append(", contentCount=");
+    builder.append(contentCount);
+    builder.append(", result=");
+    builder.append(result);
+    if (contextID != null)
+    {
+      builder.append(", contextID=");
+      builder.append(contextID);
+    }
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/controls/package-info.java b/sdk/src/org/opends/sdk/controls/package-info.java
index 92fe52a..7ec769a 100755
--- a/sdk/src/org/opends/sdk/controls/package-info.java
+++ b/sdk/src/org/opends/sdk/controls/package-info.java
@@ -29,3 +29,6 @@
  * Classes implementing common LDAP controls.
  */
 package org.opends.sdk.controls;
+
+
+
diff --git a/sdk/src/org/opends/sdk/extensions/CancelRequest.java b/sdk/src/org/opends/sdk/extensions/CancelRequest.java
deleted file mode 100644
index b9308a4..0000000
--- a/sdk/src/org/opends/sdk/extensions/CancelRequest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package org.opends.sdk.extensions;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.*;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.requests.AbstractExtendedRequest;
-import org.opends.sdk.responses.Responses;
-import org.opends.sdk.responses.Result;
-
-
-
-
-/**
- * Created by IntelliJ IDEA. User: boli Date: Jun 22, 2009 Time: 4:44:51
- * PM To change this template use File | Settings | File Templates.
- */
-public final class CancelRequest extends
-    AbstractExtendedRequest<CancelRequest, Result>
-{
-  /**
-   * The request OID for the cancel extended operation.
-   */
-  static final String OID_CANCEL_REQUEST = "1.3.6.1.1.8";
-
-  private int cancelID;
-
-
-
-  public CancelRequest(int cancelID)
-  {
-    this.cancelID = cancelID;
-  }
-
-
-
-  public int getCancelID()
-  {
-    return cancelID;
-  }
-
-
-
-  public Operation getExtendedOperation()
-  {
-    return OPERATION;
-  }
-
-
-
-  public ByteString getRequestValue()
-  {
-    ByteStringBuilder buffer = new ByteStringBuilder(6);
-    ASN1Writer writer = ASN1.getWriter(buffer);
-
-    try
-    {
-      writer.writeStartSequence();
-      writer.writeInteger(cancelID);
-      writer.writeEndSequence();
-    }
-    catch (IOException ioe)
-    {
-      // This should never happen unless there is a bug somewhere.
-      throw new RuntimeException(ioe);
-    }
-
-    return buffer.toByteString();
-  }
-
-
-
-  public CancelRequest setCancelID(int cancelID)
-  {
-    this.cancelID = cancelID;
-    return this;
-  }
-
-
-
-  public StringBuilder toString(StringBuilder builder)
-  {
-    builder.append("CancelExtendedRequest(requestName=");
-    builder.append(getRequestName());
-    builder.append(", cancelID=");
-    builder.append(cancelID);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder;
-  }
-
-
-
-  private static final class Operation implements
-      ExtendedOperation<CancelRequest, Result>
-  {
-
-    public CancelRequest decodeRequest(String requestName,
-        ByteString requestValue) throws DecodeException
-    {
-      if ((requestValue == null) || (requestValue.length() <= 0))
-      {
-        throw DecodeException
-            .error(ERR_EXTOP_CANCEL_NO_REQUEST_VALUE.get());
-      }
-
-      try
-      {
-        ASN1Reader reader = ASN1.getReader(requestValue);
-        reader.readStartSequence();
-        int idToCancel = (int) reader.readInteger();
-        reader.readEndSequence();
-        return new CancelRequest(idToCancel);
-      }
-      catch (IOException e)
-      {
-        LocalizableMessage message = ERR_EXTOP_CANCEL_CANNOT_DECODE_REQUEST_VALUE
-            .get(getExceptionMessage(e));
-        throw DecodeException.error(message, e);
-      }
-    }
-
-
-
-    public Result decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage)
-    {
-      return Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-    }
-
-
-
-    public Result decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage,
-        String responseName, ByteString responseValue)
-        throws DecodeException
-    {
-      // TODO: Should we check to make sure OID and value is null?
-      return Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-    }
-  }
-
-
-
-  // Singleton instance.
-  private static final Operation OPERATION = new Operation();
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getRequestName()
-  {
-    return OID_CANCEL_REQUEST;
-  }
-}
diff --git a/sdk/src/org/opends/sdk/extensions/ExtendedOperation.java b/sdk/src/org/opends/sdk/extensions/ExtendedOperation.java
deleted file mode 100644
index a52e301..0000000
--- a/sdk/src/org/opends/sdk/extensions/ExtendedOperation.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package org.opends.sdk.extensions;
-
-
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.requests.ExtendedRequest;
-import org.opends.sdk.responses.Result;
-
-
-
-/**
- * Created by IntelliJ IDEA. User: digitalperk Date: Jun 19, 2009 Time:
- * 8:39:52 PM To change this template use File | Settings | File
- * Templates.
- */
-public interface ExtendedOperation<R extends ExtendedRequest<S>, S extends Result>
-{
-  R decodeRequest(String requestName, ByteString requestValue)
-      throws DecodeException;
-
-
-
-  S decodeResponse(ResultCode resultCode, String matchedDN,
-      String diagnosticMessage);
-
-
-
-  S decodeResponse(ResultCode resultCode, String matchedDN,
-      String diagnosticMessage, String responseName,
-      ByteString responseValue) throws DecodeException;
-
-}
diff --git a/sdk/src/org/opends/sdk/extensions/GetConnectionIDRequest.java b/sdk/src/org/opends/sdk/extensions/GetConnectionIDRequest.java
deleted file mode 100644
index 4dd4190..0000000
--- a/sdk/src/org/opends/sdk/extensions/GetConnectionIDRequest.java
+++ /dev/null
@@ -1,141 +0,0 @@
-package org.opends.sdk.extensions;
-
-
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.LocalizableMessage;
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.requests.AbstractExtendedRequest;
-
-
-
-
-/**
- * Created by IntelliJ IDEA. User: boli Date: Jun 23, 2009 Time:
- * 11:43:53 AM To change this template use File | Settings | File
- * Templates.
- */
-public final class GetConnectionIDRequest
-    extends
-    AbstractExtendedRequest<GetConnectionIDRequest, GetConnectionIDResult>
-{
-  /**
-   * The OID for the extended operation that can be used to get the
-   * client connection ID. It will be both the request and response OID.
-   */
-  static final String OID_GET_CONNECTION_ID_EXTOP = "1.3.6.1.4.1.26027.1.6.2";
-
-
-
-  public GetConnectionIDRequest()
-  {
-  }
-
-
-
-  public Operation getExtendedOperation()
-  {
-    return OPERATION;
-  }
-
-
-
-  public ByteString getRequestValue()
-  {
-    return null;
-  }
-
-
-
-  public StringBuilder toString(StringBuilder builder)
-  {
-    builder.append("GetConnectionIDExtendedRequest(requestName=");
-    builder.append(getRequestName());
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder;
-  }
-
-
-
-  private static final class Operation implements
-      ExtendedOperation<GetConnectionIDRequest, GetConnectionIDResult>
-  {
-
-    public GetConnectionIDRequest decodeRequest(String requestName,
-        ByteString requestValue) throws DecodeException
-    {
-      return new GetConnectionIDRequest();
-    }
-
-
-
-    public GetConnectionIDResult decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage,
-        String responseName, ByteString responseValue)
-        throws DecodeException
-    {
-      if (!resultCode.isExceptional()
-          && ((responseValue == null) || (responseValue.length() <= 0)))
-      {
-        throw DecodeException.error(LocalizableMessage
-            .raw("Empty response value"));
-      }
-
-      try
-      {
-        ASN1Reader reader = ASN1.getReader(responseValue);
-        int connectionID = (int) reader.readInteger();
-        return new GetConnectionIDResult(resultCode, connectionID)
-            .setMatchedDN(matchedDN).setDiagnosticMessage(
-                diagnosticMessage);
-      }
-      catch (IOException e)
-      {
-        throw DecodeException.error(LocalizableMessage
-            .raw("Error decoding response value"), e);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public GetConnectionIDResult decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage)
-    {
-      if (!resultCode.isExceptional())
-      {
-        // A successful response must contain a response name and
-        // value.
-        throw new IllegalArgumentException(
-            "No response name and value for result code "
-                + resultCode.intValue());
-      }
-      return new GetConnectionIDResult(resultCode, -1).setMatchedDN(
-          matchedDN).setDiagnosticMessage(diagnosticMessage);
-    }
-  }
-
-
-
-  // Singleton instance.
-  private static final Operation OPERATION = new Operation();
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getRequestName()
-  {
-    return OID_GET_CONNECTION_ID_EXTOP;
-  }
-}
diff --git a/sdk/src/org/opends/sdk/extensions/GetConnectionIDResult.java b/sdk/src/org/opends/sdk/extensions/GetConnectionIDResult.java
deleted file mode 100644
index 920ef33..0000000
--- a/sdk/src/org/opends/sdk/extensions/GetConnectionIDResult.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.extensions;
-
-
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ByteStringBuilder;
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.responses.AbstractExtendedResult;
-
-
-
-public class GetConnectionIDResult extends
-    AbstractExtendedResult<GetConnectionIDResult>
-{
-  private int connectionID;
-
-
-
-  public GetConnectionIDResult(ResultCode resultCode, int connectionID)
-  {
-    super(resultCode);
-    this.connectionID = connectionID;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getResponseName()
-  {
-    return GetConnectionIDRequest.OID_GET_CONNECTION_ID_EXTOP;
-  }
-
-
-
-  public int getConnectionID()
-  {
-    return connectionID;
-  }
-
-
-
-  public ByteString getResponseValue()
-  {
-    ByteStringBuilder buffer = new ByteStringBuilder(6);
-    ASN1Writer writer = ASN1.getWriter(buffer);
-
-    try
-    {
-      writer.writeInteger(connectionID);
-    }
-    catch (IOException ioe)
-    {
-      // This should never happen unless there is a bug somewhere.
-      throw new RuntimeException(ioe);
-    }
-
-    return buffer.toByteString();
-  }
-
-
-
-  public GetConnectionIDResult setConnectionID(int connectionID)
-  {
-    this.connectionID = connectionID;
-    return this;
-  }
-
-
-
-  public StringBuilder toString(StringBuilder builder)
-  {
-    builder.append("GetConnectionIDExtendedResponse(resultCode=");
-    builder.append(getResultCode());
-    builder.append(", matchedDN=");
-    builder.append(getMatchedDN());
-    builder.append(", diagnosticMessage=");
-    builder.append(getDiagnosticMessage());
-    builder.append(", referrals=");
-    builder.append(getReferralURIs());
-    builder.append(", responseName=");
-    builder.append(getResponseName());
-    builder.append(", connectionID=");
-    builder.append(connectionID);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder;
-  }
-}
diff --git a/sdk/src/org/opends/sdk/extensions/GetSymmetricKeyRequest.java b/sdk/src/org/opends/sdk/extensions/GetSymmetricKeyRequest.java
deleted file mode 100644
index a2767cc..0000000
--- a/sdk/src/org/opends/sdk/extensions/GetSymmetricKeyRequest.java
+++ /dev/null
@@ -1,227 +0,0 @@
-package org.opends.sdk.extensions;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.*;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.requests.AbstractExtendedRequest;
-import org.opends.sdk.responses.Responses;
-import org.opends.sdk.responses.Result;
-
-import com.sun.opends.sdk.util.StaticUtils;
-
-
-
-/**
- * Created by IntelliJ IDEA. User: boli Date: Jun 23, 2009 Time:
- * 12:10:59 PM To change this template use File | Settings | File
- * Templates.
- */
-public final class GetSymmetricKeyRequest extends
-    AbstractExtendedRequest<GetSymmetricKeyRequest, Result>
-{
-  /**
-   * The request OID for the get symmetric key extended operation.
-   */
-  static final String OID_GET_SYMMETRIC_KEY_EXTENDED_OP = "1.3.6.1.4.1.26027.1.6.3";
-
-  private String requestSymmetricKey = null;
-
-  private String instanceKeyID = null;
-
-
-
-  public GetSymmetricKeyRequest()
-  {
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getRequestName()
-  {
-    return OID_GET_SYMMETRIC_KEY_EXTENDED_OP;
-  }
-
-
-
-  public Operation getExtendedOperation()
-  {
-    return OPERATION;
-  }
-
-
-
-  public String getInstanceKeyID()
-  {
-    return instanceKeyID;
-  }
-
-
-
-  public String getRequestSymmetricKey()
-  {
-    return requestSymmetricKey;
-  }
-
-
-
-  public ByteString getRequestValue()
-  {
-    ByteStringBuilder buffer = new ByteStringBuilder();
-    ASN1Writer writer = ASN1.getWriter(buffer);
-
-    try
-    {
-      writer.writeStartSequence();
-      if (requestSymmetricKey != null)
-      {
-        writer.writeOctetString(TYPE_SYMMETRIC_KEY_ELEMENT,
-            requestSymmetricKey);
-      }
-      if (instanceKeyID != null)
-      {
-        writer.writeOctetString(TYPE_INSTANCE_KEY_ID_ELEMENT,
-            instanceKeyID);
-      }
-      writer.writeEndSequence();
-    }
-    catch (IOException ioe)
-    {
-      // This should never happen unless there is a bug somewhere.
-      throw new RuntimeException(ioe);
-    }
-
-    return buffer.toByteString();
-  }
-
-
-
-  public GetSymmetricKeyRequest setInstanceKeyID(String instanceKeyID)
-  {
-    this.instanceKeyID = instanceKeyID;
-    return this;
-  }
-
-
-
-  public GetSymmetricKeyRequest setRequestSymmetricKey(
-      String requestSymmetricKey)
-  {
-    this.requestSymmetricKey = requestSymmetricKey;
-    return this;
-  }
-
-
-
-  public StringBuilder toString(StringBuilder builder)
-  {
-    builder.append("GetSymmetricKeyExtendedRequest(requestName=");
-    builder.append(getRequestName());
-    builder.append(", requestSymmetricKey=");
-    builder.append(requestSymmetricKey);
-    builder.append(", instanceKeyID=");
-    builder.append(instanceKeyID);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder;
-  }
-
-
-
-  /**
-   * The BER type value for the symmetric key element of the operation
-   * value.
-   */
-  private static final byte TYPE_SYMMETRIC_KEY_ELEMENT = (byte) 0x80;
-
-  /**
-   * The BER type value for the instance key ID element of the operation
-   * value.
-   */
-  private static final byte TYPE_INSTANCE_KEY_ID_ELEMENT = (byte) 0x81;
-
-
-
-  private static final class Operation implements
-      ExtendedOperation<GetSymmetricKeyRequest, Result>
-  {
-
-    public GetSymmetricKeyRequest decodeRequest(String requestName,
-        ByteString requestValue) throws DecodeException
-    {
-      if (requestValue == null)
-      {
-        // The request must always have a value.
-        LocalizableMessage message = ERR_GET_SYMMETRIC_KEY_NO_VALUE.get();
-        throw DecodeException.error(message);
-      }
-
-      String requestSymmetricKey = null;
-      String instanceKeyID = null;
-
-      try
-      {
-        ASN1Reader reader = ASN1.getReader(requestValue);
-        reader.readStartSequence();
-        if (reader.hasNextElement()
-            && (reader.peekType() == TYPE_SYMMETRIC_KEY_ELEMENT))
-        {
-          requestSymmetricKey = reader.readOctetStringAsString();
-        }
-        if (reader.hasNextElement()
-            && (reader.peekType() == TYPE_INSTANCE_KEY_ID_ELEMENT))
-        {
-          instanceKeyID = reader.readOctetStringAsString();
-        }
-        reader.readEndSequence();
-        return new GetSymmetricKeyRequest().setRequestSymmetricKey(
-            requestSymmetricKey).setInstanceKeyID(instanceKeyID);
-      }
-      catch (IOException ae)
-      {
-        StaticUtils.DEBUG_LOG.throwing(
-            "GetSymmetricKeyRequest.Operation", "decodeRequest", ae);
-
-        LocalizableMessage message = ERR_GET_SYMMETRIC_KEY_ASN1_DECODE_EXCEPTION
-            .get(ae.getMessage());
-        throw DecodeException.error(message, ae);
-      }
-    }
-
-
-
-    public Result decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage)
-    {
-      return Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-    }
-
-
-
-    public Result decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage,
-        String responseName, ByteString responseValue)
-        throws DecodeException
-    {
-      // TODO: Should we check to make sure OID and value is null?
-      return Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-    }
-  }
-
-
-
-  // Singleton instance.
-  private static final Operation OPERATION = new Operation();
-}
diff --git a/sdk/src/org/opends/sdk/extensions/PasswordModifyRequest.java b/sdk/src/org/opends/sdk/extensions/PasswordModifyRequest.java
deleted file mode 100644
index c9b6d66..0000000
--- a/sdk/src/org/opends/sdk/extensions/PasswordModifyRequest.java
+++ /dev/null
@@ -1,274 +0,0 @@
-package org.opends.sdk.extensions;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-
-import org.opends.sdk.*;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.requests.AbstractExtendedRequest;
-
-
-
-
-/**
- * This class implements the password modify extended operation response
- * defined in RFC 3062. It includes support for requiring the user's
- * current password as well as for generating a new password if none was
- * provided.
- */
-public final class PasswordModifyRequest extends
-    AbstractExtendedRequest<PasswordModifyRequest, PasswordModifyResult>
-{
-  /**
-   * The request OID for the password modify extended operation.
-   */
-  public static final String OID_PASSWORD_MODIFY_REQUEST = "1.3.6.1.4.1.4203.1.11.1";
-
-  /**
-   * The ASN.1 element type that will be used to encode the userIdentity
-   * component in a password modify extended request.
-   */
-  static final byte TYPE_PASSWORD_MODIFY_USER_ID = (byte) 0x80;
-
-  /**
-   * The ASN.1 element type that will be used to encode the oldPasswd
-   * component in a password modify extended request.
-   */
-  static final byte TYPE_PASSWORD_MODIFY_OLD_PASSWORD = (byte) 0x81;
-
-  /**
-   * The ASN.1 element type that will be used to encode the newPasswd
-   * component in a password modify extended request.
-   */
-  static final byte TYPE_PASSWORD_MODIFY_NEW_PASSWORD = (byte) 0x82;
-
-  /**
-   * The ASN.1 element type that will be used to encode the genPasswd
-   * component in a password modify extended response.
-   */
-  static final byte TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD = (byte) 0x80;
-
-  private String userIdentity;
-
-  private ByteString oldPassword;
-
-  private ByteString newPassword;
-
-
-
-  public PasswordModifyRequest()
-  {
-
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getRequestName()
-  {
-    return OID_PASSWORD_MODIFY_REQUEST;
-  }
-
-
-  public ExtendedOperation<PasswordModifyRequest, PasswordModifyResult>
-  getExtendedOperation()
-  {
-    return OPERATION;
-  }
-
-  public ByteString getNewPassword()
-  {
-    return newPassword;
-  }
-
-
-
-  public ByteString getOldPassword()
-  {
-    return oldPassword;
-  }
-
-
-
-  public ByteString getRequestValue()
-  {
-    ByteStringBuilder buffer = new ByteStringBuilder();
-    ASN1Writer writer = ASN1.getWriter(buffer);
-
-    try
-    {
-      writer.writeStartSequence();
-      if (userIdentity != null)
-      {
-        writer.writeOctetString(TYPE_PASSWORD_MODIFY_USER_ID,
-            userIdentity);
-      }
-      if (oldPassword != null)
-      {
-        writer.writeOctetString(TYPE_PASSWORD_MODIFY_OLD_PASSWORD,
-            oldPassword);
-      }
-      if (newPassword != null)
-      {
-        writer.writeOctetString(TYPE_PASSWORD_MODIFY_NEW_PASSWORD,
-            newPassword);
-      }
-      writer.writeEndSequence();
-    }
-    catch (IOException ioe)
-    {
-      // This should never happen unless there is a bug somewhere.
-      throw new RuntimeException(ioe);
-    }
-
-    return buffer.toByteString();
-  }
-
-
-
-  public String getUserIdentity()
-  {
-    return userIdentity;
-  }
-
-
-
-  public PasswordModifyRequest setNewPassword(ByteString newPassword)
-  {
-    this.newPassword = newPassword;
-    return this;
-  }
-
-
-
-  public PasswordModifyRequest setOldPassword(ByteString oldPassword)
-  {
-    this.oldPassword = oldPassword;
-    return this;
-  }
-
-
-
-  public PasswordModifyRequest setUserIdentity(String userIdentity)
-  {
-    this.userIdentity = userIdentity;
-    return this;
-  }
-
-
-
-  public StringBuilder toString(StringBuilder builder)
-  {
-    builder.append("PasswordModifyExtendedRequest(requestName=");
-    builder.append(getRequestName());
-    builder.append(", userIdentity=");
-    builder.append(userIdentity);
-    builder.append(", oldPassword=");
-    builder.append(oldPassword);
-    builder.append(", newPassword=");
-    builder.append(newPassword);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder;
-  }
-
-
-
-  private static final class Operation implements
-      ExtendedOperation<PasswordModifyRequest, PasswordModifyResult>
-  {
-
-    public PasswordModifyRequest decodeRequest(String requestName,
-        ByteString requestValue) throws DecodeException
-    {
-      PasswordModifyRequest request = new PasswordModifyRequest();
-      if (requestValue != null)
-      {
-        try
-        {
-          ASN1Reader reader = ASN1.getReader(requestValue);
-          reader.readStartSequence();
-          if (reader.hasNextElement()
-              && (reader.peekType() == TYPE_PASSWORD_MODIFY_USER_ID))
-          {
-            request.setUserIdentity(reader.readOctetStringAsString());
-          }
-          if (reader.hasNextElement()
-              && (reader.peekType() == TYPE_PASSWORD_MODIFY_OLD_PASSWORD))
-          {
-            request.setOldPassword(reader.readOctetString());
-          }
-          if (reader.hasNextElement()
-              && (reader.peekType() == TYPE_PASSWORD_MODIFY_NEW_PASSWORD))
-          {
-            request.setNewPassword(reader.readOctetString());
-          }
-          reader.readEndSequence();
-        }
-        catch (IOException e)
-        {
-          LocalizableMessage message = ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST
-              .get(getExceptionMessage(e));
-          throw DecodeException.error(message, e);
-        }
-      }
-      return request;
-    }
-
-
-
-    public PasswordModifyResult decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage,
-        String responseName, ByteString responseValue)
-        throws DecodeException
-    {
-      // TODO: Should we check to make sure OID is null?
-      PasswordModifyResult result = new PasswordModifyResult(resultCode)
-          .setMatchedDN(matchedDN).setDiagnosticMessage(
-              diagnosticMessage);
-      if (resultCode == ResultCode.SUCCESS && responseValue != null)
-      {
-        try
-        {
-          ASN1Reader asn1Reader = ASN1.getReader(responseValue);
-          asn1Reader.readStartSequence();
-          if (asn1Reader.peekType() == TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD)
-          {
-            result.setGenPassword(asn1Reader.readOctetString());
-          }
-          asn1Reader.readEndSequence();
-        }
-        catch (IOException e)
-        {
-          LocalizableMessage message = ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST
-              .get(getExceptionMessage(e));
-          throw DecodeException.error(message, e);
-        }
-      }
-      return result;
-    }
-
-
-
-    public PasswordModifyResult decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage)
-    {
-      return new PasswordModifyResult(resultCode).setMatchedDN(
-          matchedDN).setDiagnosticMessage(diagnosticMessage);
-    }
-  }
-
-
-
-  // Singleton instance.
-  private static final Operation OPERATION = new Operation();
-}
diff --git a/sdk/src/org/opends/sdk/extensions/PasswordModifyResult.java b/sdk/src/org/opends/sdk/extensions/PasswordModifyResult.java
deleted file mode 100644
index 2882393..0000000
--- a/sdk/src/org/opends/sdk/extensions/PasswordModifyResult.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package org.opends.sdk.extensions;
-
-
-
-import java.io.IOException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ByteStringBuilder;
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.responses.AbstractExtendedResult;
-
-
-
-/**
- * This class implements the password modify extended operation response
- * defined in RFC 3062. It includes support for requiring the user's
- * current password as well as for generating a new password if none was
- * provided.
- */
-public class PasswordModifyResult extends
-    AbstractExtendedResult<PasswordModifyResult>
-{
-  private ByteString genPassword;
-
-
-
-  public PasswordModifyResult(ResultCode resultCode)
-  {
-    super(resultCode);
-  }
-
-
-
-  /**
-   * Get the newly generated password.
-   * 
-   * @return The password generated by the server or <code>null</code>
-   *         if it is not available.
-   */
-  public ByteString getGenPassword()
-  {
-    return genPassword;
-  }
-
-
-
-  public PasswordModifyResult setGenPassword(ByteString genPassword)
-  {
-    this.genPassword = genPassword;
-    return this;
-  }
-
-
-
-  public ByteString getResponseValue()
-  {
-    if (genPassword != null)
-    {
-      ByteStringBuilder buffer = new ByteStringBuilder();
-      ASN1Writer writer = ASN1.getWriter(buffer);
-
-      try
-      {
-        writer.writeStartSequence();
-        writer
-            .writeOctetString(
-                PasswordModifyRequest.TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD,
-                genPassword);
-        writer.writeEndSequence();
-      }
-      catch (IOException ioe)
-      {
-        // This should never happen unless there is a bug somewhere.
-        throw new RuntimeException(ioe);
-      }
-
-      return buffer.toByteString();
-    }
-    return null;
-  }
-
-
-
-  @Override
-  public String toString()
-  {
-    StringBuilder builder = new StringBuilder();
-    builder.append("PasswordModifyExtendedResponse(resultCode=");
-    builder.append(getResultCode());
-    builder.append(", matchedDN=");
-    builder.append(getMatchedDN());
-    builder.append(", diagnosticMessage=");
-    builder.append(getDiagnosticMessage());
-    builder.append(", referrals=");
-    builder.append(getReferralURIs());
-    if (genPassword != null)
-    {
-      builder.append(", genPassword=");
-      builder.append(genPassword);
-    }
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder.toString();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getResponseName()
-  {
-    // No response name defined.
-    return null;
-  }
-}
diff --git a/sdk/src/org/opends/sdk/extensions/PasswordPolicyStateExtendedOperation.java b/sdk/src/org/opends/sdk/extensions/PasswordPolicyStateExtendedOperation.java
deleted file mode 100644
index 4668d61..0000000
--- a/sdk/src/org/opends/sdk/extensions/PasswordPolicyStateExtendedOperation.java
+++ /dev/null
@@ -1,1070 +0,0 @@
-package org.opends.sdk.extensions;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-
-import org.opends.sdk.*;
-import org.opends.sdk.asn1.ASN1;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.requests.AbstractExtendedRequest;
-import org.opends.sdk.responses.AbstractExtendedResult;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * This class implements an LDAP extended operation that can be used to
- * query and update elements of the Directory Server password policy
- * state for a given user. The ASN.1 definition for the value of the
- * extended request is: <BR>
- * 
- * <PRE>
- * PasswordPolicyStateValue ::= SEQUENCE {
- *      targetUser     LDAPDN
- *      operations     SEQUENCE OF PasswordPolicyStateOperation OPTIONAL }
- * PasswordPolicyStateOperation ::= SEQUENCE {
- *      opType       ENUMERATED {
- *           getPasswordPolicyDN                          (0),
- *           getAccountDisabledState                      (1),
- *           setAccountDisabledState                      (2),
- *           clearAccountDisabledState                    (3),
- *           getAccountExpirationTime                     (4),
- *           setAccountExpirationTime                     (5),
- *           clearAccountExpirationTime                   (6),
- *           getSecondsUntilAccountExpiration             (7),
- *           getPasswordChangedTime                       (8),
- *           setPasswordChangedTime                       (9),
- *           clearPasswordChangedTime                     (10),
- *           getPasswordExpirationWarnedTime              (11),
- *           setPasswordExpirationWarnedTime              (12),
- *           clearPasswordExpirationWarnedTime            (13),
- *           getSecondsUntilPasswordExpiration            (14),
- *           getSecondsUntilPasswordExpirationWarning     (15),
- *           getAuthenticationFailureTimes                (16),
- *           addAuthenticationFailureTime                 (17),
- *           setAuthenticationFailureTimes                (18),
- *           clearAuthenticationFailureTimes              (19),
- *           getSecondsUntilAuthenticationFailureUnlock   (20),
- *           getRemainingAuthenticationFailureCount       (21),
- *           getLastLoginTime                             (22),
- *           setLastLoginTime                             (23),
- *           clearLastLoginTime                           (24),
- *           getSecondsUntilIdleLockout                   (25),
- *           getPasswordResetState                        (26),
- *           setPasswordResetState                        (27),
- *           clearPasswordResetState                      (28),
- *           getSecondsUntilPasswordResetLockout          (29),
- *           getGraceLoginUseTimes                        (30),
- *           addGraceLoginUseTime                         (31),
- *           setGraceLoginUseTimes                        (32),
- *           clearGraceLoginUseTimes                      (33),
- *           getRemainingGraceLoginCount                  (34),
- *           getPasswordChangedByRequiredTime             (35),
- *           setPasswordChangedByRequiredTime             (36),
- *           clearPasswordChangedByRequiredTime           (37),
- *           getSecondsUntilRequiredChangeTime            (38),
- *           getPasswordHistory                           (39),
- *           clearPasswordHistory                         (40),
- *           ... },
- *      opValues     SEQUENCE OF OCTET STRING OPTIONAL }
- * </PRE>
- * 
- * <BR>
- * Both the request and response values use the same encoded form, and
- * they both use the same OID of "1.3.6.1.4.1.26027.1.6.1". The response
- * value will only include get* elements. If the request did not include
- * any operations, then the response will include all get* elements;
- * otherwise, the response will only include the get* elements that
- * correspond to the state fields referenced in the request (regardless
- * of whether that operation was included in a get*, set*, add*,
- * remove*, or clear* operation).
- */
-public final class PasswordPolicyStateExtendedOperation
-{
-  /**
-   * The OID for the password policy state extended operation (both the
-   * request and response types).
-   */
-  static final String OID_PASSWORD_POLICY_STATE_EXTOP = "1.3.6.1.4.1.26027.1.6.1";
-
-
-
-  public interface Operation
-  {
-    public OperationType getOperationType();
-
-
-
-    public Iterable<ByteString> getValues();
-  }
-
-
-
-  public static enum OperationType implements Operation
-  {
-    GET_PASSWORD_POLICY_DN(PASSWORD_POLICY_DN_NAME),
-
-    GET_ACCOUNT_DISABLED_STATE(ACCOUNT_DISABLED_STATE_NAME), SET_ACCOUNT_DISABLED_STATE(
-        ACCOUNT_DISABLED_STATE_NAME), CLEAR_ACCOUNT_DISABLED_STATE(
-        ACCOUNT_DISABLED_STATE_NAME),
-
-    GET_ACCOUNT_EXPIRATION_TIME(ACCOUNT_EXPIRATION_TIME_NAME), SET_ACCOUNT_EXPIRATION_TIME(
-        ACCOUNT_EXPIRATION_TIME_NAME), CLEAR_ACCOUNT_EXPIRATION_TIME(
-        ACCOUNT_EXPIRATION_TIME_NAME),
-
-    GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION(
-        SECONDS_UNTIL_ACCOUNT_EXPIRATION_NAME),
-
-    GET_PASSWORD_CHANGED_TIME(PASSWORD_CHANGED_TIME_NAME), SET_PASSWORD_CHANGED_TIME(
-        PASSWORD_CHANGED_TIME_NAME), CLEAR_PASSWORD_CHANGED_TIME(
-        PASSWORD_CHANGED_TIME_NAME),
-
-    GET_PASSWORD_EXPIRATION_WARNED_TIME(
-        PASSWORD_EXPIRATION_WARNED_TIME_NAME), SET_PASSWORD_EXPIRATION_WARNED_TIME(
-        PASSWORD_EXPIRATION_WARNED_TIME_NAME), CLEAR_PASSWORD_EXPIRATION_WARNED_TIME(
-        PASSWORD_EXPIRATION_WARNED_TIME_NAME),
-
-    GET_SECONDS_UNTIL_PASSWORD_EXPIRATION(
-        SECONDS_UNTIL_PASSWORD_EXPIRATION_NAME),
-
-    GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING(
-        SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING_NAME),
-
-    GET_AUTHENTICATION_FAILURE_TIMES(AUTHENTICATION_FAILURE_TIMES_NAME), ADD_AUTHENTICATION_FAILURE_TIMES(
-        AUTHENTICATION_FAILURE_TIMES_NAME), SET_AUTHENTICATION_FAILURE_TIMES(
-        AUTHENTICATION_FAILURE_TIMES_NAME), CLEAR_AUTHENTICATION_FAILURE_TIMES(
-        AUTHENTICATION_FAILURE_TIMES_NAME),
-
-    GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK(
-        SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK_NAME),
-
-    GET_REMAINING_AUTHENTICATION_FAILURE_COUNT(
-        REMAINING_AUTHENTICATION_FAILURE_COUNT_NAME),
-
-    GET_LAST_LOGIN_TIME(LAST_LOGIN_TIME_NAME), SET_LAST_LOGIN_TIME(
-        LAST_LOGIN_TIME_NAME), CLEAR_LAST_LOGIN_TIME(
-        LAST_LOGIN_TIME_NAME),
-
-    GET_SECONDS_UNTIL_IDLE_LOCKOUT(SECONDS_UNTIL_IDLE_LOCKOUT_NAME),
-
-    GET_PASSWORD_RESET_STATE(PASSWORD_RESET_STATE_NAME), SET_PASSWORD_RESET_STATE(
-        PASSWORD_RESET_STATE_NAME), CLEAR_PASSWORD_RESET_STATE(
-        PASSWORD_RESET_STATE_NAME),
-
-    GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT(
-        SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT_NAME),
-
-    GET_GRACE_LOGIN_USE_TIMES(GRACE_LOGIN_USE_TIMES_NAME), ADD_GRACE_LOGIN_USE_TIME(
-        GRACE_LOGIN_USE_TIMES_NAME), SET_GRACE_LOGIN_USE_TIMES(
-        GRACE_LOGIN_USE_TIMES_NAME), CLEAR_GRACE_LOGIN_USE_TIMES(
-        GRACE_LOGIN_USE_TIMES_NAME),
-
-    GET_REMAINING_GRACE_LOGIN_COUNT(REMAINING_GRACE_LOGIN_COUNT_NAME),
-
-    GET_PASSWORD_CHANGED_BY_REQUIRED_TIME(
-        PASSWORD_CHANGED_BY_REQUIRED_TIME_NAME), SET_PASSWORD_CHANGED_BY_REQUIRED_TIME(
-        PASSWORD_CHANGED_BY_REQUIRED_TIME_NAME), CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME(
-        PASSWORD_CHANGED_BY_REQUIRED_TIME_NAME),
-
-    GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME(
-        SECONDS_UNTIL_REQUIRED_CHANGE_TIME_NAME),
-
-    GET_PASSWORD_HISTORY(PASSWORD_HISTORY_NAME), CLEAR_PASSWORD_HISTORY(
-        PASSWORD_HISTORY_NAME);
-
-    private String propertyName;
-
-
-
-    OperationType(String propertyName)
-    {
-      this.propertyName = propertyName;
-    }
-
-
-
-    public OperationType getOperationType()
-    {
-      return this;
-    }
-
-
-
-    public String getPropertyName()
-    {
-      return propertyName;
-    }
-
-
-
-    public Iterable<ByteString> getValues()
-    {
-      return null;
-    }
-
-
-
-    @Override
-    public String toString()
-    {
-      return propertyName;
-    }
-  }
-
-
-
-  public static class Request extends
-      AbstractExtendedRequest<Request, Response> implements
-      OperationContainer
-  {
-    private String targetUser;
-
-    private List<Operation> operations = new ArrayList<Operation>();
-
-
-
-    public Request(DN targetUser)
-    {
-      Validator.ensureNotNull(targetUser);
-      this.targetUser = targetUser.toString();
-    }
-
-
-
-    public Request(String targetUser)
-    {
-      Validator.ensureNotNull(targetUser);
-      this.targetUser = targetUser;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getRequestName()
-    {
-      return OID_PASSWORD_POLICY_STATE_EXTOP;
-    }
-
-
-
-    public void addAuthenticationFailureTime(Date date)
-    {
-      if (date == null)
-      {
-        operations.add(OperationType.ADD_AUTHENTICATION_FAILURE_TIMES);
-      }
-      else
-      {
-        operations.add(new MultiValueOperation(
-            OperationType.ADD_AUTHENTICATION_FAILURE_TIMES, ByteString
-                .valueOf(formatAsGeneralizedTime(date))));
-      }
-    }
-
-
-
-    public void addGraceLoginUseTime(Date date)
-    {
-      if (date == null)
-      {
-        operations.add(OperationType.ADD_GRACE_LOGIN_USE_TIME);
-      }
-      else
-      {
-        operations.add(new MultiValueOperation(
-            OperationType.ADD_GRACE_LOGIN_USE_TIME, ByteString
-                .valueOf(formatAsGeneralizedTime(date))));
-      }
-    }
-
-
-
-    public void addOperation(Operation operation)
-    {
-      operations.add(operation);
-    }
-
-
-
-    public void clearAccountDisabledState()
-    {
-      operations.add(OperationType.CLEAR_ACCOUNT_DISABLED_STATE);
-    }
-
-
-
-    public void clearAccountExpirationTime()
-    {
-      operations.add(OperationType.CLEAR_ACCOUNT_EXPIRATION_TIME);
-    }
-
-
-
-    public void clearAuthenticationFailureTimes()
-    {
-      operations.add(OperationType.CLEAR_AUTHENTICATION_FAILURE_TIMES);
-    }
-
-
-
-    public void clearGraceLoginUseTimes()
-    {
-      operations.add(OperationType.CLEAR_GRACE_LOGIN_USE_TIMES);
-    }
-
-
-
-    public void clearLastLoginTime()
-    {
-      operations.add(OperationType.CLEAR_LAST_LOGIN_TIME);
-    }
-
-
-
-    public void clearPasswordChangedByRequiredTime()
-    {
-      operations
-          .add(OperationType.CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME);
-    }
-
-
-
-    public void clearPasswordChangedTime()
-    {
-      operations.add(OperationType.CLEAR_PASSWORD_CHANGED_TIME);
-    }
-
-
-
-    public void clearPasswordExpirationWarnedTime()
-    {
-      operations
-          .add(OperationType.CLEAR_PASSWORD_EXPIRATION_WARNED_TIME);
-    }
-
-
-
-    public void clearPasswordHistory()
-    {
-      operations.add(OperationType.CLEAR_PASSWORD_HISTORY);
-    }
-
-
-
-    public void clearPasswordResetState()
-    {
-      operations.add(OperationType.CLEAR_PASSWORD_RESET_STATE);
-    }
-
-
-
-    @Override
-    public OperationImpl getExtendedOperation()
-    {
-      return OPERATION_IMPL;
-    }
-
-
-
-    public Iterable<Operation> getOperations()
-    {
-      return operations;
-    }
-
-
-
-    public ByteString getRequestValue()
-    {
-      return encode(targetUser, operations);
-    }
-
-
-
-    public void requestAccountDisabledState()
-    {
-      operations.add(OperationType.GET_ACCOUNT_DISABLED_STATE);
-    }
-
-
-
-    public void requestAccountExpirationTime()
-    {
-      operations.add(OperationType.GET_ACCOUNT_EXPIRATION_TIME);
-    }
-
-
-
-    public void requestAuthenticationFailureTimes()
-    {
-      operations.add(OperationType.GET_AUTHENTICATION_FAILURE_TIMES);
-    }
-
-
-
-    public void requestGraceLoginUseTimes()
-    {
-      operations.add(OperationType.GET_GRACE_LOGIN_USE_TIMES);
-    }
-
-
-
-    public void requestLastLoginTime()
-    {
-      operations.add(OperationType.GET_LAST_LOGIN_TIME);
-    }
-
-
-
-    public void requestPasswordChangedByRequiredTime()
-    {
-      operations
-          .add(OperationType.GET_PASSWORD_CHANGED_BY_REQUIRED_TIME);
-    }
-
-
-
-    public void requestPasswordChangedTime()
-    {
-      operations.add(OperationType.GET_PASSWORD_CHANGED_TIME);
-    }
-
-
-
-    public void requestPasswordExpirationWarnedTime()
-    {
-      operations.add(OperationType.GET_PASSWORD_EXPIRATION_WARNED_TIME);
-    }
-
-
-
-    public void requestPasswordHistory()
-    {
-      operations.add(OperationType.GET_PASSWORD_HISTORY);
-    }
-
-
-
-    public void requestPasswordPolicyDN()
-    {
-      operations.add(OperationType.GET_PASSWORD_POLICY_DN);
-    }
-
-
-
-    public void requestPasswordResetState()
-    {
-      operations.add(OperationType.GET_PASSWORD_RESET_STATE);
-    }
-
-
-
-    public void requestRemainingAuthenticationFailureCount()
-    {
-      operations
-          .add(OperationType.GET_REMAINING_AUTHENTICATION_FAILURE_COUNT);
-    }
-
-
-
-    public void requestRemainingGraceLoginCount()
-    {
-      operations.add(OperationType.GET_REMAINING_GRACE_LOGIN_COUNT);
-    }
-
-
-
-    public void requestSecondsUntilAccountExpiration()
-    {
-      operations
-          .add(OperationType.GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION);
-    }
-
-
-
-    public void requestSecondsUntilAuthenticationFailureUnlock()
-    {
-      operations
-          .add(OperationType.GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK);
-    }
-
-
-
-    public void requestSecondsUntilIdleLockout()
-    {
-      operations.add(OperationType.GET_SECONDS_UNTIL_IDLE_LOCKOUT);
-    }
-
-
-
-    public void requestSecondsUntilPasswordExpiration()
-    {
-      operations
-          .add(OperationType.GET_SECONDS_UNTIL_PASSWORD_EXPIRATION);
-    }
-
-
-
-    public void requestSecondsUntilPasswordExpirationWarning()
-    {
-      operations
-          .add(OperationType.GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING);
-    }
-
-
-
-    public void requestSecondsUntilPasswordResetLockout()
-    {
-      operations
-          .add(OperationType.GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT);
-    }
-
-
-
-    public void requestSecondsUntilRequiredChangeTime()
-    {
-      operations
-          .add(OperationType.GET_SECONDS_UNTIL_REQUIRED_CHANGE_TIME);
-    }
-
-
-
-    public void setAccountDisabledState(boolean state)
-    {
-      operations.add(new MultiValueOperation(
-          OperationType.SET_ACCOUNT_DISABLED_STATE, ByteString
-              .valueOf(String.valueOf(state))));
-    }
-
-
-
-    public void setAccountExpirationTime(Date date)
-    {
-      if (date == null)
-      {
-        operations.add(OperationType.SET_ACCOUNT_EXPIRATION_TIME);
-      }
-      else
-      {
-        operations.add(new MultiValueOperation(
-            OperationType.SET_ACCOUNT_EXPIRATION_TIME, ByteString
-                .valueOf(formatAsGeneralizedTime(date))));
-      }
-    }
-
-
-
-    public void setAuthenticationFailureTimes(Date... dates)
-    {
-      if (dates == null)
-      {
-        operations.add(OperationType.SET_AUTHENTICATION_FAILURE_TIMES);
-      }
-      else
-      {
-        ArrayList<ByteString> times = new ArrayList<ByteString>(
-            dates.length);
-        for (Date date : dates)
-        {
-          times.add(ByteString.valueOf(formatAsGeneralizedTime(date)));
-        }
-        operations.add(new MultiValueOperation(
-            OperationType.SET_AUTHENTICATION_FAILURE_TIMES, times));
-      }
-    }
-
-
-
-    public void setGraceLoginUseTimes(Date... dates)
-    {
-      if (dates == null)
-      {
-        operations.add(OperationType.SET_GRACE_LOGIN_USE_TIMES);
-      }
-      else
-      {
-        ArrayList<ByteString> times = new ArrayList<ByteString>(
-            dates.length);
-        for (Date date : dates)
-        {
-          times.add(ByteString.valueOf(formatAsGeneralizedTime(date)));
-        }
-        operations.add(new MultiValueOperation(
-            OperationType.SET_GRACE_LOGIN_USE_TIMES, times));
-      }
-    }
-
-
-
-    public void setLastLoginTime(Date date)
-    {
-      if (date == null)
-      {
-        operations.add(OperationType.SET_LAST_LOGIN_TIME);
-
-      }
-      else
-      {
-        operations.add(new MultiValueOperation(
-            OperationType.SET_LAST_LOGIN_TIME, ByteString
-                .valueOf(formatAsGeneralizedTime(date))));
-      }
-    }
-
-
-
-    public void setPasswordChangedByRequiredTime(boolean state)
-    {
-      operations.add(new MultiValueOperation(
-          OperationType.SET_PASSWORD_CHANGED_BY_REQUIRED_TIME,
-          ByteString.valueOf(String.valueOf(state))));
-    }
-
-
-
-    public void setPasswordChangedTime(Date date)
-    {
-      if (date == null)
-      {
-        operations.add(OperationType.SET_PASSWORD_CHANGED_TIME);
-      }
-      else
-      {
-        operations.add(new MultiValueOperation(
-            OperationType.SET_PASSWORD_CHANGED_TIME, ByteString
-                .valueOf(formatAsGeneralizedTime(date))));
-      }
-    }
-
-
-
-    public void setPasswordExpirationWarnedTime(Date date)
-    {
-      if (date == null)
-      {
-        operations
-            .add(OperationType.SET_PASSWORD_EXPIRATION_WARNED_TIME);
-
-      }
-      else
-      {
-        operations.add(new MultiValueOperation(
-            OperationType.SET_PASSWORD_EXPIRATION_WARNED_TIME,
-            ByteString.valueOf(formatAsGeneralizedTime(date))));
-      }
-    }
-
-
-
-    public void setPasswordResetState(boolean state)
-    {
-      operations.add(new MultiValueOperation(
-          OperationType.SET_LAST_LOGIN_TIME, ByteString.valueOf(String
-              .valueOf(state))));
-    }
-
-
-
-    @Override
-    public String toString()
-    {
-      StringBuilder builder = new StringBuilder();
-      builder.append("PasswordPolicyStateExtendedRequest(requestName=");
-      builder.append(getRequestName());
-      builder.append(", targetUser=");
-      builder.append(targetUser);
-      builder.append(", operations=");
-      builder.append(operations);
-      builder.append(", controls=");
-      builder.append(getControls());
-      builder.append(")");
-      return builder.toString();
-    }
-  }
-
-
-
-  public static class Response extends AbstractExtendedResult<Response>
-      implements OperationContainer
-  {
-    private String targetUser;
-
-    private List<Operation> operations = new ArrayList<Operation>();
-
-
-
-    public Response(ResultCode resultCode, DN targetUser)
-    {
-      this(resultCode, String.valueOf(targetUser));
-    }
-
-
-
-    public Response(ResultCode resultCode, String targetUser)
-    {
-      super(resultCode);
-      this.targetUser = targetUser;
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getResponseName()
-    {
-      // No response name defined.
-      return OID_PASSWORD_POLICY_STATE_EXTOP;
-    }
-
-
-
-    public void addOperation(Operation operation)
-    {
-      operations.add(operation);
-    }
-
-
-
-    public Iterable<Operation> getOperations()
-    {
-      return operations;
-    }
-
-
-
-    public ByteString getResponseValue()
-    {
-      return encode(targetUser, operations);
-    }
-
-
-
-    @Override
-    public String toString()
-    {
-      StringBuilder builder = new StringBuilder();
-      builder.append("PasswordPolicyStateExtendedResponse(resultCode=");
-      builder.append(getResultCode());
-      builder.append(", matchedDN=");
-      builder.append(getMatchedDN());
-      builder.append(", diagnosticMessage=");
-      builder.append(getDiagnosticMessage());
-      builder.append(", referrals=");
-      builder.append(getReferralURIs());
-      builder.append(", responseName=");
-      builder.append(getResponseName());
-      builder.append(", targetUser=");
-      builder.append(targetUser);
-      builder.append(", operations=");
-      builder.append(operations);
-      builder.append(", controls=");
-      builder.append(getControls());
-      builder.append(")");
-      return builder.toString();
-    }
-  }
-
-
-
-  private static class MultiValueOperation implements Operation
-  {
-    private OperationType property;
-
-    private List<ByteString> values;
-
-
-
-    private MultiValueOperation(OperationType property, ByteString value)
-    {
-      this.property = property;
-      this.values = Collections.singletonList(value);
-    }
-
-
-
-    private MultiValueOperation(OperationType property,
-        List<ByteString> values)
-    {
-      this.property = property;
-      this.values = values;
-    }
-
-
-
-    public OperationType getOperationType()
-    {
-      return property;
-    }
-
-
-
-    public Iterable<ByteString> getValues()
-    {
-      return values;
-    }
-
-
-
-    @Override
-    public String toString()
-    {
-      return property.getPropertyName() + ": " + values;
-    }
-  }
-
-
-
-  private interface OperationContainer
-  {
-    public void addOperation(Operation operation);
-
-
-
-    public Iterable<Operation> getOperations();
-  }
-
-
-
-  private static final String PASSWORD_POLICY_DN_NAME = "Password Policy DN";
-
-  private static final String ACCOUNT_DISABLED_STATE_NAME = "Account Disabled State";
-
-  private static final String ACCOUNT_EXPIRATION_TIME_NAME = "Account Expiration Time";
-
-  private static final String SECONDS_UNTIL_ACCOUNT_EXPIRATION_NAME = "Seconds Until Account Expiration";
-
-  private static final String PASSWORD_CHANGED_TIME_NAME = "Password Changed Time";
-
-  private static final String PASSWORD_EXPIRATION_WARNED_TIME_NAME = "Password Expiration Warned Time";
-
-  private static final String SECONDS_UNTIL_PASSWORD_EXPIRATION_NAME = "Seconds Until Password Expiration";
-
-  private static final String SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING_NAME = "Seconds Until Password Expiration Warning";
-
-  private static final String AUTHENTICATION_FAILURE_TIMES_NAME = "Authentication Failure Times";
-
-  private static final String SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK_NAME = "Seconds Until Authentication Failure Unlock";
-
-  private static final String REMAINING_AUTHENTICATION_FAILURE_COUNT_NAME = "Remaining Authentication Failure Count";
-
-  private static final String LAST_LOGIN_TIME_NAME = "Last Login Time";
-
-  private static final String SECONDS_UNTIL_IDLE_LOCKOUT_NAME = "Seconds Until Idle Lockout";
-
-  private static final String PASSWORD_RESET_STATE_NAME = "Password Reset State";
-
-  private static final String SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT_NAME = "Seconds Until Password Reset Lockout";
-
-  private static final String GRACE_LOGIN_USE_TIMES_NAME = "Grace Login Use Times";
-
-  private static final String REMAINING_GRACE_LOGIN_COUNT_NAME = "Remaining Grace Login Count";
-
-  private static final String PASSWORD_CHANGED_BY_REQUIRED_TIME_NAME = "Password Changed By Required Time";
-
-  private static final String SECONDS_UNTIL_REQUIRED_CHANGE_TIME_NAME = "Seconds Until Required Change Time";
-
-  private static final String PASSWORD_HISTORY_NAME = "Password History";
-
-
-
-  private static void decodeOperations(ASN1Reader reader,
-      OperationContainer container) throws IOException, DecodeException
-  {
-    // See if we have operations
-    if (reader.hasNextElement())
-    {
-      reader.readStartSequence();
-      int opType;
-      OperationType type;
-      while (reader.hasNextElement())
-      {
-        reader.readStartSequence();
-        // Read the opType
-        opType = reader.readEnumerated();
-        try
-        {
-          type = OperationType.values()[opType];
-        }
-        catch (IndexOutOfBoundsException iobe)
-        {
-          throw DecodeException.error(
-              ERR_PWPSTATE_EXTOP_UNKNOWN_OP_TYPE.get(String
-                  .valueOf(opType)), iobe);
-        }
-
-        // See if we have any values
-        if (reader.hasNextElement())
-        {
-          reader.readStartSequence();
-          ArrayList<ByteString> values = new ArrayList<ByteString>();
-          while (reader.hasNextElement())
-          {
-            values.add(reader.readOctetString());
-          }
-          reader.readEndSequence();
-          container.addOperation(new MultiValueOperation(type, values));
-        }
-        else
-        {
-          container.addOperation(type);
-        }
-        reader.readEndSequence();
-      }
-      reader.readEndSequence();
-    }
-  }
-
-
-
-  private static ByteString encode(String targetUser,
-      List<Operation> operations)
-  {
-    ByteStringBuilder buffer = new ByteStringBuilder(6);
-    ASN1Writer writer = ASN1.getWriter(buffer);
-
-    try
-    {
-      writer.writeStartSequence();
-      writer.writeOctetString(targetUser);
-      if (!operations.isEmpty())
-      {
-        writer.writeStartSequence();
-        for (Operation operation : operations)
-        {
-          writer.writeStartSequence();
-          writer
-              .writeEnumerated(operation.getOperationType().ordinal());
-          if (operation.getValues() != null)
-          {
-            writer.writeStartSequence();
-            for (ByteString value : operation.getValues())
-            {
-              writer.writeOctetString(value);
-            }
-            writer.writeEndSequence();
-          }
-          writer.writeEndSequence();
-        }
-        writer.writeEndSequence();
-      }
-      writer.writeEndSequence();
-    }
-    catch (IOException ioe)
-    {
-      // This should never happen unless there is a bug somewhere.
-      throw new RuntimeException(ioe);
-    }
-
-    return buffer.toByteString();
-  }
-
-
-
-  private static final class OperationImpl implements
-      ExtendedOperation<Request, Response>
-  {
-
-    public Request decodeRequest(String requestName,
-        ByteString requestValue) throws DecodeException
-    {
-      if ((requestValue == null) || (requestValue.length() <= 0))
-      {
-        throw DecodeException
-            .error(ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE.get());
-      }
-
-      try
-      {
-        ASN1Reader reader = ASN1.getReader(requestValue);
-        reader.readStartSequence();
-
-        // Read the target user DN
-        Request request = new Request(reader.readOctetStringAsString());
-
-        decodeOperations(reader, request);
-        reader.readEndSequence();
-        return request;
-      }
-      catch (IOException ioe)
-      {
-        LocalizableMessage message = ERR_PWPSTATE_EXTOP_DECODE_FAILURE
-            .get(getExceptionMessage(ioe));
-        throw DecodeException.error(message, ioe);
-      }
-    }
-
-
-
-    public Response decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage,
-        String responseName, ByteString responseValue)
-        throws DecodeException
-    {
-      if (!resultCode.isExceptional()
-          && ((responseValue == null) || (responseValue.length() <= 0)))
-      {
-        throw DecodeException
-            .error(ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE.get());
-      }
-
-      try
-      {
-        ASN1Reader reader = ASN1.getReader(responseValue);
-        reader.readStartSequence();
-
-        // Read the target user DN
-        Response response = new Response(resultCode, reader
-            .readOctetStringAsString()).setMatchedDN(matchedDN)
-            .setDiagnosticMessage(diagnosticMessage);
-
-        decodeOperations(reader, response);
-        reader.readEndSequence();
-        return response;
-      }
-      catch (IOException ioe)
-      {
-        LocalizableMessage message = ERR_PWPSTATE_EXTOP_DECODE_FAILURE
-            .get(getExceptionMessage(ioe));
-        throw DecodeException.error(message, ioe);
-      }
-    }
-
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public Response decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage)
-    {
-      if (!resultCode.isExceptional())
-      {
-        // A successful response must contain a response name and
-        // value.
-        throw new IllegalArgumentException(
-            "No response name and value for result code "
-                + resultCode.intValue());
-      }
-
-      return new Response(resultCode, (String) null).setMatchedDN(
-          matchedDN).setDiagnosticMessage(diagnosticMessage);
-    }
-  }
-
-
-
-  // Singleton instance.
-  private static final OperationImpl OPERATION_IMPL = new OperationImpl();
-}
diff --git a/sdk/src/org/opends/sdk/extensions/StartTLSRequest.java b/sdk/src/org/opends/sdk/extensions/StartTLSRequest.java
deleted file mode 100644
index 70819df..0000000
--- a/sdk/src/org/opends/sdk/extensions/StartTLSRequest.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.opends.sdk.extensions;
-
-
-
-import javax.net.ssl.SSLContext;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.requests.AbstractExtendedRequest;
-import org.opends.sdk.responses.Responses;
-import org.opends.sdk.responses.Result;
-
-
-
-/**
- * Created by IntelliJ IDEA. User: boli Date: Jun 22, 2009 Time: 6:21:44
- * PM To change this template use File | Settings | File Templates.
- */
-public final class StartTLSRequest extends
-    AbstractExtendedRequest<StartTLSRequest, Result>
-{
-  private final SSLContext sslContext;
-
-  /**
-   * The request OID for the StartTLS extended operation.
-   */
-  public static final String OID_START_TLS_REQUEST = "1.3.6.1.4.1.1466.20037";
-
-
-
-  public StartTLSRequest(SSLContext sslContext)
-  {
-    this.sslContext = sslContext;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getRequestName()
-  {
-    return OID_START_TLS_REQUEST;
-  }
-
-
-
-  public Operation getExtendedOperation()
-  {
-    return OPERATION;
-  }
-
-
-
-  public ByteString getRequestValue()
-  {
-    return null;
-  }
-
-
-
-  public SSLContext getSSLContext()
-  {
-    return sslContext;
-  }
-
-
-
-  public StringBuilder toString(StringBuilder builder)
-  {
-    builder.append("StartTLSExtendedRequest(requestName=");
-    builder.append(getRequestName());
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder;
-  }
-
-
-
-  private static final class Operation implements
-      ExtendedOperation<StartTLSRequest, Result>
-  {
-
-    public StartTLSRequest decodeRequest(String requestName,
-        ByteString requestValue) throws DecodeException
-    {
-      return new StartTLSRequest(null);
-    }
-
-
-
-    public Result decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage,
-        String responseName, ByteString responseValue)
-        throws DecodeException
-    {
-      // TODO: Should we check oid is NOT null and matches but
-      // value is null?
-      return Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-    }
-
-
-
-    public Result decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage)
-    {
-      return Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-    }
-  }
-
-
-
-  // Singleton instance.
-  private static final Operation OPERATION = new Operation();
-
-}
diff --git a/sdk/src/org/opends/sdk/extensions/WhoAmIRequest.java b/sdk/src/org/opends/sdk/extensions/WhoAmIRequest.java
deleted file mode 100644
index ae87c86..0000000
--- a/sdk/src/org/opends/sdk/extensions/WhoAmIRequest.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package org.opends.sdk.extensions;
-
-
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.requests.AbstractExtendedRequest;
-
-
-
-/**
- * Created by IntelliJ IDEA. User: boli Date: Jun 22, 2009 Time: 6:40:06
- * PM To change this template use File | Settings | File Templates.
- */
-public final class WhoAmIRequest extends
-    AbstractExtendedRequest<WhoAmIRequest, WhoAmIResult>
-{
-  /**
-   * The request OID for the "Who Am I?" extended operation.
-   */
-  static final String OID_WHO_AM_I_REQUEST = "1.3.6.1.4.1.4203.1.11.3";
-
-
-
-  public WhoAmIRequest()
-  {
-
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getRequestName()
-  {
-    return OID_WHO_AM_I_REQUEST;
-  }
-
-
-
-  public Operation getExtendedOperation()
-  {
-    return OPERATION;
-  }
-
-
-
-  public ByteString getRequestValue()
-  {
-    return null;
-  }
-
-
-
-  public StringBuilder toString(StringBuilder builder)
-  {
-    builder.append("WhoAmIExtendedRequest(requestName=");
-    builder.append(getRequestName());
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder;
-  }
-
-
-
-  private static final class Operation implements
-      ExtendedOperation<WhoAmIRequest, WhoAmIResult>
-  {
-
-    public WhoAmIRequest decodeRequest(String requestName,
-        ByteString requestValue) throws DecodeException
-    {
-      return new WhoAmIRequest();
-    }
-
-
-
-    public WhoAmIResult decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage,
-        String responseName, ByteString responseValue)
-        throws DecodeException
-    {
-      // TODO: Should we check oid is null?
-      String authzId = null;
-      if (responseValue != null)
-      {
-        authzId = responseValue.toString();
-      }
-      return new WhoAmIResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage).setAuthzId(authzId);
-    }
-
-
-
-    public WhoAmIResult decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage)
-    {
-      return new WhoAmIResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-    }
-  }
-
-
-
-  // Singleton instance.
-  private static final Operation OPERATION = new Operation();
-}
diff --git a/sdk/src/org/opends/sdk/extensions/WhoAmIResult.java b/sdk/src/org/opends/sdk/extensions/WhoAmIResult.java
deleted file mode 100644
index 6a77ae9..0000000
--- a/sdk/src/org/opends/sdk/extensions/WhoAmIResult.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.extensions;
-
-
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.responses.AbstractExtendedResult;
-
-
-
-public class WhoAmIResult extends AbstractExtendedResult<WhoAmIResult>
-{
-  private String authzId;
-
-
-
-  public WhoAmIResult(ResultCode resultCode)
-  {
-    super(resultCode);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getResponseName()
-  {
-    // No response name defined.
-    return null;
-  }
-
-
-
-  /**
-   * Get the authzId to return or <code>null</code> if it is not
-   * available.
-   * 
-   * @return The authzID or <code>null</code>.
-   */
-  public String getAuthzId()
-  {
-    return authzId;
-  }
-
-
-
-  public ByteString getResponseValue()
-  {
-    if (authzId != null)
-    {
-      ByteString.valueOf(authzId);
-    }
-    return null;
-  }
-
-
-
-  public WhoAmIResult setAuthzId(String authzId)
-  {
-    this.authzId = authzId;
-    return this;
-  }
-
-
-
-  @Override
-  public String toString()
-  {
-    StringBuilder builder = new StringBuilder();
-    builder.append("WhoAmIExtendedResponse(resultCode=");
-    builder.append(getResultCode());
-    builder.append(", matchedDN=");
-    builder.append(getMatchedDN());
-    builder.append(", diagnosticMessage=");
-    builder.append(getDiagnosticMessage());
-    builder.append(", referrals=");
-    builder.append(getReferralURIs());
-    builder.append(", authzId=");
-    builder.append(authzId);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder.toString();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/extensions/package-info.java b/sdk/src/org/opends/sdk/extensions/package-info.java
deleted file mode 100755
index bd698f1..0000000
--- a/sdk/src/org/opends/sdk/extensions/package-info.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-/**
- * Classes implementing common LDAP extended operations.
- */
-package org.opends.sdk.extensions;
diff --git a/sdk/src/org/opends/sdk/ldap/LDAPConnectionFactory.java b/sdk/src/org/opends/sdk/ldap/LDAPConnectionFactory.java
deleted file mode 100644
index 0c81b73..0000000
--- a/sdk/src/org/opends/sdk/ldap/LDAPConnectionFactory.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.ldap;
-
-
-
-import org.opends.sdk.*;
-import com.sun.opends.sdk.ldap.LDAPConnectionFactoryImpl;
-
-
-
-/**
- * LDAP connection factory implementation.
- */
-public final class LDAPConnectionFactory implements ConnectionFactory
-{
-  // We implement the factory using the pimpl idiom in order have
-  // cleaner Javadoc which does not expose implementation methods from
-  // AbstractConnectionFactory.
-
-  private final LDAPConnectionFactoryImpl impl;
-
-
-
-  /**
-   * Creates a plain LDAP connection to the Directory Server at the
-   * specified host and port address.
-   *
-   * @param host
-   *          The host name.
-   * @param port
-   *          The port number.
-   * @return A connection to the Directory Server at the specified host
-   *         and port address.
-   * @throws ErrorResultException
-   *           If the connection request failed for some reason.
-   * @throws NullPointerException
-   *           If {@code host} was {@code null}.
-   */
-  public static Connection connect(String host, int port)
-      throws ErrorResultException, NullPointerException
-  {
-    return new LDAPConnectionFactory(host, port).getConnection();
-  }
-
-
-
-  /**
-   * Creates a new LDAP connection factory which can be used to create
-   * LDAP connections to the Directory Server at the provided host and
-   * port address using default connection options.
-   *
-   * @param host
-   *          The host name.
-   * @param port
-   *          The port number.
-   * @throws NullPointerException
-   *           If {@code host} was {@code null}.
-   */
-  public LDAPConnectionFactory(String host, int port)
-      throws NullPointerException
-  {
-    this(host, port, LDAPConnectionOptions.defaultOptions());
-  }
-
-
-
-  /**
-   * Creates a new LDAP connection factory which can be used to create
-   * LDAP connections to the Directory Server at the provided host and
-   * port address using provided connection options.
-   *
-   * @param host
-   *          The host name.
-   * @param port
-   *          The port number.
-   * @param options
-   *          The LDAP connection options to use when creating
-   *          connections.
-   * @throws NullPointerException
-   *           If {@code host} or {@code options} was {@code null}.
-   */
-  public LDAPConnectionFactory(String host, int port,
-      LDAPConnectionOptions options) throws NullPointerException
-  {
-    this.impl = new LDAPConnectionFactoryImpl(host, port, options);
-  }
-
-
-
-  public FutureResult<AsynchronousConnection> getAsynchronousConnection(
-      ResultHandler<AsynchronousConnection> handler)
-  {
-    return impl.getAsynchronousConnection(handler);
-  }
-
-
-
-  public Connection getConnection() throws ErrorResultException
-  {
-    return impl.getConnection();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/ldap/LDAPConnectionOptions.java b/sdk/src/org/opends/sdk/ldap/LDAPConnectionOptions.java
deleted file mode 100644
index 1267b96..0000000
--- a/sdk/src/org/opends/sdk/ldap/LDAPConnectionOptions.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.ldap;
-
-
-
-import javax.net.ssl.SSLContext;
-
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * Common connection options for LDAP connections.
- */
-public final class LDAPConnectionOptions
-{
-  private Schema schema = Schema.getDefaultSchema();
-
-  private SSLContext sslContext = null;
-
-  private boolean useStartTLS = false;
-
-
-
-  /**
-   * Creates a copy of the provided connection options.
-   *
-   * @param options
-   *          The options to be copied.
-   * @return The copy of the provided connection options.
-   */
-  public static LDAPConnectionOptions copyOf(
-      LDAPConnectionOptions options)
-  {
-    return defaultOptions().assign(options);
-  }
-
-
-
-  /**
-   * Creates a new set of connection options with default settings. SSL
-   * will not be enabled, nor will key or trust managers be defined.
-   *
-   * @return The new connection options.
-   */
-  public static LDAPConnectionOptions defaultOptions()
-  {
-    return new LDAPConnectionOptions();
-  }
-
-
-
-  // Prevent direct instantiation.
-  private LDAPConnectionOptions()
-  {
-    // Nothing to do.
-  }
-
-
-
-  /**
-   * Returns the schema which will be used to decode responses from the
-   * server. By default the schema returned by
-   * {@link Schema#getDefaultSchema()} will be used.
-   *
-   * @return The schema which will be used to decode responses from the
-   *         server.
-   */
-  public Schema getSchema()
-  {
-    return schema;
-  }
-
-
-
-  /**
-   * Sets the schema which will be used to decode responses from the
-   * server. By default the schema returned by
-   * {@link Schema#getDefaultSchema()} will be used.
-   *
-   * @param schema
-   *          The schema which will be used to decode responses from the
-   *          server.
-   * @return A reference to this LDAP connection options.
-   * @throws NullPointerException
-   *           If {@code schema} was {@code null}.
-   */
-  public LDAPConnectionOptions setSchema(Schema schema)
-      throws NullPointerException
-  {
-    Validator.ensureNotNull(schema);
-    this.schema = schema;
-    return this;
-  }
-
-
-
-  /**
-   * Returns the SSL context which will be used when initiating
-   * connections with the Directory Server. By default no SSL context
-   * will be used, indicating that connections will not be secured. If a
-   * non-{@code null} SSL context is returned then connections will be
-   * secured using either SSL or StartTLS depending on
-   * {@link #useStartTLS()}.
-   *
-   * @return The SSL context which will be used when initiating secure
-   *         connections with the Directory Server, which may be {@code
-   *         null} indicating that connections will not be secured.
-   */
-  public SSLContext getSSLContext()
-  {
-    return sslContext;
-  }
-
-
-
-  /**
-   * Sets the SSL context which will be used when initiating connections
-   * with the Directory Server. By default no SSL context will be used,
-   * indicating that connections will not be secured. If a non-{@code
-   * null} SSL context is returned then connections will be secured
-   * using either SSL or StartTLS depending on {@link #useStartTLS()}.
-   *
-   * @param sslContext
-   *          The SSL context which will be used when initiating secure
-   *          connections with the Directory Server, which may be
-   *          {@code null} indicating that connections will not be
-   *          secured.
-   * @return A reference to this LDAP connection options.
-   */
-  public LDAPConnectionOptions setSSLContext(SSLContext sslContext)
-  {
-    this.sslContext = sslContext;
-    return this;
-  }
-
-
-
-  /**
-   * Indicates whether or not SSL or StartTLS should be used for
-   * securing connections when an SSL context is specified. By default
-   * SSL will be used in preference to StartTLS.
-   *
-   * @return {@code true} if StartTLS should be used for securing
-   *         connections when an SSL context is specified, otherwise
-   *         {@code false} indicating that SSL should be used.
-   */
-  public boolean useStartTLS()
-  {
-    return useStartTLS;
-  }
-
-
-
-  /**
-   * Specifies whether or not SSL or StartTLS should be used for
-   * securing connections when an SSL context is specified. By default
-   * SSL will be used in preference to StartTLS.
-   *
-   * @param useStartTLS
-   *          {@code true} if StartTLS should be used for securing
-   *          connections when an SSL context is specified, otherwise
-   *          {@code false} indicating that SSL should be used.
-   * @return A reference to this LDAP connection options.
-   */
-  public LDAPConnectionOptions setUseStartTLS(boolean useStartTLS)
-  {
-    this.useStartTLS = useStartTLS;
-    return this;
-  }
-
-
-
-  // Assigns the provided options to this set of options.
-  LDAPConnectionOptions assign(LDAPConnectionOptions options)
-  {
-    this.schema = options.schema;
-    this.sslContext = options.sslContext;
-    this.useStartTLS = options.useStartTLS;
-    return this;
-  }
-
-}
diff --git a/sdk/src/org/opends/sdk/ldap/LDAPDecoder.java b/sdk/src/org/opends/sdk/ldap/LDAPDecoder.java
deleted file mode 100644
index 72c25b7..0000000
--- a/sdk/src/org/opends/sdk/ldap/LDAPDecoder.java
+++ /dev/null
@@ -1,1921 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.ldap;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.asn1.ASN1Constants.*;
-import static com.sun.opends.sdk.ldap.LDAPConstants.*;
-
-import java.io.IOException;
-import java.util.logging.Level;
-
-import org.opends.sdk.*;
-import org.opends.sdk.asn1.ASN1Reader;
-import org.opends.sdk.controls.Control;
-import org.opends.sdk.requests.*;
-import org.opends.sdk.responses.*;
-import org.opends.sdk.sasl.GenericSASLBindRequest;
-import org.opends.sdk.schema.Schema;
-
-import com.sun.opends.sdk.util.StaticUtils;
-import com.sun.opends.sdk.ldap.LDAPMessageHandler;
-
-
-/**
- * Static methods for decoding LDAP messages.
- */
-public class LDAPDecoder
-{
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * message.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle a
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  public static void decode(ASN1Reader reader, LDAPMessageHandler handler)
-      throws IOException
-  {
-    reader.readStartSequence();
-    try
-    {
-      int messageID = (int) reader.readInteger();
-      decodeProtocolOp(reader, messageID, handler);
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-  }
-
-
-
-  public static SearchResultEntry decodeEntry(ASN1Reader reader, Schema schema)
-      throws IOException
-  {
-    SearchResultEntry message;
-
-    reader.readStartSequence(OP_TYPE_SEARCH_RESULT_ENTRY);
-    try
-    {
-      String dnString = reader.readOctetStringAsString();
-      DN dn;
-      try
-      {
-        dn = DN.valueOf(dnString, schema);
-      }
-      catch (LocalizedIllegalArgumentException e)
-      {
-        throw DecodeException.error(e.getMessageObject());
-      }
-      message = Responses.newSearchResultEntry(dn);
-
-      reader.readStartSequence();
-      try
-      {
-        while (reader.hasNextElement())
-        {
-          reader.readStartSequence();
-          try
-          {
-            String ads = reader.readOctetStringAsString();
-            AttributeDescription ad;
-            try
-            {
-              ad = AttributeDescription.valueOf(ads, schema);
-            }
-            catch (LocalizedIllegalArgumentException e)
-            {
-              throw DecodeException.error(e.getMessageObject());
-            }
-            Attribute attribute = new LinkedAttribute(ad);
-
-            reader.readStartSet();
-            try
-            {
-              while (reader.hasNextElement())
-              {
-                attribute.add(reader.readOctetString());
-              }
-              message.addAttribute(attribute);
-            }
-            finally
-            {
-              reader.readEndSet();
-            }
-          }
-          finally
-          {
-            reader.readEndSequence();
-          }
-        }
-      }
-      finally
-      {
-        reader.readEndSequence();
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    return message;
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 read as an LDAP
-   * abandon request protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeAbandonRequest(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    int msgToAbandon = (int) reader
-        .readInteger(OP_TYPE_ABANDON_REQUEST);
-    AbandonRequest message = Requests.newAbandonRequest(msgToAbandon);
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP ABANDON REQUEST(messageID=%d, request=%s)",
-          messageID, message));
-    }
-
-    handler.handleAbandonRequest(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP add
-   * request protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeAddRequest(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    AddRequest message;
-    ResolvedSchema resolvedSchema;
-
-    reader.readStartSequence(OP_TYPE_ADD_REQUEST);
-    try
-    {
-      String dnString = reader.readOctetStringAsString();
-      resolvedSchema = handler.resolveSchema(dnString);
-      DN dn = resolvedSchema.getInitialDN();
-      message = Requests.newAddRequest(dn);
-
-      reader.readStartSequence();
-      try
-      {
-        while (reader.hasNextElement())
-        {
-          reader.readStartSequence();
-          try
-          {
-            String ads = reader.readOctetStringAsString();
-            AttributeDescription ad = resolvedSchema
-                .decodeAttributeDescription(ads);
-            Attribute attribute = new LinkedAttribute(ad);
-
-            reader.readStartSet();
-            try
-            {
-              while (reader.hasNextElement())
-              {
-                attribute.add(reader.readOctetString());
-              }
-              message.addAttribute(attribute);
-            }
-            finally
-            {
-              reader.readEndSet();
-            }
-          }
-          finally
-          {
-            reader.readEndSequence();
-          }
-        }
-      }
-      finally
-      {
-        reader.readEndSequence();
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler, resolvedSchema
-        .getSchema());
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP ADD REQUEST(messageID=%d, request=%s)",
-          messageID, message));
-    }
-
-    handler.handleAddRequest(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an add
-   * response protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeAddResult(ASN1Reader reader, int messageID,
-      LDAPMessageHandler handler) throws IOException
-  {
-    Result message;
-
-    reader.readStartSequence(OP_TYPE_ADD_RESPONSE);
-    try
-    {
-      ResultCode resultCode = ResultCode.valueOf(reader
-          .readEnumerated());
-      String matchedDN = reader.readOctetStringAsString();
-      String diagnosticMessage = reader.readOctetStringAsString();
-      message = Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-      decodeResponseReferrals(reader, message);
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP ADD RESULT(messageID=%d, result=%s)", messageID,
-          message));
-    }
-
-    handler.handleAddResult(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 read as an LDAP bind
-   * request protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeBindRequest(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    reader.readStartSequence(OP_TYPE_BIND_REQUEST);
-    try
-    {
-      int protocolVersion = (int) reader.readInteger();
-
-      String dnString = reader.readOctetStringAsString();
-      ResolvedSchema resolvedSchema = handler.resolveSchema(dnString);
-      DN dn = resolvedSchema.getInitialDN();
-
-      byte type = reader.peekType();
-
-      switch (type)
-      {
-      case TYPE_AUTHENTICATION_SIMPLE:
-        ByteString simplePassword = reader
-            .readOctetString(TYPE_AUTHENTICATION_SIMPLE);
-
-        SimpleBindRequest simpleBindMessage = Requests.newSimpleBindRequest(dn, simplePassword);
-
-        decodeControls(reader, simpleBindMessage, messageID, handler,
-            resolvedSchema.getSchema());
-
-        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-        {
-          StaticUtils.DEBUG_LOG
-              .finer(String
-                  .format(
-                      "DECODE LDAP BIND REQUEST(messageID=%d, auth=simple, request=%s)",
-                      messageID, simpleBindMessage));
-        }
-
-        handler.handleBindRequest(messageID, protocolVersion,
-            simpleBindMessage);
-        break;
-      case TYPE_AUTHENTICATION_SASL:
-        String saslMechanism;
-        ByteString saslCredentials;
-
-        reader.readStartSequence(TYPE_AUTHENTICATION_SASL);
-        try
-        {
-          saslMechanism = reader.readOctetStringAsString();
-          if (reader.hasNextElement()
-              && (reader.peekType() == UNIVERSAL_OCTET_STRING_TYPE))
-          {
-            saslCredentials = reader.readOctetString();
-          }
-          else
-          {
-            saslCredentials = ByteString.empty();
-          }
-        }
-        finally
-        {
-          reader.readEndSequence();
-        }
-
-        GenericSASLBindRequest rawSASLBindMessage = new GenericSASLBindRequest(
-            saslMechanism, saslCredentials);
-
-        // TODO: we can ignore the bind DN for SASL bind requests
-        // according to the RFC.
-        //
-        // rawSASLBindMessage.setName(dn);
-
-        decodeControls(reader, rawSASLBindMessage, messageID, handler,
-            resolvedSchema.getSchema());
-
-        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-        {
-          StaticUtils.DEBUG_LOG
-              .finer(String
-                  .format(
-                      "DECODE LDAP BIND REQUEST(messageID=%d, auth=SASL, request=%s)",
-                      messageID, rawSASLBindMessage));
-        }
-
-        handler.handleBindRequest(messageID, protocolVersion,
-            rawSASLBindMessage);
-        break;
-      default:
-        ByteString unknownAuthBytes = reader.readOctetString(type);
-
-        GenericBindRequest rawUnknownBindMessage = Requests.newGenericBindRequest(dn, type, unknownAuthBytes);
-
-        decodeControls(reader, rawUnknownBindMessage, messageID,
-            handler, resolvedSchema.getSchema());
-
-        if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-        {
-          StaticUtils.DEBUG_LOG
-              .finer(String
-                  .format(
-                      "DECODE LDAP BIND REQUEST(messageID=%d, auth=0x%x, request=%s)",
-                      messageID, rawUnknownBindMessage
-                          .getAuthenticationType(),
-                      rawUnknownBindMessage));
-        }
-
-        handler.handleBindRequest(messageID, protocolVersion,
-            rawUnknownBindMessage);
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a bind
-   * response protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeBindResult(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    BindResult message;
-
-    reader.readStartSequence(OP_TYPE_BIND_RESPONSE);
-    try
-    {
-      ResultCode resultCode = ResultCode.valueOf(reader
-          .readEnumerated());
-      String matchedDN = reader.readOctetStringAsString();
-      String diagnosticMessage = reader.readOctetStringAsString();
-      message = Responses.newBindResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-      decodeResponseReferrals(reader, message);
-      if (reader.hasNextElement()
-          && (reader.peekType() == TYPE_SERVER_SASL_CREDENTIALS))
-      {
-        message.setServerSASLCredentials(reader
-            .readOctetString(TYPE_SERVER_SASL_CREDENTIALS));
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP BIND RESULT(messageID=%d, result=%s)",
-          messageID, message));
-    }
-
-    handler.handleBindResult(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * compare request protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeCompareRequest(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    DN dn;
-    AttributeDescription ad;
-    ByteString assertionValue;
-    ResolvedSchema resolvedSchema;
-
-    reader.readStartSequence(OP_TYPE_COMPARE_REQUEST);
-    try
-    {
-      String dnString = reader.readOctetStringAsString();
-      resolvedSchema = handler.resolveSchema(dnString);
-      dn = resolvedSchema.getInitialDN();
-
-      reader.readStartSequence();
-      try
-      {
-        String ads = reader.readOctetStringAsString();
-        ad = resolvedSchema.decodeAttributeDescription(ads);
-        assertionValue = reader.readOctetString();
-      }
-      finally
-      {
-        reader.readEndSequence();
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    CompareRequest message = Requests.newCompareRequest(dn, ad, assertionValue);
-    decodeControls(reader, message, messageID, handler, resolvedSchema
-        .getSchema());
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP COMPARE REQUEST(messageID=%d, request=%s)",
-          messageID, message));
-    }
-
-    handler.handleCompareRequest(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a compare
-   * response protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeCompareResult(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    CompareResult message;
-
-    reader.readStartSequence(OP_TYPE_COMPARE_RESPONSE);
-    try
-    {
-      ResultCode resultCode = ResultCode.valueOf(reader
-          .readEnumerated());
-      String matchedDN = reader.readOctetStringAsString();
-      String diagnosticMessage = reader.readOctetStringAsString();
-      message = Responses.newCompareResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-      decodeResponseReferrals(reader, message);
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP COMPARE RESULT(messageID=%d, result=%s)",
-          messageID, message));
-    }
-
-    handler.handleCompareResult(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * control.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param request
-   *          The decoded request to decode controls for.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will decode the
-   *          control.
-   * @param schema
-   *          The schema to use when decoding control.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeControl(ASN1Reader reader, Request request,
-      int messageID, LDAPMessageHandler handler, Schema schema)
-      throws IOException
-  {
-    String oid;
-    boolean isCritical;
-    ByteString value;
-
-    reader.readStartSequence();
-    try
-    {
-      oid = reader.readOctetStringAsString();
-      isCritical = false;
-      value = null;
-      if (reader.hasNextElement()
-          && (reader.peekType() == UNIVERSAL_BOOLEAN_TYPE))
-      {
-        isCritical = reader.readBoolean();
-      }
-      if (reader.hasNextElement()
-          && (reader.peekType() == UNIVERSAL_OCTET_STRING_TYPE))
-      {
-        value = reader.readOctetString();
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    try
-    {
-      Control c = handler.decodeRequestControl(messageID, oid,
-          isCritical, value, schema);
-      request.addControl(c);
-    }
-    catch (DecodeException e)
-    {
-      if (isCritical)
-      {
-        if (e.isFatal())
-        {
-          throw DecodeException.error(e.getMessageObject(), e
-              .getCause());
-        }
-        else
-        {
-          // Exceptions encountered when decoding controls are never
-          // fatal.
-          throw e;
-        }
-      }
-    }
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * control.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param response
-   *          The decoded message to decode controls for.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will decode the
-   *          control.
-   * @param schema
-   *          The schema to use when decoding control.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeControl(ASN1Reader reader,
-      Response response, int messageID, LDAPMessageHandler handler,
-      Schema schema) throws IOException
-  {
-    String oid;
-    boolean isCritical;
-    ByteString value;
-
-    reader.readStartSequence();
-    try
-    {
-      oid = reader.readOctetStringAsString();
-      isCritical = false;
-      value = null;
-      if (reader.hasNextElement()
-          && (reader.peekType() == UNIVERSAL_BOOLEAN_TYPE))
-      {
-        isCritical = reader.readBoolean();
-      }
-      if (reader.hasNextElement()
-          && (reader.peekType() == UNIVERSAL_OCTET_STRING_TYPE))
-      {
-        value = reader.readOctetString();
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    try
-    {
-      Control c = handler.decodeResponseControl(messageID, oid,
-          isCritical, value, schema);
-      response.addControl(c);
-    }
-    catch (DecodeException e)
-    {
-      if (isCritical)
-      {
-        if (e.isFatal())
-        {
-          throw DecodeException.error(e.getMessageObject(), e
-              .getCause());
-        }
-        else
-        {
-          // Exceptions encountered when decoding controls are never
-          // fatal.
-          throw e;
-        }
-      }
-    }
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a set of
-   * controls using the default schema.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param request
-   *          The decoded message to decode controls for.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will decode the
-   *          controls.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeControls(ASN1Reader reader,
-      Request request, int messageID, LDAPMessageHandler handler)
-      throws IOException
-  {
-    decodeControls(reader, request, messageID, handler, handler
-        .getDefaultSchema());
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a set of
-   * controls.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param request
-   *          The decoded message to decode controls for.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will decode the
-   *          controls.
-   * @param schema
-   *          The schema to use when decoding controls.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeControls(ASN1Reader reader,
-      Request request, int messageID, LDAPMessageHandler handler,
-      Schema schema) throws IOException
-  {
-    if (reader.hasNextElement()
-        && (reader.peekType() == TYPE_CONTROL_SEQUENCE))
-    {
-      reader.readStartSequence(TYPE_CONTROL_SEQUENCE);
-      try
-      {
-        while (reader.hasNextElement())
-        {
-          decodeControl(reader, request, messageID, handler, schema);
-        }
-      }
-      finally
-      {
-        reader.readEndSequence();
-      }
-    }
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a set of
-   * controls using the default schema.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param response
-   *          The decoded message to decode controls for.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will decode the
-   *          controls.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeControls(ASN1Reader reader,
-      Response response, int messageID, LDAPMessageHandler handler)
-      throws IOException
-  {
-    decodeControls(reader, response, messageID, handler, handler
-        .getDefaultSchema());
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a set of
-   * controls.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param response
-   *          The decoded message to decode controls for.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will decode the
-   *          controls.
-   * @param schema
-   *          The schema to use when decoding control.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeControls(ASN1Reader reader,
-      Response response, int messageID, LDAPMessageHandler handler,
-      Schema schema) throws IOException
-  {
-    if (reader.hasNextElement()
-        && (reader.peekType() == TYPE_CONTROL_SEQUENCE))
-    {
-      reader.readStartSequence(TYPE_CONTROL_SEQUENCE);
-      try
-      {
-        while (reader.hasNextElement())
-        {
-          decodeControl(reader, response, messageID, handler, schema);
-        }
-      }
-      finally
-      {
-        reader.readEndSequence();
-      }
-    }
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * delete request protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeDeleteRequest(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    String dnString = reader
-        .readOctetStringAsString(OP_TYPE_DELETE_REQUEST);
-    ResolvedSchema resolvedSchema = handler.resolveSchema(dnString);
-    DN dn = resolvedSchema.getInitialDN();
-    DeleteRequest message = Requests.newDeleteRequest(dn);
-
-    decodeControls(reader, message, messageID, handler, resolvedSchema
-        .getSchema());
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP DELETE REQUEST(messageID=%d, request=%s)",
-          messageID, message));
-    }
-
-    handler.handleDeleteRequest(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a delete
-   * response protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeDeleteResult(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    Result message;
-
-    reader.readStartSequence(OP_TYPE_DELETE_RESPONSE);
-    try
-    {
-      ResultCode resultCode = ResultCode.valueOf(reader
-          .readEnumerated());
-      String matchedDN = reader.readOctetStringAsString();
-      String diagnosticMessage = reader.readOctetStringAsString();
-      message = Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-      decodeResponseReferrals(reader, message);
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP DELETE RESULT(messageID=%d, result=%s)",
-          messageID, message));
-    }
-
-    handler.handleDeleteResult(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * extended request protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeExtendedRequest(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    String oid;
-    ByteString value;
-
-    reader.readStartSequence(OP_TYPE_EXTENDED_REQUEST);
-    try
-    {
-      oid = reader.readOctetStringAsString(TYPE_EXTENDED_REQUEST_OID);
-      value = null;
-      if (reader.hasNextElement()
-          && (reader.peekType() == TYPE_EXTENDED_REQUEST_VALUE))
-      {
-        value = reader.readOctetString(TYPE_EXTENDED_REQUEST_VALUE);
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    GenericExtendedRequest message = Requests.newGenericExtendedRequest(oid, value);
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP EXTENDED REQUEST(messageID=%d, request=%s)",
-          messageID, message));
-    }
-
-    handler.handleExtendedRequest(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a extended
-   * response protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeExtendedResult(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-
-    GenericExtendedResult message;
-
-    reader.readStartSequence(OP_TYPE_EXTENDED_RESPONSE);
-    try
-    {
-      ResultCode resultCode = ResultCode.valueOf(reader
-          .readEnumerated());
-      String matchedDN = reader.readOctetStringAsString();
-      String diagnosticMessage = reader.readOctetStringAsString();
-      message = Responses.newGenericExtendedResult(resultCode).setMatchedDN(
-          matchedDN).setDiagnosticMessage(diagnosticMessage);
-      decodeResponseReferrals(reader, message);
-      if (reader.hasNextElement()
-          && (reader.peekType() == TYPE_EXTENDED_RESPONSE_OID))
-      {
-        message.setResponseName(reader
-            .readOctetStringAsString(TYPE_EXTENDED_RESPONSE_OID));
-      }
-      if (reader.hasNextElement()
-          && (reader.peekType() == TYPE_EXTENDED_RESPONSE_VALUE))
-      {
-        message.setResponseValue(reader
-            .readOctetString(TYPE_EXTENDED_RESPONSE_VALUE));
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP EXTENDED RESULT(messageID=%d, result=%s)",
-          messageID, message));
-    }
-
-    handler.handleExtendedResult(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * intermediate response protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeIntermediateResponse(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    GenericIntermediateResponse message;
-
-    reader.readStartSequence(OP_TYPE_INTERMEDIATE_RESPONSE);
-    try
-    {
-      message = Responses.newGenericIntermediateResponse();
-      if (reader.hasNextElement()
-          && (reader.peekType() == TYPE_INTERMEDIATE_RESPONSE_OID))
-      {
-        message.setResponseName(reader
-            .readOctetStringAsString(TYPE_INTERMEDIATE_RESPONSE_OID));
-      }
-      if (reader.hasNextElement()
-          && (reader.peekType() == TYPE_INTERMEDIATE_RESPONSE_VALUE))
-      {
-        message.setResponseValue(reader
-            .readOctetString(TYPE_INTERMEDIATE_RESPONSE_VALUE));
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG
-          .finer(String
-              .format(
-                  "DECODE LDAP INTERMEDIATE RESPONSE(messageID=%d, response=%s)",
-                  messageID, message));
-    }
-
-    handler.handleIntermediateResponse(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a modify DN
-   * request protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeModifyDNRequest(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    ModifyDNRequest message;
-    ResolvedSchema resolvedSchema;
-
-    reader.readStartSequence(OP_TYPE_MODIFY_DN_REQUEST);
-    try
-    {
-      String dnString = reader.readOctetStringAsString();
-      resolvedSchema = handler.resolveSchema(dnString);
-      DN dn = resolvedSchema.getInitialDN();
-
-      String newRDNString = reader.readOctetStringAsString();
-      RDN newRDN = resolvedSchema.decodeRDN(newRDNString);
-
-      message = Requests.newModifyDNRequest(dn, newRDN);
-
-      message.setDeleteOldRDN(reader.readBoolean());
-
-      if (reader.hasNextElement()
-          && (reader.peekType() == TYPE_MODIFY_DN_NEW_SUPERIOR))
-      {
-        String newSuperiorString = reader
-            .readOctetStringAsString(TYPE_MODIFY_DN_NEW_SUPERIOR);
-        DN newSuperior = resolvedSchema.decodeDN(newSuperiorString);
-        message.setNewSuperior(newSuperior);
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler, resolvedSchema
-        .getSchema());
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP MODIFY DN REQUEST(messageID=%d, request=%s)",
-          messageID, message));
-    }
-
-    handler.handleModifyDNRequest(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a modify DN
-   * response protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeModifyDNResult(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    Result message;
-
-    reader.readStartSequence(OP_TYPE_MODIFY_DN_RESPONSE);
-    try
-    {
-      ResultCode resultCode = ResultCode.valueOf(reader
-          .readEnumerated());
-      String matchedDN = reader.readOctetStringAsString();
-      String diagnosticMessage = reader.readOctetStringAsString();
-      message = Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-      decodeResponseReferrals(reader, message);
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP MODIFY DN RESULT(messageID=%d, result=%s)",
-          messageID, message));
-    }
-
-    handler.handleModifyDNResult(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * modify request protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeModifyRequest(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    ModifyRequest message;
-    ResolvedSchema resolvedSchema;
-
-    reader.readStartSequence(OP_TYPE_MODIFY_REQUEST);
-    try
-    {
-      String dnString = reader.readOctetStringAsString();
-      resolvedSchema = handler.resolveSchema(dnString);
-      DN dn = resolvedSchema.getInitialDN();
-      message = Requests.newModifyRequest(dn);
-
-      reader.readStartSequence();
-      try
-      {
-        while (reader.hasNextElement())
-        {
-          reader.readStartSequence();
-          try
-          {
-            int typeIntValue = reader.readEnumerated();
-            ModificationType type = ModificationType
-                .valueOf(typeIntValue);
-            if (type == null)
-            {
-              throw DecodeException
-                  .error(ERR_LDAP_MODIFICATION_DECODE_INVALID_MOD_TYPE
-                      .get(typeIntValue));
-            }
-            reader.readStartSequence();
-            try
-            {
-              String attributeDescription = reader
-                  .readOctetStringAsString();
-              Attribute attribute = new LinkedAttribute(resolvedSchema
-                  .decodeAttributeDescription(attributeDescription));
-
-              reader.readStartSet();
-              try
-              {
-                while (reader.hasNextElement())
-                {
-                  attribute.add(reader.readOctetString());
-                }
-                message.addChange(new Change(type, attribute));
-              }
-              finally
-              {
-                reader.readEndSet();
-              }
-            }
-            finally
-            {
-              reader.readEndSequence();
-            }
-          }
-          finally
-          {
-            reader.readEndSequence();
-          }
-        }
-      }
-      finally
-      {
-        reader.readEndSequence();
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler, resolvedSchema
-        .getSchema());
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP MODIFY REQUEST(messageID=%d, request=%s)",
-          messageID, message));
-    }
-
-    handler.handleModifyRequest(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a modify
-   * response protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeModifyResult(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    Result message;
-
-    reader.readStartSequence(OP_TYPE_MODIFY_RESPONSE);
-    try
-    {
-      ResultCode resultCode = ResultCode.valueOf(reader
-          .readEnumerated());
-      String matchedDN = reader.readOctetStringAsString();
-      String diagnosticMessage = reader.readOctetStringAsString();
-      message = Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-      decodeResponseReferrals(reader, message);
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP MODIFY RESULT(messageID=%d, result=%s)",
-          messageID, message));
-    }
-
-    handler.handleModifyResult(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeProtocolOp(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    byte type = reader.peekType();
-
-    switch (type)
-    {
-    case OP_TYPE_UNBIND_REQUEST: // 0x42
-      decodeUnbindRequest(reader, messageID, handler);
-      break;
-    case 0x43: // 0x43
-    case 0x44: // 0x44
-    case 0x45: // 0x45
-    case 0x46: // 0x46
-    case 0x47: // 0x47
-    case 0x48: // 0x48
-    case 0x49: // 0x49
-      handler.handleUnrecognizedMessage(messageID, type, reader
-          .readOctetString(type));
-      break;
-    case OP_TYPE_DELETE_REQUEST: // 0x4A
-      decodeDeleteRequest(reader, messageID, handler);
-      break;
-    case 0x4B: // 0x4B
-    case 0x4C: // 0x4C
-    case 0x4D: // 0x4D
-    case 0x4E: // 0x4E
-    case 0x4F: // 0x4F
-      handler.handleUnrecognizedMessage(messageID, type, reader
-          .readOctetString(type));
-      break;
-    case OP_TYPE_ABANDON_REQUEST: // 0x50
-      decodeAbandonRequest(reader, messageID, handler);
-      break;
-    case 0x51: // 0x51
-    case 0x52: // 0x52
-    case 0x53: // 0x53
-    case 0x54: // 0x54
-    case 0x55: // 0x55
-    case 0x56: // 0x56
-    case 0x57: // 0x57
-    case 0x58: // 0x58
-    case 0x59: // 0x59
-    case 0x5A: // 0x5A
-    case 0x5B: // 0x5B
-    case 0x5C: // 0x5C
-    case 0x5D: // 0x5D
-    case 0x5E: // 0x5E
-    case 0x5F: // 0x5F
-      handler.handleUnrecognizedMessage(messageID, type, reader
-          .readOctetString(type));
-      break;
-    case OP_TYPE_BIND_REQUEST: // 0x60
-      decodeBindRequest(reader, messageID, handler);
-      break;
-    case OP_TYPE_BIND_RESPONSE: // 0x61
-      decodeBindResult(reader, messageID, handler);
-      break;
-    case 0x62: // 0x62
-      handler.handleUnrecognizedMessage(messageID, type, reader
-          .readOctetString(type));
-      break;
-    case OP_TYPE_SEARCH_REQUEST: // 0x63
-      decodeSearchRequest(reader, messageID, handler);
-      break;
-    case OP_TYPE_SEARCH_RESULT_ENTRY: // 0x64
-      decodeSearchResultEntry(reader, messageID, handler);
-      break;
-    case OP_TYPE_SEARCH_RESULT_DONE: // 0x65
-      decodeSearchResult(reader, messageID, handler);
-      break;
-    case OP_TYPE_MODIFY_REQUEST: // 0x66
-      decodeModifyRequest(reader, messageID, handler);
-      break;
-    case OP_TYPE_MODIFY_RESPONSE: // 0x67
-      decodeModifyResult(reader, messageID, handler);
-      break;
-    case OP_TYPE_ADD_REQUEST: // 0x68
-      decodeAddRequest(reader, messageID, handler);
-      break;
-    case OP_TYPE_ADD_RESPONSE: // 0x69
-      decodeAddResult(reader, messageID, handler);
-      break;
-    case 0x6A: // 0x6A
-      handler.handleUnrecognizedMessage(messageID, type, reader
-          .readOctetString(type));
-      break;
-    case OP_TYPE_DELETE_RESPONSE: // 0x6B
-      decodeDeleteResult(reader, messageID, handler);
-      break;
-    case OP_TYPE_MODIFY_DN_REQUEST: // 0x6C
-      decodeModifyDNRequest(reader, messageID, handler);
-      break;
-    case OP_TYPE_MODIFY_DN_RESPONSE: // 0x6D
-      decodeModifyDNResult(reader, messageID, handler);
-      break;
-    case OP_TYPE_COMPARE_REQUEST: // 0x6E
-      decodeCompareRequest(reader, messageID, handler);
-      break;
-    case OP_TYPE_COMPARE_RESPONSE: // 0x6F
-      decodeCompareResult(reader, messageID, handler);
-      break;
-    case 0x70: // 0x70
-    case 0x71: // 0x71
-    case 0x72: // 0x72
-      handler.handleUnrecognizedMessage(messageID, type, reader
-          .readOctetString(type));
-      break;
-    case OP_TYPE_SEARCH_RESULT_REFERENCE: // 0x73
-      decodeSearchResultReference(reader, messageID, handler);
-      break;
-    case 0x74: // 0x74
-    case 0x75: // 0x75
-    case 0x76: // 0x76
-      handler.handleUnrecognizedMessage(messageID, type, reader
-          .readOctetString(type));
-      break;
-    case OP_TYPE_EXTENDED_REQUEST: // 0x77
-      decodeExtendedRequest(reader, messageID, handler);
-      break;
-    case OP_TYPE_EXTENDED_RESPONSE: // 0x78
-      decodeExtendedResult(reader, messageID, handler);
-      break;
-    case OP_TYPE_INTERMEDIATE_RESPONSE: // 0x79
-      decodeIntermediateResponse(reader, messageID, handler);
-      break;
-    default:
-      handler.handleUnrecognizedMessage(messageID, type, reader
-          .readOctetString(type));
-      break;
-    }
-  }
-
-
-
-  private static void decodeResponseReferrals(ASN1Reader reader,
-      Result message) throws IOException
-  {
-    if (reader.hasNextElement()
-        && (reader.peekType() == TYPE_REFERRAL_SEQUENCE))
-    {
-      reader.readStartSequence(TYPE_REFERRAL_SEQUENCE);
-      try
-      {
-        // Should have at least 1.
-        do
-        {
-          message.addReferralURI((reader.readOctetStringAsString()));
-        } while (reader.hasNextElement());
-      }
-      finally
-      {
-        reader.readEndSequence();
-      }
-    }
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a search
-   * result done protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeSearchResult(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-
-    Result message;
-
-    reader.readStartSequence(OP_TYPE_SEARCH_RESULT_DONE);
-    try
-    {
-      ResultCode resultCode = ResultCode.valueOf(reader
-          .readEnumerated());
-      String matchedDN = reader.readOctetStringAsString();
-      String diagnosticMessage = reader.readOctetStringAsString();
-      message = Responses.newResult(resultCode).setMatchedDN(matchedDN)
-          .setDiagnosticMessage(diagnosticMessage);
-      decodeResponseReferrals(reader, message);
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP SEARCH RESULT(messageID=%d, result=%s)",
-          messageID, message));
-    }
-
-    handler.handleSearchResult(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * search result entry protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeSearchResultEntry(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    SearchResultEntry message;
-    ResolvedSchema resolvedSchema;
-
-    reader.readStartSequence(OP_TYPE_SEARCH_RESULT_ENTRY);
-    try
-    {
-      String dnString = reader.readOctetStringAsString();
-      resolvedSchema = handler.resolveSchema(dnString);
-      DN dn = resolvedSchema.getInitialDN();
-      message = Responses.newSearchResultEntry(dn);
-
-      reader.readStartSequence();
-      try
-      {
-        while (reader.hasNextElement())
-        {
-          reader.readStartSequence();
-          try
-          {
-            String ads = reader.readOctetStringAsString();
-            AttributeDescription ad = resolvedSchema
-                .decodeAttributeDescription(ads);
-            Attribute attribute = new LinkedAttribute(ad);
-
-            reader.readStartSet();
-            try
-            {
-              while (reader.hasNextElement())
-              {
-                attribute.add(reader.readOctetString());
-              }
-              message.addAttribute(attribute);
-            }
-            finally
-            {
-              reader.readEndSet();
-            }
-          }
-          finally
-          {
-            reader.readEndSequence();
-          }
-        }
-      }
-      finally
-      {
-        reader.readEndSequence();
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler, resolvedSchema
-        .getSchema());
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP SEARCH RESULT ENTRY(messageID=%d, entry=%s)",
-          messageID, message));
-    }
-
-    handler.handleSearchResultEntry(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as a search
-   * result reference protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeSearchResultReference(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    SearchResultReference message;
-
-    reader.readStartSequence(OP_TYPE_SEARCH_RESULT_REFERENCE);
-    try
-    {
-      message = Responses.newSearchResultReference(reader
-          .readOctetStringAsString());
-      while (reader.hasNextElement())
-      {
-        message.addURI(reader.readOctetStringAsString());
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG
-          .finer(String
-              .format(
-                  "DECODE LDAP SEARCH RESULT REFERENCE(messageID=%d, reference=%s)",
-                  messageID, message));
-    }
-
-    handler.handleSearchResultReference(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 reader as an LDAP
-   * search request protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeSearchRequest(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    SearchRequest message;
-    ResolvedSchema resolvedSchema;
-
-    reader.readStartSequence(OP_TYPE_SEARCH_REQUEST);
-    try
-    {
-      String baseDNString = reader.readOctetStringAsString();
-      resolvedSchema = handler.resolveSchema(baseDNString);
-      DN baseDN = resolvedSchema.getInitialDN();
-
-      int scopeIntValue = reader.readEnumerated();
-      SearchScope scope = SearchScope.valueOf(scopeIntValue);
-      if (scope == null)
-      {
-        throw DecodeException
-            .error(ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_SCOPE
-                .get(scopeIntValue));
-      }
-
-      int dereferencePolicyIntValue = reader.readEnumerated();
-      DereferenceAliasesPolicy dereferencePolicy = DereferenceAliasesPolicy
-          .valueOf(dereferencePolicyIntValue);
-      if (dereferencePolicy == null)
-      {
-        throw DecodeException
-            .error(ERR_LDAP_SEARCH_REQUEST_DECODE_INVALID_DEREF
-                .get(dereferencePolicyIntValue));
-      }
-
-      int sizeLimit = (int) reader.readInteger();
-      int timeLimit = (int) reader.readInteger();
-      boolean typesOnly = reader.readBoolean();
-      Filter filter = LDAPUtils.decodeFilter(reader);
-
-      message = Requests.newSearchRequest(baseDN, scope, filter);
-      message.setDereferenceAliasesPolicy(dereferencePolicy);
-      try
-      {
-        message.setTimeLimit(timeLimit);
-        message.setSizeLimit(sizeLimit);
-      }
-      catch (LocalizedIllegalArgumentException e)
-      {
-        throw DecodeException.error(e.getMessageObject());
-      }
-      message.setTypesOnly(typesOnly);
-
-      reader.readStartSequence();
-      try
-      {
-        while (reader.hasNextElement())
-        {
-          message.addAttribute(reader.readOctetStringAsString());
-        }
-      }
-      finally
-      {
-        reader.readEndSequence();
-      }
-    }
-    finally
-    {
-      reader.readEndSequence();
-    }
-
-    decodeControls(reader, message, messageID, handler, resolvedSchema
-        .getSchema());
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP SEARCH REQUEST(messageID=%d, request=%s)",
-          messageID, message));
-    }
-
-    handler.handleSearchRequest(messageID, message);
-  }
-
-
-
-  /**
-   * Decodes the elements from the provided ASN.1 read as an LDAP unbind
-   * request protocol op.
-   *
-   * @param reader
-   *          The ASN.1 reader.
-   * @param messageID
-   *          The decoded message ID for this message.
-   * @param handler
-   *          The <code>LDAPMessageHandler</code> that will handle this
-   *          decoded message.
-   * @throws IOException
-   *           If an error occurred while reading bytes to decode.
-   */
-  private static void decodeUnbindRequest(ASN1Reader reader,
-      int messageID, LDAPMessageHandler handler) throws IOException
-  {
-    UnbindRequest message;
-    reader.readNull(OP_TYPE_UNBIND_REQUEST);
-    message = Requests.newUnbindRequest();
-
-    decodeControls(reader, message, messageID, handler);
-
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "DECODE LDAP UNBIND REQUEST(messageID=%d, request=%s)",
-          messageID, message));
-    }
-
-    handler.handleUnbindRequest(messageID, message);
-  }
-}
diff --git a/sdk/src/org/opends/sdk/ldap/LDAPEncoder.java b/sdk/src/org/opends/sdk/ldap/LDAPEncoder.java
deleted file mode 100644
index da5438d..0000000
--- a/sdk/src/org/opends/sdk/ldap/LDAPEncoder.java
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.ldap;
-
-
-
-import static com.sun.opends.sdk.ldap.LDAPConstants.*;
-
-import java.io.IOException;
-import java.util.logging.Level;
-
-import org.opends.sdk.Attribute;
-import org.opends.sdk.ByteString;
-import org.opends.sdk.Change;
-import org.opends.sdk.DN;
-import org.opends.sdk.asn1.ASN1Writer;
-import org.opends.sdk.controls.Control;
-import org.opends.sdk.requests.*;
-import org.opends.sdk.responses.*;
-import org.opends.sdk.sasl.SASLBindRequest;
-
-import com.sun.opends.sdk.util.StaticUtils;
-
-
-
-/**
- * Static methods for encoding LDAP messages.
- */
-public final class LDAPEncoder
-{
-  public static void encodeControl(ASN1Writer writer, Control control)
-      throws IOException
-  {
-    writer.writeStartSequence();
-    writer.writeOctetString(control.getOID());
-    if (control.isCritical())
-    {
-      writer.writeBoolean(control.isCritical());
-    }
-    if (control.getValue() != null)
-    {
-      writer.writeOctetString(control.getValue());
-    }
-    writer.writeEndSequence();
-  }
-
-
-
-  public static void encodeEntry(ASN1Writer writer,
-      SearchResultEntry searchResultEntry) throws IOException
-  {
-    writer.writeStartSequence(OP_TYPE_SEARCH_RESULT_ENTRY);
-    writer.writeOctetString(searchResultEntry.getName().toString());
-
-    writer.writeStartSequence();
-    for (Attribute attr : searchResultEntry.getAttributes())
-    {
-      encodeAttribute(writer, attr);
-    }
-    writer.writeEndSequence();
-    writer.writeEndSequence();
-  }
-
-
-
-  public static void encodeAbandonRequest(ASN1Writer writer, int messageID,
-      AbandonRequest request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP ABANDON REQUEST(messageID=%d, request=%s)",
-          messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer
-        .writeInteger(OP_TYPE_ABANDON_REQUEST, request.getMessageID());
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeAddRequest(ASN1Writer writer, int messageID,
-      AddRequest request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP ADD REQUEST(messageID=%d, request=%s)",
-          messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_ADD_REQUEST);
-    writer.writeOctetString(request.getName().toString());
-
-    // Write the attributes
-    writer.writeStartSequence();
-    for (Attribute attr : request.getAttributes())
-    {
-      encodeAttribute(writer, attr);
-    }
-    writer.writeEndSequence();
-
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeCompareRequest(ASN1Writer writer, int messageID,
-      CompareRequest request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP COMPARE REQUEST(messageID=%d, request=%s)",
-          messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_COMPARE_REQUEST);
-    writer.writeOctetString(request.getName().toString());
-
-    writer.writeStartSequence();
-    writer.writeOctetString(request.getAttributeDescription()
-        .toString());
-    writer.writeOctetString(request.getAssertionValue());
-    writer.writeEndSequence();
-
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeDeleteRequest(ASN1Writer writer, int messageID,
-      DeleteRequest request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP DELETE REQUEST(messageID=%d, request=%s)",
-          messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeOctetString(OP_TYPE_DELETE_REQUEST, request.getName()
-        .toString());
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeExtendedRequest(ASN1Writer writer, int messageID,
-      ExtendedRequest<?> request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP EXTENDED REQUEST(messageID=%d, request=%s)",
-          messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_EXTENDED_REQUEST);
-    writer.writeOctetString(TYPE_EXTENDED_REQUEST_OID, request
-        .getRequestName());
-
-    ByteString requestValue = request.getRequestValue();
-    if (requestValue != null)
-    {
-      writer
-          .writeOctetString(TYPE_EXTENDED_REQUEST_VALUE, requestValue);
-    }
-
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeBindRequest(ASN1Writer writer, int messageID,
-      int version, GenericBindRequest request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG
-          .finer(String
-              .format(
-                  "ENCODE LDAP BIND REQUEST(messageID=%d, auth=0x%x, request=%s)",
-                  messageID, request.getAuthenticationType(), request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_BIND_REQUEST);
-
-    writer.writeInteger(version);
-    writer.writeOctetString(request.getName().toString());
-
-    writer.writeOctetString(request.getAuthenticationType(), request
-        .getAuthenticationValue());
-
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeBindRequest(ASN1Writer writer, int messageID,
-      int version, SASLBindRequest<?> request,
-      ByteString saslCredentials) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG
-          .finer(String
-              .format(
-                  "ENCODE LDAP BIND REQUEST(messageID=%d, auth=SASL, request=%s)",
-                  messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_BIND_REQUEST);
-
-    writer.writeInteger(version);
-    writer.writeOctetString(request.getName().toString());
-
-    writer.writeStartSequence(TYPE_AUTHENTICATION_SASL);
-    writer.writeOctetString(request.getSASLMechanism());
-    if (saslCredentials != null)
-    {
-      writer.writeOctetString(saslCredentials);
-    }
-    writer.writeEndSequence();
-
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeBindRequest(ASN1Writer writer, int messageID,
-      int version, SimpleBindRequest request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG
-          .finer(String
-              .format(
-                  "ENCODE LDAP BIND REQUEST(messageID=%d, auth=simple, request=%s)",
-                  messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_BIND_REQUEST);
-
-    writer.writeInteger(version);
-    writer.writeOctetString(request.getName().toString());
-    writer.writeOctetString(TYPE_AUTHENTICATION_SIMPLE, request
-        .getPassword());
-
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeModifyDNRequest(ASN1Writer writer, int messageID,
-      ModifyDNRequest request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP MODIFY DN REQUEST(messageID=%d, request=%s)",
-          messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_MODIFY_DN_REQUEST);
-    writer.writeOctetString(request.getName().toString());
-    writer.writeOctetString(request.getNewRDN().toString());
-    writer.writeBoolean(request.isDeleteOldRDN());
-
-    DN newSuperior = request.getNewSuperior();
-    if (newSuperior != null)
-    {
-      writer.writeOctetString(TYPE_MODIFY_DN_NEW_SUPERIOR, newSuperior
-          .toString());
-    }
-
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeModifyRequest(ASN1Writer writer, int messageID,
-      ModifyRequest request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP MODIFY REQUEST(messageID=%d, request=%s)",
-          messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_MODIFY_REQUEST);
-    writer.writeOctetString(request.getName().toString());
-
-    writer.writeStartSequence();
-    for (Change change : request.getChanges())
-    {
-      encodeChange(writer, change);
-    }
-    writer.writeEndSequence();
-
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeSearchRequest(ASN1Writer writer, int messageID,
-      SearchRequest request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP SEARCH REQUEST(messageID=%d, request=%s)",
-          messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_SEARCH_REQUEST);
-    writer.writeOctetString(request.getName().toString());
-    writer.writeEnumerated(request.getScope().intValue());
-    writer.writeEnumerated(request.getDereferenceAliasesPolicy()
-        .intValue());
-    writer.writeInteger(request.getSizeLimit());
-    writer.writeInteger(request.getTimeLimit());
-    writer.writeBoolean(request.isTypesOnly());
-    LDAPUtils.encodeFilter(writer, request.getFilter());
-
-    writer.writeStartSequence();
-    for (String attribute : request.getAttributes())
-    {
-      writer.writeOctetString(attribute);
-    }
-    writer.writeEndSequence();
-
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeUnbindRequest(ASN1Writer writer, int messageID,
-      UnbindRequest request) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP UNBIND REQUEST(messageID=%d, request=%s)",
-          messageID, request));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeNull(OP_TYPE_UNBIND_REQUEST);
-    encodeMessageFooter(writer, request);
-  }
-
-
-
-  public static void encodeAddResult(ASN1Writer writer, int messageID,
-      Result result) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP ADD RESULT(messageID=%d, result=%s)", messageID,
-          result));
-    }
-    encodeMessageHeader(writer, messageID);
-    encodeResultHeader(writer, OP_TYPE_ADD_RESPONSE, result);
-    encodeResultFooter(writer);
-    encodeMessageFooter(writer, result);
-  }
-
-
-
-  public static void encodeBindResult(ASN1Writer writer, int messageID,
-      BindResult result) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP BIND RESULT(messageID=%d, result=%s)",
-          messageID, result));
-    }
-    encodeMessageHeader(writer, messageID);
-    encodeResultHeader(writer, OP_TYPE_BIND_RESPONSE, result);
-
-    ByteString saslCredentials = result.getServerSASLCredentials();
-    if (saslCredentials !=null && saslCredentials.length() > 0)
-    {
-      writer.writeOctetString(TYPE_SERVER_SASL_CREDENTIALS, result
-          .getServerSASLCredentials());
-    }
-
-    encodeResultFooter(writer);
-    encodeMessageFooter(writer, result);
-  }
-
-
-
-  public static void encodeCompareResult(ASN1Writer writer, int messageID,
-      CompareResult result) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP COMPARE RESULT(messageID=%d, result=%s)",
-          messageID, result));
-    }
-    encodeMessageHeader(writer, messageID);
-    encodeResultHeader(writer, OP_TYPE_COMPARE_RESPONSE, result);
-    encodeResultFooter(writer);
-    encodeMessageFooter(writer, result);
-  }
-
-
-
-  public static void encodeDeleteResult(ASN1Writer writer, int messageID,
-      Result result) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP DELETE RESULT(messageID=%d, result=%s)",
-          messageID, result));
-    }
-    encodeMessageHeader(writer, messageID);
-    encodeResultHeader(writer, OP_TYPE_DELETE_RESPONSE, result);
-    encodeResultFooter(writer);
-    encodeMessageFooter(writer, result);
-  }
-
-
-
-  public static void encodeExtendedResult(ASN1Writer writer, int messageID,
-      ExtendedResult result) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP EXTENDED RESULT(messageID=%d, result=%s)",
-          messageID, result));
-    }
-    encodeMessageHeader(writer, messageID);
-    encodeResultHeader(writer, OP_TYPE_EXTENDED_RESPONSE, result);
-
-    String responseName = result.getResponseName();
-    ByteString responseValue = result.getResponseValue();
-
-    if (responseName != null)
-    {
-      writer.writeOctetString(TYPE_EXTENDED_RESPONSE_OID, responseName);
-    }
-
-    if (responseValue != null)
-    {
-      writer.writeOctetString(TYPE_EXTENDED_RESPONSE_VALUE,
-          responseValue);
-    }
-
-    encodeResultFooter(writer);
-    encodeMessageFooter(writer, result);
-  }
-
-
-
-  public static void encodeIntermediateResponse(ASN1Writer writer,
-      int messageID, IntermediateResponse response) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG
-          .finer(String
-              .format(
-                  "ENCODE LDAP INTERMEDIATE RESPONSE(messageID=%d, response=%s)",
-                  messageID, response));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_INTERMEDIATE_RESPONSE);
-
-    String responseName = response.getResponseName();
-    ByteString responseValue = response.getResponseValue();
-
-    if (responseName != null)
-    {
-      writer.writeOctetString(TYPE_INTERMEDIATE_RESPONSE_OID, response
-          .getResponseName());
-    }
-
-    if (responseValue != null)
-    {
-      writer.writeOctetString(TYPE_INTERMEDIATE_RESPONSE_VALUE,
-          response.getResponseValue());
-    }
-
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, response);
-  }
-
-
-
-  public static void encodeModifyDNResult(ASN1Writer writer, int messageID,
-      Result result) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP MODIFY DN RESULT(messageID=%d, result=%s)",
-          messageID, result));
-    }
-    encodeMessageHeader(writer, messageID);
-    encodeResultHeader(writer, OP_TYPE_MODIFY_DN_RESPONSE, result);
-    encodeResultFooter(writer);
-    encodeMessageFooter(writer, result);
-  }
-
-
-
-  public static void encodeModifyResult(ASN1Writer writer, int messageID,
-      Result result) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP MODIFY RESULT(messageID=%d, result=%s)",
-          messageID, result));
-    }
-    encodeMessageHeader(writer, messageID);
-    encodeResultHeader(writer, OP_TYPE_MODIFY_RESPONSE, result);
-    encodeResultFooter(writer);
-    encodeMessageFooter(writer, result);
-  }
-
-
-
-  public static void encodeSearchResult(ASN1Writer writer, int messageID,
-      Result result) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP SEARCH RESULT(messageID=%d, result=%s)",
-          messageID, result));
-    }
-    encodeMessageHeader(writer, messageID);
-    encodeResultHeader(writer, OP_TYPE_SEARCH_RESULT_DONE, result);
-    encodeResultFooter(writer);
-    encodeMessageFooter(writer, result);
-  }
-
-
-
-  public static void encodeSearchResultEntry(ASN1Writer writer, int messageID,
-      SearchResultEntry entry) throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG.finer(String.format(
-          "ENCODE LDAP SEARCH RESULT ENTRY(messageID=%d, entry=%s)",
-          messageID, entry));
-    }
-    encodeMessageHeader(writer, messageID);
-    encodeEntry(writer, entry);
-    encodeMessageFooter(writer, entry);
-  }
-
-
-
-  public static void encodeSearchResultReference(ASN1Writer writer,
-      int messageID, SearchResultReference reference)
-      throws IOException
-  {
-    if (StaticUtils.DEBUG_LOG.isLoggable(Level.FINER))
-    {
-      StaticUtils.DEBUG_LOG
-          .finer(String
-              .format(
-                  "ENCODE LDAP SEARCH RESULT REFERENCE(messageID=%d, reference=%s)",
-                  messageID, reference));
-    }
-    encodeMessageHeader(writer, messageID);
-    writer.writeStartSequence(OP_TYPE_SEARCH_RESULT_REFERENCE);
-    for (String url : reference.getURIs())
-    {
-      writer.writeOctetString(url);
-    }
-    writer.writeEndSequence();
-    encodeMessageFooter(writer, reference);
-  }
-
-
-
-  private static void encodeAttribute(ASN1Writer writer, Attribute attribute)
-      throws IOException
-  {
-    writer.writeStartSequence();
-    writer
-        .writeOctetString(attribute.getAttributeDescriptionAsString());
-
-    writer.writeStartSet();
-    for (ByteString value : attribute)
-    {
-      writer.writeOctetString(value);
-    }
-    writer.writeEndSequence();
-
-    writer.writeEndSequence();
-  }
-
-
-
-  private static void encodeChange(ASN1Writer writer, Change change)
-      throws IOException
-  {
-    writer.writeStartSequence();
-    writer.writeEnumerated(change.getModificationType().intValue());
-    encodeAttribute(writer, change.getAttribute());
-    writer.writeEndSequence();
-  }
-
-
-
-  private static void encodeMessageFooter(ASN1Writer writer,
-      Request request) throws IOException
-  {
-    if (request.hasControls())
-    {
-      writer.writeStartSequence(TYPE_CONTROL_SEQUENCE);
-      for (Control control : request.getControls())
-      {
-        encodeControl(writer, control);
-      }
-      writer.writeEndSequence();
-    }
-
-    writer.writeEndSequence();
-  }
-
-
-
-  private static void encodeMessageFooter(ASN1Writer writer,
-      Response response) throws IOException
-  {
-    if (response.hasControls())
-    {
-      writer.writeStartSequence(TYPE_CONTROL_SEQUENCE);
-      for (Control control : response.getControls())
-      {
-        encodeControl(writer, control);
-      }
-      writer.writeEndSequence();
-    }
-
-    writer.writeEndSequence();
-  }
-
-
-
-  private static void encodeMessageHeader(ASN1Writer writer,
-      int messageID) throws IOException
-  {
-    writer.writeStartSequence();
-    writer.writeInteger(messageID);
-  }
-
-
-
-  private static void encodeResultFooter(ASN1Writer writer)
-      throws IOException
-  {
-    writer.writeEndSequence();
-  }
-
-
-
-  private static void encodeResultHeader(ASN1Writer writer,
-      byte typeTag, Result rawMessage) throws IOException
-  {
-    writer.writeStartSequence(typeTag);
-    writer.writeEnumerated(rawMessage.getResultCode().intValue());
-    writer.writeOctetString(rawMessage.getMatchedDN());
-    writer.writeOctetString(rawMessage.getDiagnosticMessage());
-
-    if (rawMessage.hasReferralURIs())
-    {
-      writer.writeStartSequence(TYPE_REFERRAL_SEQUENCE);
-      for (String s : rawMessage.getReferralURIs())
-      {
-        writer.writeOctetString(s);
-      }
-      writer.writeEndSequence();
-    }
-  }
-}
diff --git a/sdk/src/org/opends/sdk/ldap/ResolvedSchema.java b/sdk/src/org/opends/sdk/ldap/ResolvedSchema.java
deleted file mode 100644
index ae9bfde..0000000
--- a/sdk/src/org/opends/sdk/ldap/ResolvedSchema.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.ldap;
-
-
-
-import org.opends.sdk.AttributeDescription;
-import org.opends.sdk.DN;
-import org.opends.sdk.DecodeException;
-import org.opends.sdk.RDN;
-import org.opends.sdk.schema.Schema;
-
-
-
-/**
- * A reference to a schema which should be used when decoding incoming
- * protocol elements.
- */
-public interface ResolvedSchema
-{
-  DN getInitialDN();
-
-
-
-  Schema getSchema();
-
-
-
-  DN decodeDN(String dn) throws DecodeException;
-
-
-
-  RDN decodeRDN(String rdn) throws DecodeException;
-
-
-
-  AttributeDescription decodeAttributeDescription(
-      String attributeDescription) throws DecodeException;
-
-}
diff --git a/sdk/src/org/opends/sdk/ldif/AbstractLDIFReader.java b/sdk/src/org/opends/sdk/ldif/AbstractLDIFReader.java
index 4038f82..8ff8698 100644
--- a/sdk/src/org/opends/sdk/ldif/AbstractLDIFReader.java
+++ b/sdk/src/org/opends/sdk/ldif/AbstractLDIFReader.java
@@ -30,7 +30,7 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -43,7 +43,8 @@
 
 import org.opends.sdk.*;
 
-import com.sun.opends.sdk.util.*;
+import com.sun.opends.sdk.util.Base64;
+import com.sun.opends.sdk.util.Validator;
 
 
 
@@ -68,8 +69,7 @@
   {
 
     /**
-     * Closes any resources associated with this LDIF reader
-     * implementation.
+     * Closes any resources associated with this LDIF reader implementation.
      *
      * @throws IOException
      *           If an error occurs while closing.
@@ -82,8 +82,8 @@
      * Reads the next line of LDIF from the underlying LDIF source.
      * Implementations must remove trailing line delimiters.
      *
-     * @return The next line of LDIF, or {@code null} if the end of the
-     *         LDIF source has been reached.
+     * @return The next line of LDIF, or {@code null} if the end of the LDIF
+     *         source has been reached.
      * @throws IOException
      *           If an error occurs while reading from the LDIF source.
      */
@@ -92,7 +92,7 @@
 
 
 
-  final class LDIFRecord
+  static final class LDIFRecord
   {
     final Iterator<String> iterator;
 
@@ -102,7 +102,7 @@
 
 
 
-    private LDIFRecord(long lineNumber, LinkedList<String> ldifLines)
+    private LDIFRecord(final long lineNumber, final LinkedList<String> ldifLines)
     {
       this.lineNumber = lineNumber;
       this.ldifLines = ldifLines;
@@ -115,7 +115,7 @@
   /**
    * LDIF output stream writer implementation.
    */
-  private final class LDIFReaderInputStreamImpl implements
+  private static final class LDIFReaderInputStreamImpl implements
       LDIFReaderImpl
   {
 
@@ -129,7 +129,7 @@
      * @param in
      *          The input stream to use.
      */
-    LDIFReaderInputStreamImpl(InputStream in)
+    LDIFReaderInputStreamImpl(final InputStream in)
     {
       this.reader = new BufferedReader(new InputStreamReader(in));
     }
@@ -171,7 +171,7 @@
   /**
    * LDIF output stream writer implementation.
    */
-  private final class LDIFReaderListImpl implements LDIFReaderImpl
+  private static final class LDIFReaderListImpl implements LDIFReaderImpl
   {
 
     private final Iterator<String> iterator;
@@ -184,7 +184,7 @@
      * @param ldifLines
      *          The string list.
      */
-    LDIFReaderListImpl(List<String> ldifLines)
+    LDIFReaderListImpl(final List<String> ldifLines)
     {
       this.iterator = ldifLines.iterator();
     }
@@ -228,13 +228,12 @@
 
 
   /**
-   * Creates a new LDIF entry reader whose source is the provided input
-   * stream.
+   * Creates a new LDIF entry reader whose source is the provided input stream.
    *
    * @param in
    *          The input stream to use.
    */
-  AbstractLDIFReader(InputStream in)
+  AbstractLDIFReader(final InputStream in)
   {
     Validator.ensureNotNull(in);
     this.impl = new LDIFReaderInputStreamImpl(in);
@@ -243,13 +242,13 @@
 
 
   /**
-   * Creates a new LDIF entry reader which will read lines of LDIF from
-   * the provided list.
+   * Creates a new LDIF entry reader which will read lines of LDIF from the
+   * provided list.
    *
    * @param ldifLines
    *          The list from which lines of LDIF should be read.
    */
-  AbstractLDIFReader(List<String> ldifLines)
+  AbstractLDIFReader(final List<String> ldifLines)
   {
     Validator.ensureNotNull(ldifLines);
     this.impl = new LDIFReaderListImpl(ldifLines);
@@ -264,7 +263,7 @@
 
 
 
-  final int parseColonPosition(LDIFRecord record, String ldifLine)
+  final int parseColonPosition(final LDIFRecord record, final String ldifLine)
       throws DecodeException
   {
     final int colonPos = ldifLine.indexOf(":");
@@ -279,8 +278,9 @@
 
 
 
-  final ByteString parseSingleValue(LDIFRecord record, String ldifLine,
-      DN entryDN, int colonPos, String attrName) throws DecodeException
+  final ByteString parseSingleValue(final LDIFRecord record,
+      final String ldifLine, final DN entryDN, final int colonPos,
+      final String attrName) throws DecodeException
   {
 
     // Look at the character immediately after the colon. If there is
@@ -339,8 +339,7 @@
         {
           // The URL was malformed or had an invalid protocol.
           final LocalizableMessage message = ERR_LDIF_INVALID_URL.get(entryDN
-              .toString(), record.lineNumber, attrName, String
-              .valueOf(e));
+              .toString(), record.lineNumber, attrName, String.valueOf(e));
           throw DecodeException.error(message);
         }
 
@@ -409,13 +408,13 @@
     final LinkedList<String> ldifLines = new LinkedList<String>();
     long recordLineNumber = 0;
 
-    final int START = 0;
-    final int START_COMMENT_LINE = 1;
-    final int GOT_LDIF_LINE = 2;
-    final int GOT_COMMENT_LINE = 3;
-    final int APPENDING_LDIF_LINE = 4;
+    final int stateStart = 0;
+    final int stateStartCommentLine = 1;
+    final int stateGotLDIFLine = 2;
+    final int stateGotCommentLine = 3;
+    final int appendingLDIFLine = 4;
 
-    int state = START;
+    int state = stateStart;
 
     while (true)
     {
@@ -423,7 +422,7 @@
 
       switch (state)
       {
-      case START:
+      case stateStart:
         if (line == null)
         {
           // We have reached the end of the LDIF source.
@@ -436,13 +435,13 @@
         else if (line.charAt(0) == '#')
         {
           // This is a comment at the start of the LDIF record.
-          state = START_COMMENT_LINE;
+          state = stateStartCommentLine;
         }
         else if (isContinuationLine(line))
         {
           // Fatal: got a continuation line at the start of the record.
-          final LocalizableMessage message = ERR_LDIF_INVALID_LEADING_SPACE.get(
-              lineNumber, line);
+          final LocalizableMessage message = ERR_LDIF_INVALID_LEADING_SPACE
+              .get(lineNumber, line);
           throw DecodeException.fatalError(message);
         }
         else
@@ -450,10 +449,10 @@
           // Got the first line of LDIF.
           ldifLines.add(line);
           recordLineNumber = lineNumber;
-          state = GOT_LDIF_LINE;
+          state = stateGotLDIFLine;
         }
         break;
-      case START_COMMENT_LINE:
+      case stateStartCommentLine:
         if (line == null)
         {
           // We have reached the end of the LDIF source.
@@ -462,7 +461,7 @@
         else if (line.length() == 0)
         {
           // Skip leading blank lines and comments.
-          state = START;
+          state = stateStart;
         }
         else if (line.charAt(0) == '#')
         {
@@ -477,10 +476,10 @@
           // Got the first line of LDIF.
           ldifLines.add(line);
           recordLineNumber = lineNumber;
-          state = GOT_LDIF_LINE;
+          state = stateGotLDIFLine;
         }
         break;
-      case GOT_LDIF_LINE:
+      case stateGotLDIFLine:
         if (line == null)
         {
           // We have reached the end of the LDIF source.
@@ -494,7 +493,7 @@
         else if (line.charAt(0) == '#')
         {
           // This is a comment.
-          state = GOT_COMMENT_LINE;
+          state = stateGotCommentLine;
         }
         else if (isContinuationLine(line))
         {
@@ -502,16 +501,16 @@
           lastLineBuilder.setLength(0);
           lastLineBuilder.append(ldifLines.removeLast());
           lastLineBuilder.append(line.substring(1));
-          state = APPENDING_LDIF_LINE;
+          state = appendingLDIFLine;
         }
         else
         {
           // Got the next line of LDIF.
           ldifLines.add(line);
-          state = GOT_LDIF_LINE;
+          state = stateGotLDIFLine;
         }
         break;
-      case GOT_COMMENT_LINE:
+      case stateGotCommentLine:
         if (line == null)
         {
           // We have reached the end of the LDIF source.
@@ -525,7 +524,7 @@
         else if (line.charAt(0) == '#')
         {
           // This is another comment.
-          state = GOT_COMMENT_LINE;
+          state = stateGotCommentLine;
         }
         else if (isContinuationLine(line))
         {
@@ -535,10 +534,10 @@
         {
           // Got the next line of LDIF.
           ldifLines.add(line);
-          state = GOT_LDIF_LINE;
+          state = stateGotLDIFLine;
         }
         break;
-      case APPENDING_LDIF_LINE:
+      case appendingLDIFLine:
         if (line == null)
         {
           // We have reached the end of the LDIF source.
@@ -555,7 +554,7 @@
         {
           // This is a comment.
           ldifLines.add(lastLineBuilder.toString());
-          state = GOT_COMMENT_LINE;
+          state = stateGotCommentLine;
         }
         else if (isContinuationLine(line))
         {
@@ -567,7 +566,7 @@
           // Got the next line of LDIF.
           ldifLines.add(lastLineBuilder.toString());
           ldifLines.add(line);
-          state = GOT_LDIF_LINE;
+          state = stateGotLDIFLine;
         }
         break;
       }
@@ -576,8 +575,8 @@
 
 
 
-  final void readLDIFRecordAttributeValue(LDIFRecord record,
-      String ldifLine, Entry entry) throws DecodeException
+  final void readLDIFRecordAttributeValue(final LDIFRecord record,
+      final String ldifLine, final Entry entry) throws DecodeException
   {
     // Parse the attribute description.
     final int colonPos = parseColonPosition(record, ldifLine);
@@ -586,8 +585,7 @@
     AttributeDescription attributeDescription;
     try
     {
-      attributeDescription = AttributeDescription.valueOf(attrDescr,
-          schema);
+      attributeDescription = AttributeDescription.valueOf(attrDescr, schema);
     }
     catch (final LocalizedIllegalArgumentException e)
     {
@@ -595,8 +593,8 @@
     }
 
     // Now parse the attribute value.
-    final ByteString value = parseSingleValue(record, ldifLine, entry
-        .getName(), colonPos, attrDescr);
+    final ByteString value = parseSingleValue(record, ldifLine,
+        entry.getName(), colonPos, attrDescr);
 
     // Skip the attribute if requested before performing any schema
     // checking: the attribute may have been excluded because it is
@@ -610,18 +608,17 @@
     if (!attributeDescription.getAttributeType().getSyntax()
         .isBEREncodingRequired())
     {
-      if (validateSchema
-          && attributeDescription.containsOption("binary"))
+      if (validateSchema && attributeDescription.containsOption("binary"))
       {
-        final LocalizableMessage message = ERR_LDIF_INVALID_ATTR_OPTION.get(entry
-            .getName().toString(), record.lineNumber, attrDescr);
+        final LocalizableMessage message = ERR_LDIF_INVALID_ATTR_OPTION.get(
+            entry.getName().toString(), record.lineNumber, attrDescr);
         throw DecodeException.error(message);
       }
     }
     else
     {
-      attributeDescription = AttributeDescription.create(
-          attributeDescription, "binary");
+      attributeDescription = AttributeDescription.create(attributeDescription,
+          "binary");
     }
 
     Attribute attribute = entry.getAttribute(attributeDescription);
@@ -633,8 +630,8 @@
         if (!attributeDescription.getAttributeType().getSyntax()
             .valueIsAcceptable(value, invalidReason))
         {
-          final LocalizableMessage message = WARN_LDIF_VALUE_VIOLATES_SYNTAX.get(
-              entry.getName().toString(), record.lineNumber, value
+          final LocalizableMessage message = WARN_LDIF_VALUE_VIOLATES_SYNTAX
+              .get(entry.getName().toString(), record.lineNumber, value
                   .toString(), attrDescr, invalidReason);
           throw DecodeException.error(message);
         }
@@ -651,8 +648,8 @@
         if (!attributeDescription.getAttributeType().getSyntax()
             .valueIsAcceptable(value, invalidReason))
         {
-          final LocalizableMessage message = WARN_LDIF_VALUE_VIOLATES_SYNTAX.get(
-              entry.getName().toString(), record.lineNumber, value
+          final LocalizableMessage message = WARN_LDIF_VALUE_VIOLATES_SYNTAX
+              .get(entry.getName().toString(), record.lineNumber, value
                   .toString(), attrDescr, invalidReason);
           throw DecodeException.error(message);
         }
@@ -660,16 +657,15 @@
         if (!attribute.add(value))
         {
           final LocalizableMessage message = WARN_LDIF_DUPLICATE_ATTR.get(entry
-              .getName().toString(), record.lineNumber, attrDescr,
-              value.toString());
+              .getName().toString(), record.lineNumber, attrDescr, value
+              .toString());
           throw DecodeException.error(message);
         }
 
         if (attributeDescription.getAttributeType().isSingleValue())
         {
           final LocalizableMessage message = ERR_LDIF_MULTIPLE_VALUES_FOR_SINGLE_VALUED_ATTR
-              .get(entry.getName().toString(), record.lineNumber,
-                  attrDescr);
+              .get(entry.getName().toString(), record.lineNumber, attrDescr);
           throw DecodeException.error(message);
         }
       }
@@ -682,7 +678,7 @@
 
 
 
-  final DN readLDIFRecordDN(LDIFRecord record) throws DecodeException
+  final DN readLDIFRecordDN(final LDIFRecord record) throws DecodeException
   {
     String ldifLine = record.iterator.next();
     int colonPos = ldifLine.indexOf(":");
@@ -783,8 +779,9 @@
 
 
 
-  final String readLDIFRecordKeyValuePair(LDIFRecord record,
-      KeyValuePair pair, boolean allowBase64) throws DecodeException
+  final String readLDIFRecordKeyValuePair(final LDIFRecord record,
+      final KeyValuePair pair, final boolean allowBase64)
+      throws DecodeException
   {
     final String ldifLine = record.iterator.next();
     final int colonPos = ldifLine.indexOf(":");
@@ -849,8 +846,8 @@
 
 
 
-  final void rejectLDIFRecord(LDIFRecord record, LocalizableMessage message)
-      throws DecodeException
+  final void rejectLDIFRecord(final LDIFRecord record,
+      final LocalizableMessage message) throws DecodeException
   {
     // FIXME: not yet implemented.
     throw DecodeException.error(message);
@@ -858,7 +855,8 @@
 
 
 
-  final void skipLDIFRecord(LDIFRecord record, LocalizableMessage message)
+  final void skipLDIFRecord(final LDIFRecord record,
+      final LocalizableMessage message)
   {
     // FIXME: not yet implemented.
   }
@@ -870,7 +868,7 @@
   // position, both OpenLDAP and the Sun Java System Directory Server
   // allow a tab as well, so we will too for compatibility reasons. See
   // issue #852 for details.
-  private boolean isContinuationLine(String line)
+  private boolean isContinuationLine(final String line)
   {
     return line.charAt(0) == ' ' || line.charAt(0) == '\t';
   }
diff --git a/sdk/src/org/opends/sdk/ldif/AbstractLDIFStream.java b/sdk/src/org/opends/sdk/ldif/AbstractLDIFStream.java
index 5e7ca7e..fbf1f08 100644
--- a/sdk/src/org/opends/sdk/ldif/AbstractLDIFStream.java
+++ b/sdk/src/org/opends/sdk/ldif/AbstractLDIFStream.java
@@ -49,15 +49,13 @@
 abstract class AbstractLDIFStream
 {
 
-  final Set<AttributeDescription> excludeAttributes =
-      new HashSet<AttributeDescription>();
+  final Set<AttributeDescription> excludeAttributes = new HashSet<AttributeDescription>();
 
   boolean excludeOperationalAttributes = false;
 
   boolean excludeUserAttributes = false;
 
-  final Set<AttributeDescription> includeAttributes =
-      new HashSet<AttributeDescription>();
+  final Set<AttributeDescription> includeAttributes = new HashSet<AttributeDescription>();
 
   Schema schema = Schema.getDefaultSchema();
 
@@ -82,7 +80,7 @@
 
 
   final boolean isAttributeExcluded(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
   {
     if (!excludeAttributes.isEmpty()
         && excludeAttributes.contains(attributeDescription))
@@ -113,7 +111,7 @@
 
 
 
-  final boolean isBranchExcluded(DN dn)
+  final boolean isBranchExcluded(final DN dn)
   {
     if (!excludeBranches.isEmpty())
     {
@@ -143,7 +141,7 @@
 
 
 
-  final boolean isEntryExcluded(Entry entry)
+  final boolean isEntryExcluded(final Entry entry)
   {
     if (!excludeFilters.isEmpty())
     {
diff --git a/sdk/src/org/opends/sdk/ldif/AbstractLDIFWriter.java b/sdk/src/org/opends/sdk/ldif/AbstractLDIFWriter.java
index e976eb4..8ffade1 100644
--- a/sdk/src/org/opends/sdk/ldif/AbstractLDIFWriter.java
+++ b/sdk/src/org/opends/sdk/ldif/AbstractLDIFWriter.java
@@ -58,9 +58,8 @@
   {
 
     /**
-     * Closes any resources associated with this LDIF writer
-     * implementation.
-     * 
+     * Closes any resources associated with this LDIF writer implementation.
+     *
      * @throws IOException
      *           If an error occurs while closing.
      */
@@ -69,17 +68,16 @@
 
 
     /**
-     * Flushes this LDIF writer implementation so that any buffered data
-     * is written immediately to underlying stream, flushing the stream
-     * if it is also {@code Flushable}.
+     * Flushes this LDIF writer implementation so that any buffered data is
+     * written immediately to underlying stream, flushing the stream if it is
+     * also {@code Flushable}.
      * <p>
-     * If the intended destination of this stream is an abstraction
-     * provided by the underlying operating system, for example a file,
-     * then flushing the stream guarantees only that bytes previously
-     * written to the stream are passed to the operating system for
-     * writing; it does not guarantee that they are actually written to
-     * a physical device such as a disk drive.
-     * 
+     * If the intended destination of this stream is an abstraction provided by
+     * the underlying operating system, for example a file, then flushing the
+     * stream guarantees only that bytes previously written to the stream are
+     * passed to the operating system for writing; it does not guarantee that
+     * they are actually written to a physical device such as a disk drive.
+     *
      * @throws IOException
      *           If an error occurs while flushing.
      */
@@ -88,9 +86,9 @@
 
 
     /**
-     * Prints the provided {@code CharSequence}. Implementations must
-     * not add a new-line character sequence.
-     * 
+     * Prints the provided {@code CharSequence}. Implementations must not add a
+     * new-line character sequence.
+     *
      * @param s
      *          The {@code CharSequence} to be printed.
      * @throws IOException
@@ -102,10 +100,10 @@
 
     /**
      * Prints a new-line character sequence.
-     * 
+     *
      * @throws IOException
-     *           If an error occurs while printing the new-line
-     *           character sequence.
+     *           If an error occurs while printing the new-line character
+     *           sequence.
      */
     void println() throws IOException;
   }
@@ -115,7 +113,7 @@
   /**
    * LDIF string list writer implementation.
    */
-  private final class LDIFWriterListImpl implements LDIFWriterImpl
+  private static final class LDIFWriterListImpl implements LDIFWriterImpl
   {
 
     private final StringBuilder builder = new StringBuilder();
@@ -126,11 +124,11 @@
 
     /**
      * Creates a new LDIF list writer.
-     * 
+     *
      * @param ldifLines
      *          The string list.
      */
-    LDIFWriterListImpl(List<String> ldifLines)
+    LDIFWriterListImpl(final List<String> ldifLines)
     {
       this.ldifLines = ldifLines;
     }
@@ -160,7 +158,7 @@
     /**
      * {@inheritDoc}
      */
-    public void print(CharSequence s) throws IOException
+    public void print(final CharSequence s) throws IOException
     {
       builder.append(s);
     }
@@ -182,7 +180,7 @@
   /**
    * LDIF output stream writer implementation.
    */
-  private final class LDIFWriterOutputStreamImpl implements
+  private static final class LDIFWriterOutputStreamImpl implements
       LDIFWriterImpl
   {
 
@@ -192,11 +190,11 @@
 
     /**
      * Creates a new LDIF output stream writer.
-     * 
+     *
      * @param out
      *          The output stream.
      */
-    LDIFWriterOutputStreamImpl(OutputStream out)
+    LDIFWriterOutputStreamImpl(final OutputStream out)
     {
       this.writer = new BufferedWriter(new OutputStreamWriter(out));
     }
@@ -226,7 +224,7 @@
     /**
      * {@inheritDoc}
      */
-    public void print(CharSequence s) throws IOException
+    public void print(final CharSequence s) throws IOException
     {
       writer.append(s);
     }
@@ -242,9 +240,10 @@
     }
   }
 
+
+
   // Regular expression used for splitting comments on line-breaks.
-  private static final Pattern SPLIT_NEWLINE =
-      Pattern.compile("\\r?\\n");
+  private static final Pattern SPLIT_NEWLINE = Pattern.compile("\\r?\\n");
 
   boolean addUserFriendlyComments = false;
 
@@ -257,13 +256,13 @@
 
 
   /**
-   * Creates a new LDIF entry writer which will append lines of LDIF to
-   * the provided list.
-   * 
+   * Creates a new LDIF entry writer which will append lines of LDIF to the
+   * provided list.
+   *
    * @param ldifLines
    *          The list to which lines of LDIF should be appended.
    */
-  public AbstractLDIFWriter(List<String> ldifLines)
+  public AbstractLDIFWriter(final List<String> ldifLines)
   {
     Validator.ensureNotNull(ldifLines);
     this.impl = new LDIFWriterListImpl(ldifLines);
@@ -272,13 +271,13 @@
 
 
   /**
-   * Creates a new LDIF entry writer whose destination is the provided
-   * output stream.
-   * 
+   * Creates a new LDIF entry writer whose destination is the provided output
+   * stream.
+   *
    * @param out
    *          The output stream to use.
    */
-  public AbstractLDIFWriter(OutputStream out)
+  public AbstractLDIFWriter(final OutputStream out)
   {
     Validator.ensureNotNull(out);
     this.impl = new LDIFWriterOutputStreamImpl(out);
@@ -301,7 +300,7 @@
 
 
 
-  final void writeComment0(CharSequence comment) throws IOException,
+  final void writeComment0(final CharSequence comment) throws IOException,
       NullPointerException
   {
     Validator.ensureNotNull(comment);
@@ -379,8 +378,7 @@
 
 
 
-  final void writeControls(Iterable<Control> controls)
-      throws IOException
+  final void writeControls(final List<Control> controls) throws IOException
   {
     for (final Control control : controls)
     {
@@ -401,7 +399,7 @@
 
 
 
-  final void writeKeyAndValue(CharSequence key, ByteSequence value)
+  final void writeKeyAndValue(final CharSequence key, final ByteSequence value)
       throws IOException
   {
     builder.setLength(0);
@@ -438,7 +436,7 @@
 
 
 
-  final void writeKeyAndValue(CharSequence key, CharSequence value)
+  final void writeKeyAndValue(final CharSequence key, final CharSequence value)
       throws IOException
   {
     // FIXME: We should optimize this at some point.
@@ -447,7 +445,7 @@
 
 
 
-  final void writeLine(CharSequence line) throws IOException
+  final void writeLine(final CharSequence line) throws IOException
   {
     final int length = line.length();
     if (shouldWrap() && length > wrapColumn)
@@ -473,7 +471,7 @@
 
 
 
-  private boolean needsBase64Encoding(ByteSequence bytes)
+  private boolean needsBase64Encoding(final ByteSequence bytes)
   {
     final int length = bytes.length();
     if (length == 0)
@@ -532,7 +530,7 @@
 
 
   @SuppressWarnings("unused")
-  private void writeKeyAndURL(CharSequence key, CharSequence url)
+  private void writeKeyAndURL(final CharSequence key, final CharSequence url)
       throws IOException
   {
     builder.setLength(0);
diff --git a/sdk/src/org/opends/sdk/ldif/ChangeRecord.java b/sdk/src/org/opends/sdk/ldif/ChangeRecord.java
index 37a1167..7ab93d4 100644
--- a/sdk/src/org/opends/sdk/ldif/ChangeRecord.java
+++ b/sdk/src/org/opends/sdk/ldif/ChangeRecord.java
@@ -27,13 +27,15 @@
 
 package org.opends.sdk.ldif;
 
+
+
 import org.opends.sdk.DN;
 
 
 
 /**
- * A request to modify the content of the Directory in some way. A
- * change record represents one of the following operations:
+ * A request to modify the content of the Directory in some way. A change record
+ * represents one of the following operations:
  * <ul>
  * <li>An {@code Add} operation.
  * <li>An {@code Delete} operation.
@@ -49,8 +51,7 @@
    * @param <R>
    *          The return type of the visitor's methods.
    * @param <P>
-   *          The type of the additional parameters to the visitor's
-   *          methods.
+   *          The type of the additional parameters to the visitor's methods.
    * @param v
    *          The change record visitor.
    * @param p
@@ -62,8 +63,8 @@
 
 
   /**
-   * Returns the distinguished name of the entry being modified by this
-   * {@code ChangeRecord}.
+   * Returns the distinguished name of the entry being modified by this {@code
+   * ChangeRecord}.
    *
    * @return The distinguished name of the entry being modified.
    */
diff --git a/sdk/src/org/opends/sdk/ldif/ChangeRecordReader.java b/sdk/src/org/opends/sdk/ldif/ChangeRecordReader.java
index 8894159..0e73da8 100644
--- a/sdk/src/org/opends/sdk/ldif/ChangeRecordReader.java
+++ b/sdk/src/org/opends/sdk/ldif/ChangeRecordReader.java
@@ -37,14 +37,13 @@
 
 
 /**
- * An interface for reading change records from a data source, typically
- * an LDIF file.
+ * An interface for reading change records from a data source, typically an LDIF
+ * file.
  * <p>
  * Implementations must specify the following:
  * <ul>
  * <li>Whether or not it is possible for the implementation to encounter
- * malformed change records and, if it is possible, how they are
- * handled.
+ * malformed change records and, if it is possible, how they are handled.
  * <li>Any synchronization limitations.
  * </ul>
  * <p>
@@ -56,8 +55,8 @@
 {
 
   /**
-   * Closes this change record reader if it not already closed. Note
-   * that this method does not need to be called if a previous call of
+   * Closes this change record reader if it not already closed. Note that this
+   * method does not need to be called if a previous call of
    * {@link #readChangeRecord()} has returned {@code null}.
    *
    * @throws IOException
@@ -68,19 +67,18 @@
 
 
   /**
-   * Reads the next change record, blocking if necessary until a change
-   * record is available. If the next change record does not contain a
-   * change type then it will be treated as an {@code Add} change
-   * record.
+   * Reads the next change record, blocking if necessary until a change record
+   * is available. If the next change record does not contain a change type then
+   * it will be treated as an {@code Add} change record.
    *
-   * @return The next change record, or {@code null} if there are no
-   *         more change records to be read.
+   * @return The next change record, or {@code null} if there are no more change
+   *         records to be read.
    * @throws DecodeException
    *           If the change record could not be decoded because it was
    *           malformed.
    * @throws IOException
-   *           If an unexpected IO error occurred while reading the
-   *           change record.
+   *           If an unexpected IO error occurred while reading the change
+   *           record.
    */
   ChangeRecord readChangeRecord() throws DecodeException, IOException;
 }
diff --git a/sdk/src/org/opends/sdk/ldif/ChangeRecordVisitor.java b/sdk/src/org/opends/sdk/ldif/ChangeRecordVisitor.java
index 6cf718a..8dc9de8 100644
--- a/sdk/src/org/opends/sdk/ldif/ChangeRecordVisitor.java
+++ b/sdk/src/org/opends/sdk/ldif/ChangeRecordVisitor.java
@@ -37,22 +37,21 @@
 
 
 /**
- * A visitor of {@code ChangeRecord}s, in the style of the visitor
- * design pattern.
+ * A visitor of {@code ChangeRecord}s, in the style of the visitor design
+ * pattern.
  * <p>
- * Classes implementing this interface can query change records in a
- * type-safe manner. When a visitor is passed to a change record's
- * accept method, the corresponding visit method most applicable to that
- * change record is invoked.
+ * Classes implementing this interface can query change records in a type-safe
+ * manner. When a visitor is passed to a change record's accept method, the
+ * corresponding visit method most applicable to that change record is invoked.
  *
  * @param <R>
  *          The return type of this visitor's methods. Use
- *          {@link java.lang.Void} for visitors that do not need to
- *          return results.
+ *          {@link java.lang.Void} for visitors that do not need to return
+ *          results.
  * @param <P>
- *          The type of the additional parameter to this visitor's
- *          methods. Use {@link java.lang.Void} for visitors that do not
- *          need an additional parameter.
+ *          The type of the additional parameter to this visitor's methods. Use
+ *          {@link java.lang.Void} for visitors that do not need an additional
+ *          parameter.
  */
 public interface ChangeRecordVisitor<R, P>
 {
diff --git a/sdk/src/org/opends/sdk/ldif/ChangeRecordVisitorWriter.java b/sdk/src/org/opends/sdk/ldif/ChangeRecordVisitorWriter.java
index 6a09c24..e7b505b 100644
--- a/sdk/src/org/opends/sdk/ldif/ChangeRecordVisitorWriter.java
+++ b/sdk/src/org/opends/sdk/ldif/ChangeRecordVisitorWriter.java
@@ -1,3 +1,30 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
 package org.opends.sdk.ldif;
 
 
@@ -18,14 +45,13 @@
     ChangeRecordVisitor<IOException, ChangeRecordWriter>
 {
   // Visitor used for writing generic change records.
-  private static final ChangeRecordVisitorWriter VISITOR =
-      new ChangeRecordVisitorWriter();
+  private static final ChangeRecordVisitorWriter VISITOR = new ChangeRecordVisitorWriter();
 
 
 
   /**
    * Returns the singleton instance.
-   * 
+   *
    * @return The instance.
    */
   static ChangeRecordVisitorWriter getInstance()
@@ -42,8 +68,8 @@
 
 
 
-  public IOException visitChangeRecord(ChangeRecordWriter p,
-      AddRequest change)
+  public IOException visitChangeRecord(final ChangeRecordWriter p,
+      final AddRequest change)
   {
     try
     {
@@ -58,8 +84,8 @@
 
 
 
-  public IOException visitChangeRecord(ChangeRecordWriter p,
-      DeleteRequest change)
+  public IOException visitChangeRecord(final ChangeRecordWriter p,
+      final DeleteRequest change)
   {
     try
     {
@@ -74,8 +100,8 @@
 
 
 
-  public IOException visitChangeRecord(ChangeRecordWriter p,
-      ModifyDNRequest change)
+  public IOException visitChangeRecord(final ChangeRecordWriter p,
+      final ModifyDNRequest change)
   {
     try
     {
@@ -90,8 +116,8 @@
 
 
 
-  public IOException visitChangeRecord(ChangeRecordWriter p,
-      ModifyRequest change)
+  public IOException visitChangeRecord(final ChangeRecordWriter p,
+      final ModifyRequest change)
   {
     try
     {
diff --git a/sdk/src/org/opends/sdk/ldif/ChangeRecordWriter.java b/sdk/src/org/opends/sdk/ldif/ChangeRecordWriter.java
index 8c5a713..a15794e 100644
--- a/sdk/src/org/opends/sdk/ldif/ChangeRecordWriter.java
+++ b/sdk/src/org/opends/sdk/ldif/ChangeRecordWriter.java
@@ -41,16 +41,16 @@
 
 
 /**
- * An interface for writing change records to a data source, typically
- * an LDIF file.
+ * An interface for writing change records to a data source, typically an LDIF
+ * file.
  * <p>
  * TODO: FilteredChangeRecordWriter
  */
 public interface ChangeRecordWriter extends Closeable, Flushable
 {
   /**
-   * Closes this change record writer, flushing it first. Closing a
-   * previously closed change record writer has no effect.
+   * Closes this change record writer, flushing it first. Closing a previously
+   * closed change record writer has no effect.
    *
    * @throws IOException
    *           If an unexpected IO error occurred while closing.
@@ -60,16 +60,15 @@
 
 
   /**
-   * Flushes this change record writer so that any buffered data is
-   * written immediately to underlying stream, flushing the stream if it
-   * is also {@code Flushable}.
+   * Flushes this change record writer so that any buffered data is written
+   * immediately to underlying stream, flushing the stream if it is also {@code
+   * Flushable}.
    * <p>
-   * If the intended destination of this stream is an abstraction
-   * provided by the underlying operating system, for example a file,
-   * then flushing the stream guarantees only that bytes previously
-   * written to the stream are passed to the operating system for
-   * writing; it does not guarantee that they are actually written to a
-   * physical device such as a disk drive.
+   * If the intended destination of this stream is an abstraction provided by
+   * the underlying operating system, for example a file, then flushing the
+   * stream guarantees only that bytes previously written to the stream are
+   * passed to the operating system for writing; it does not guarantee that they
+   * are actually written to a physical device such as a disk drive.
    *
    * @throws IOException
    *           If an unexpected IO error occurred while flushing.
@@ -82,17 +81,17 @@
    * Writes an {@code Add} change record.
    *
    * @param change
-   *          The {@code AddRequest} to be written as an {@code Add}
-   *          change record.
+   *          The {@code AddRequest} to be written as an {@code Add} change
+   *          record.
    * @return A reference to this change record writer.
    * @throws IOException
-   *           If an unexpected IO error occurred while writing the
-   *           change record.
+   *           If an unexpected IO error occurred while writing the change
+   *           record.
    * @throws NullPointerException
    *           If {@code change} was {@code null}.
    */
-  ChangeRecordWriter writeChangeRecord(AddRequest change)
-      throws IOException, NullPointerException;
+  ChangeRecordWriter writeChangeRecord(AddRequest change) throws IOException,
+      NullPointerException;
 
 
 
@@ -103,13 +102,13 @@
    *          The {@code ChangeRecord} to be written.
    * @return A reference to this change record writer.
    * @throws IOException
-   *           If an unexpected IO error occurred while writing the
-   *           change record.
+   *           If an unexpected IO error occurred while writing the change
+   *           record.
    * @throws NullPointerException
    *           If {@code change} was {@code null}.
    */
-  ChangeRecordWriter writeChangeRecord(ChangeRecord change)
-      throws IOException, NullPointerException;
+  ChangeRecordWriter writeChangeRecord(ChangeRecord change) throws IOException,
+      NullPointerException;
 
 
 
@@ -117,12 +116,12 @@
    * Writes a {@code Delete} change record.
    *
    * @param change
-   *          The {@code DeleteRequest} to be written as an {@code
-   *          Delete} change record.
+   *          The {@code DeleteRequest} to be written as an {@code Delete}
+   *          change record.
    * @return A reference to this change record writer.
    * @throws IOException
-   *           If an unexpected IO error occurred while writing the
-   *           change record.
+   *           If an unexpected IO error occurred while writing the change
+   *           record.
    * @throws NullPointerException
    *           If {@code change} was {@code null}.
    */
@@ -135,12 +134,12 @@
    * Writes a {@code ModifyDN} change record.
    *
    * @param change
-   *          The {@code ModifyDNRequest} to be written as an {@code
-   *          ModifyDN} change record.
+   *          The {@code ModifyDNRequest} to be written as an {@code ModifyDN}
+   *          change record.
    * @return A reference to this change record writer.
    * @throws IOException
-   *           If an unexpected IO error occurred while writing the
-   *           change record.
+   *           If an unexpected IO error occurred while writing the change
+   *           record.
    * @throws NullPointerException
    *           If {@code change} was {@code null}.
    */
@@ -153,12 +152,12 @@
    * Writes a {@code Modify} change record.
    *
    * @param change
-   *          The {@code ModifyRequest} to be written as an {@code
-   *          Modify} change record.
+   *          The {@code ModifyRequest} to be written as an {@code Modify}
+   *          change record.
    * @return A reference to this change record writer.
    * @throws IOException
-   *           If an unexpected IO error occurred while writing the
-   *           change record.
+   *           If an unexpected IO error occurred while writing the change
+   *           record.
    * @throws NullPointerException
    *           If {@code change} was {@code null}.
    */
@@ -174,12 +173,11 @@
    *          The {@code CharSequence} to be written as a comment.
    * @return A reference to this change record writer.
    * @throws IOException
-   *           If an unexpected IO error occurred while writing the
-   *           comment.
+   *           If an unexpected IO error occurred while writing the comment.
    * @throws NullPointerException
    *           If {@code comment} was {@code null}.
    */
-  ChangeRecordWriter writeComment(CharSequence comment)
-      throws IOException, NullPointerException;
+  ChangeRecordWriter writeComment(CharSequence comment) throws IOException,
+      NullPointerException;
 
 }
diff --git a/sdk/src/org/opends/sdk/ldif/ConnectionChangeRecordWriter.java b/sdk/src/org/opends/sdk/ldif/ConnectionChangeRecordWriter.java
index 7f428ac..8cadd45 100644
--- a/sdk/src/org/opends/sdk/ldif/ConnectionChangeRecordWriter.java
+++ b/sdk/src/org/opends/sdk/ldif/ConnectionChangeRecordWriter.java
@@ -45,37 +45,35 @@
 
 
 /**
- * A {@code ConnectionChangeRecordWriter} is a bridge from {@code
- * Connection}s to {@code ChangeRecordWriter}s. A connection change
- * record writer writes change records by sending appropriate update
- * requests (Add, Delete, Modify, or ModifyDN) to an underlying
- * connection.
+ * A {@code ConnectionChangeRecordWriter} is a bridge from {@code Connection}s
+ * to {@code ChangeRecordWriter}s. A connection change record writer writes
+ * change records by sending appropriate update requests (Add, Delete, Modify,
+ * or ModifyDN) to an underlying connection.
  * <p>
- * All update requests are performed synchronously, blocking until an
- * update result is received. If an update result indicates that an
- * update request has failed for some reason then the error result is
- * propagated to the caller using an {@code ErrorResultIOException}.
+ * All update requests are performed synchronously, blocking until an update
+ * result is received. If an update result indicates that an update request has
+ * failed for some reason then the error result is propagated to the caller
+ * using an {@code ErrorResultIOException}.
  * <p>
- * <b>Note:</b> comments are not supported by connection change record
- * writers. Attempts to write comments will be ignored.
+ * <b>Note:</b> comments are not supported by connection change record writers.
+ * Attempts to write comments will be ignored.
  */
-public final class ConnectionChangeRecordWriter implements
-    ChangeRecordWriter
+public final class ConnectionChangeRecordWriter implements ChangeRecordWriter
 {
   private final Connection connection;
 
 
 
   /**
-   * Creates a new connection change record writer whose destination is
-   * the provided connection.
+   * Creates a new connection change record writer whose destination is the
+   * provided connection.
    *
    * @param connection
    *          The connection to use.
    * @throws NullPointerException
    *           If {@code connection} was {@code null}.
    */
-  public ConnectionChangeRecordWriter(Connection connection)
+  public ConnectionChangeRecordWriter(final Connection connection)
       throws NullPointerException
   {
     Validator.ensureNotNull(connection);
@@ -85,9 +83,8 @@
 
 
   /**
-   * Closes this connection change record writer, including the
-   * underlying connection. Closing a previously closed change record
-   * writer has no effect.
+   * Closes this connection change record writer, including the underlying
+   * connection. Closing a previously closed change record writer has no effect.
    */
   public void close()
   {
@@ -97,8 +94,8 @@
 
 
   /**
-   * Connection change record writers do not require flushing, so this
-   * method has no effect.
+   * Connection change record writers do not require flushing, so this method
+   * has no effect.
    */
   public void flush()
   {
@@ -108,23 +105,23 @@
 
 
   /**
-   * Writes the provided Add request to the underlying connection,
-   * blocking until the request completes.
+   * Writes the provided Add request to the underlying connection, blocking
+   * until the request completes.
    *
    * @param change
    *          The {@code AddRequest} to be written.
    * @return A reference to this connection change record writer.
    * @throws ErrorResultIOException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedIOException
    *           If the current thread was interrupted while waiting.
    * @throws NullPointerException
    *           If {@code change} was {@code null}.
    */
-  public ConnectionChangeRecordWriter writeChangeRecord(
-      AddRequest change) throws ErrorResultIOException,
-      InterruptedIOException, NullPointerException
+  public ConnectionChangeRecordWriter writeChangeRecord(final AddRequest change)
+      throws ErrorResultIOException, InterruptedIOException,
+      NullPointerException
   {
     Validator.ensureNotNull(change);
     try
@@ -135,7 +132,7 @@
     {
       throw new ErrorResultIOException(e);
     }
-    catch (InterruptedException e)
+    catch (final InterruptedException e)
     {
       throw new InterruptedIOException(e.getMessage());
     }
@@ -145,28 +142,28 @@
 
 
   /**
-   * Writes the provided change record to the underlying connection,
-   * blocking until the request completes.
+   * Writes the provided change record to the underlying connection, blocking
+   * until the request completes.
    *
    * @param change
    *          The change record to be written.
    * @return A reference to this connection change record writer.
    * @throws ErrorResultIOException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedIOException
    *           If the current thread was interrupted while waiting.
    * @throws NullPointerException
    *           If {@code change} was {@code null}.
    */
   public ConnectionChangeRecordWriter writeChangeRecord(
-      ChangeRecord change) throws ErrorResultIOException,
+      final ChangeRecord change) throws ErrorResultIOException,
       InterruptedIOException, NullPointerException
   {
     Validator.ensureNotNull(change);
 
-    final IOException e = change.accept(ChangeRecordVisitorWriter
-        .getInstance(), this);
+    final IOException e = change.accept(
+        ChangeRecordVisitorWriter.getInstance(), this);
     try
     {
       if (e != null)
@@ -178,7 +175,7 @@
     {
       throw e1;
     }
-    catch (InterruptedIOException e1)
+    catch (final InterruptedIOException e1)
     {
       throw e1;
     }
@@ -193,22 +190,22 @@
 
 
   /**
-   * Writes the provided Delete request to the underlying connection,
-   * blocking until the request completes.
+   * Writes the provided Delete request to the underlying connection, blocking
+   * until the request completes.
    *
    * @param change
    *          The {@code DeleteRequest} to be written.
    * @return A reference to this connection change record writer.
    * @throws ErrorResultIOException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedIOException
    *           If the current thread was interrupted while waiting.
    * @throws NullPointerException
    *           If {@code change} was {@code null}.
    */
   public ConnectionChangeRecordWriter writeChangeRecord(
-      DeleteRequest change) throws ErrorResultIOException,
+      final DeleteRequest change) throws ErrorResultIOException,
       InterruptedIOException, NullPointerException
   {
     Validator.ensureNotNull(change);
@@ -220,7 +217,7 @@
     {
       throw new ErrorResultIOException(e);
     }
-    catch (InterruptedException e)
+    catch (final InterruptedException e)
     {
       throw new InterruptedIOException(e.getMessage());
     }
@@ -230,22 +227,22 @@
 
 
   /**
-   * Writes the provided ModifyDN request to the underlying connection,
-   * blocking until the request completes.
+   * Writes the provided ModifyDN request to the underlying connection, blocking
+   * until the request completes.
    *
    * @param change
    *          The {@code ModifyDNRequest} to be written.
    * @return A reference to this connection change record writer.
    * @throws ErrorResultIOException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedIOException
    *           If the current thread was interrupted while waiting.
    * @throws NullPointerException
    *           If {@code change} was {@code null}.
    */
   public ConnectionChangeRecordWriter writeChangeRecord(
-      ModifyDNRequest change) throws ErrorResultIOException,
+      final ModifyDNRequest change) throws ErrorResultIOException,
       InterruptedIOException, NullPointerException
   {
     Validator.ensureNotNull(change);
@@ -257,7 +254,7 @@
     {
       throw new ErrorResultIOException(e);
     }
-    catch (InterruptedException e)
+    catch (final InterruptedException e)
     {
       throw new InterruptedIOException(e.getMessage());
     }
@@ -267,22 +264,22 @@
 
 
   /**
-   * Writes the provided Modify request to the underlying connection,
-   * blocking until the request completes.
+   * Writes the provided Modify request to the underlying connection, blocking
+   * until the request completes.
    *
    * @param change
    *          The {@code ModifyRequest} to be written.
    * @return A reference to this connection change record writer.
    * @throws ErrorResultIOException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedIOException
    *           If the current thread was interrupted while waiting.
    * @throws NullPointerException
    *           If {@code change} was {@code null}.
    */
   public ConnectionChangeRecordWriter writeChangeRecord(
-      ModifyRequest change) throws ErrorResultIOException,
+      final ModifyRequest change) throws ErrorResultIOException,
       InterruptedIOException, NullPointerException
   {
     Validator.ensureNotNull(change);
@@ -294,7 +291,7 @@
     {
       throw new ErrorResultIOException(e);
     }
-    catch (InterruptedException e)
+    catch (final InterruptedException e)
     {
       throw new InterruptedIOException(e.getMessage());
     }
@@ -304,8 +301,8 @@
 
 
   /**
-   * Connection change record writers do not support comments, so the
-   * provided comment will be ignored.
+   * Connection change record writers do not support comments, so the provided
+   * comment will be ignored.
    *
    * @param comment
    *          The {@code CharSequence} to be written as a comment.
@@ -313,7 +310,8 @@
    * @throws NullPointerException
    *           If {@code comment} was {@code null}.
    */
-  public ConnectionChangeRecordWriter writeComment(CharSequence comment)
+  public ConnectionChangeRecordWriter writeComment(final CharSequence comment)
+      throws NullPointerException
   {
     Validator.ensureNotNull(comment);
 
diff --git a/sdk/src/org/opends/sdk/ldif/ConnectionEntryWriter.java b/sdk/src/org/opends/sdk/ldif/ConnectionEntryWriter.java
index 6d29ce4..2e0ab68 100644
--- a/sdk/src/org/opends/sdk/ldif/ConnectionEntryWriter.java
+++ b/sdk/src/org/opends/sdk/ldif/ConnectionEntryWriter.java
@@ -41,17 +41,17 @@
 
 
 /**
- * A {@code ConnectionEntryWriter} is a bridge from {@code Connection}s
- * to {@code EntryWriter}s. A connection entry writer writes entries by
- * sending Add requests to an underlying connection.
+ * A {@code ConnectionEntryWriter} is a bridge from {@code Connection}s to
+ * {@code EntryWriter}s. A connection entry writer writes entries by sending Add
+ * requests to an underlying connection.
  * <p>
- * All Add requests are performed synchronously, blocking until an Add
- * result is received. If an Add result indicates that an Add request
- * has failed for some reason then the error result is propagated to the
- * caller using an {@code ErrorResultIOException}.
+ * All Add requests are performed synchronously, blocking until an Add result is
+ * received. If an Add result indicates that an Add request has failed for some
+ * reason then the error result is propagated to the caller using an {@code
+ * ErrorResultIOException}.
  * <p>
- * <b>Note:</b> comments are not supported by connection change record
- * writers. Attempts to write comments will be ignored.
+ * <b>Note:</b> comments are not supported by connection change record writers.
+ * Attempts to write comments will be ignored.
  */
 public final class ConnectionEntryWriter implements EntryWriter
 {
@@ -60,15 +60,15 @@
 
 
   /**
-   * Creates a new connection entry writer whose destination is the
-   * provided connection.
+   * Creates a new connection entry writer whose destination is the provided
+   * connection.
    *
    * @param connection
    *          The connection to use.
    * @throws NullPointerException
    *           If {@code connection} was {@code null}.
    */
-  public ConnectionEntryWriter(Connection connection)
+  public ConnectionEntryWriter(final Connection connection)
       throws NullPointerException
   {
     Validator.ensureNotNull(connection);
@@ -78,8 +78,8 @@
 
 
   /**
-   * Closes this connection entry writer, including the underlying
-   * connection. Closing a previously closed entry writer has no effect.
+   * Closes this connection entry writer, including the underlying connection.
+   * Closing a previously closed entry writer has no effect.
    */
   public void close()
   {
@@ -89,8 +89,8 @@
 
 
   /**
-   * Connection entry writers do not require flushing, so this method
-   * has no effect.
+   * Connection entry writers do not require flushing, so this method has no
+   * effect.
    */
   public void flush()
   {
@@ -100,8 +100,8 @@
 
 
   /**
-   * Connection entry writers do not support comments, so the provided
-   * comment will be ignored.
+   * Connection entry writers do not support comments, so the provided comment
+   * will be ignored.
    *
    * @param comment
    *          The {@code CharSequence} to be written as a comment.
@@ -109,7 +109,8 @@
    * @throws NullPointerException
    *           If {@code comment} was {@code null}.
    */
-  public ConnectionEntryWriter writeComment(CharSequence comment)
+  public ConnectionEntryWriter writeComment(final CharSequence comment)
+      throws NullPointerException
   {
     Validator.ensureNotNull(comment);
 
@@ -120,21 +121,21 @@
 
 
   /**
-   * Writes an entry to the underlying connection using an Add request,
-   * blocking until the request completes.
+   * Writes an entry to the underlying connection using an Add request, blocking
+   * until the request completes.
    *
    * @param entry
    *          The {@code Entry} to be written.
    * @return A reference to this connection entry writer.
    * @throws ErrorResultIOException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedIOException
    *           If the current thread was interrupted while waiting.
    * @throws NullPointerException
    *           If {@code entry} was {@code null}.
    */
-  public ConnectionEntryWriter writeEntry(Entry entry)
+  public ConnectionEntryWriter writeEntry(final Entry entry)
       throws ErrorResultIOException, InterruptedIOException,
       NullPointerException
   {
@@ -147,7 +148,7 @@
     {
       throw new ErrorResultIOException(e);
     }
-    catch (InterruptedException e)
+    catch (final InterruptedException e)
     {
       throw new InterruptedIOException(e.getMessage());
     }
diff --git a/sdk/src/org/opends/sdk/ldif/EntryReader.java b/sdk/src/org/opends/sdk/ldif/EntryReader.java
index 0a01687..a42c293 100644
--- a/sdk/src/org/opends/sdk/ldif/EntryReader.java
+++ b/sdk/src/org/opends/sdk/ldif/EntryReader.java
@@ -38,14 +38,12 @@
 
 
 /**
- * An interface for reading entries from a data source, typically an
- * LDIF file.
+ * An interface for reading entries from a data source, typically an LDIF file.
  * <p>
  * Implementations must specify the following:
  * <ul>
  * <li>Whether or not it is possible for the implementation to encounter
- * malformed change records and, if it is possible, how they are
- * handled.
+ * malformed change records and, if it is possible, how they are handled.
  * <li>Any synchronization limitations.
  * </ul>
  * <p>
@@ -57,9 +55,9 @@
 {
 
   /**
-   * Closes this entry reader if it is not already closed. Note that
-   * this method does not need to be called if a previous call of
-   * {@link #readEntry()} has returned {@code null}.
+   * Closes this entry reader if it is not already closed. Note that this method
+   * does not need to be called if a previous call of {@link #readEntry()} has
+   * returned {@code null}.
    *
    * @throws IOException
    *           If an unexpected IO error occurred while closing.
@@ -69,17 +67,14 @@
 
 
   /**
-   * Reads the next entry, blocking if necessary until an entry is
-   * available.
+   * Reads the next entry, blocking if necessary until an entry is available.
    *
-   * @return The next entry or {@code null} if there are no more entries
-   *         to be read.
+   * @return The next entry or {@code null} if there are no more entries to be
+   *         read.
    * @throws DecodeException
-   *           If the entry could not be decoded because it was
-   *           malformed.
+   *           If the entry could not be decoded because it was malformed.
    * @throws IOException
-   *           If an unexpected IO error occurred while reading the
-   *           entry.
+   *           If an unexpected IO error occurred while reading the entry.
    */
   Entry readEntry() throws DecodeException, IOException;
 }
diff --git a/sdk/src/org/opends/sdk/ldif/EntryWriter.java b/sdk/src/org/opends/sdk/ldif/EntryWriter.java
index 594a2b6..438268c 100644
--- a/sdk/src/org/opends/sdk/ldif/EntryWriter.java
+++ b/sdk/src/org/opends/sdk/ldif/EntryWriter.java
@@ -38,16 +38,15 @@
 
 
 /**
- * An interface for writing entries to a data source, typically an LDIF
- * file.
+ * An interface for writing entries to a data source, typically an LDIF file.
  * <p>
  * TODO: FilteredChangeRecordWriter
  */
 public interface EntryWriter extends Closeable, Flushable
 {
   /**
-   * Closes this entry writer, flushing it first. Closing a previously
-   * closed entry writer has no effect.
+   * Closes this entry writer, flushing it first. Closing a previously closed
+   * entry writer has no effect.
    *
    * @throws IOException
    *           If an unexpected IO error occurred while closing.
@@ -57,16 +56,14 @@
 
 
   /**
-   * Flushes this entry writer so that any buffered data is written
-   * immediately to underlying stream, flushing the stream if it is also
-   * {@code Flushable}.
+   * Flushes this entry writer so that any buffered data is written immediately
+   * to underlying stream, flushing the stream if it is also {@code Flushable}.
    * <p>
-   * If the intended destination of this stream is an abstraction
-   * provided by the underlying operating system, for example a file,
-   * then flushing the stream guarantees only that bytes previously
-   * written to the stream are passed to the operating system for
-   * writing; it does not guarantee that they are actually written to a
-   * physical device such as a disk drive.
+   * If the intended destination of this stream is an abstraction provided by
+   * the underlying operating system, for example a file, then flushing the
+   * stream guarantees only that bytes previously written to the stream are
+   * passed to the operating system for writing; it does not guarantee that they
+   * are actually written to a physical device such as a disk drive.
    *
    * @throws IOException
    *           If an unexpected IO error occurred while flushing.
@@ -82,8 +79,7 @@
    *          The {@code CharSequence} to be written as a comment.
    * @return A reference to this entry writer.
    * @throws IOException
-   *           If an unexpected IO error occurred while writing the
-   *           comment.
+   *           If an unexpected IO error occurred while writing the comment.
    * @throws NullPointerException
    *           If {@code comment} was {@code null}.
    */
@@ -99,12 +95,10 @@
    *          The {@code Entry} to be written.
    * @return A reference to this entry writer.
    * @throws IOException
-   *           If an unexpected IO error occurred while writing the
-   *           entry.
+   *           If an unexpected IO error occurred while writing the entry.
    * @throws NullPointerException
    *           If {@code entry} was {@code null}.
    */
-  EntryWriter writeEntry(Entry entry) throws IOException,
-      NullPointerException;
+  EntryWriter writeEntry(Entry entry) throws IOException, NullPointerException;
 
 }
diff --git a/sdk/src/org/opends/sdk/ldif/LDIFChangeRecordReader.java b/sdk/src/org/opends/sdk/ldif/LDIFChangeRecordReader.java
index f9dbffb..0825276 100644
--- a/sdk/src/org/opends/sdk/ldif/LDIFChangeRecordReader.java
+++ b/sdk/src/org/opends/sdk/ldif/LDIFChangeRecordReader.java
@@ -30,7 +30,7 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -52,42 +52,39 @@
  * An LDIF change record reader reads change records using the LDAP Data
  * Interchange Format (LDIF) from a user defined source.
  *
- * @see <a href="http://tools.ietf.org/html/rfc2849">RFC 2849 - The LDAP
- *      Data Interchange Format (LDIF) - Technical Specification </a>
+ * @see <a href="http://tools.ietf.org/html/rfc2849">RFC 2849 - The LDAP Data
+ *      Interchange Format (LDIF) - Technical Specification </a>
  */
-public final class LDIFChangeRecordReader extends AbstractLDIFReader
-    implements ChangeRecordReader
+public final class LDIFChangeRecordReader extends AbstractLDIFReader implements
+    ChangeRecordReader
 {
   /**
-   * Parses the provided array of LDIF lines as a single LDIF change
-   * record.
+   * Parses the provided array of LDIF lines as a single LDIF change record.
    *
    * @param ldifLines
    *          The lines of LDIF to be parsed.
    * @return The parsed LDIF change record.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code ldifLines} did not contain an LDIF change
-   *           record, if it contained multiple change records, if
-   *           contained malformed LDIF, or if the change record could
-   *           not be decoded using the default schema.
+   *           If {@code ldifLines} did not contain an LDIF change record, if it
+   *           contained multiple change records, if contained malformed LDIF,
+   *           or if the change record could not be decoded using the default
+   *           schema.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null}.
    */
-  public static ChangeRecord valueOfLDIFChangeRecord(
-      String... ldifLines) throws LocalizedIllegalArgumentException,
-      NullPointerException
+  public static ChangeRecord valueOfLDIFChangeRecord(final String... ldifLines)
+      throws LocalizedIllegalArgumentException, NullPointerException
   {
     // LDIF change record reader is tolerant to missing change types.
-    LDIFChangeRecordReader reader = new LDIFChangeRecordReader(
-        ldifLines);
+    final LDIFChangeRecordReader reader = new LDIFChangeRecordReader(ldifLines);
     try
     {
-      ChangeRecord record = reader.readChangeRecord();
+      final ChangeRecord record = reader.readChangeRecord();
 
       if (record == null)
       {
         // No change record found.
-        LocalizableMessage message = WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND
+        final LocalizableMessage message = WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND
             .get();
         throw new LocalizedIllegalArgumentException(message);
       }
@@ -95,23 +92,23 @@
       if (reader.readChangeRecord() != null)
       {
         // Multiple change records found.
-        LocalizableMessage message = WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND
+        final LocalizableMessage message = WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND
             .get();
         throw new LocalizedIllegalArgumentException(message);
       }
 
       return record;
     }
-    catch (DecodeException e)
+    catch (final DecodeException e)
     {
       // Badly formed LDIF.
       throw new LocalizedIllegalArgumentException(e.getMessageObject());
     }
-    catch (IOException e)
+    catch (final IOException e)
     {
       // This should never happen for a String based reader.
-      LocalizableMessage message = WARN_READ_LDIF_RECORD_UNEXPECTED_IO_ERROR.get(e
-          .getMessage());
+      final LocalizableMessage message = WARN_READ_LDIF_RECORD_UNEXPECTED_IO_ERROR
+          .get(e.getMessage());
       throw new LocalizedIllegalArgumentException(message);
     }
   }
@@ -119,15 +116,15 @@
 
 
   /**
-   * Creates a new LDIF change record reader whose source is the
-   * provided input stream.
+   * Creates a new LDIF change record reader whose source is the provided input
+   * stream.
    *
    * @param in
    *          The input stream to use.
    * @throws NullPointerException
    *           If {@code in} was {@code null}.
    */
-  public LDIFChangeRecordReader(InputStream in)
+  public LDIFChangeRecordReader(final InputStream in)
       throws NullPointerException
   {
     super(in);
@@ -136,15 +133,15 @@
 
 
   /**
-   * Creates a new LDIF change record reader which will read lines of
-   * LDIF from the provided list of LDIF lines.
+   * Creates a new LDIF change record reader which will read lines of LDIF from
+   * the provided list of LDIF lines.
    *
    * @param ldifLines
    *          The lines of LDIF to be read.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null}.
    */
-  public LDIFChangeRecordReader(List<String> ldifLines)
+  public LDIFChangeRecordReader(final List<String> ldifLines)
       throws NullPointerException
   {
     super(ldifLines);
@@ -153,15 +150,15 @@
 
 
   /**
-   * Creates a new LDIF change record reader which will read lines of
-   * LDIF from the provided array of LDIF lines.
+   * Creates a new LDIF change record reader which will read lines of LDIF from
+   * the provided array of LDIF lines.
    *
    * @param ldifLines
    *          The lines of LDIF to be read.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null}.
    */
-  public LDIFChangeRecordReader(String... ldifLines)
+  public LDIFChangeRecordReader(final String... ldifLines)
       throws NullPointerException
   {
     super(Arrays.asList(ldifLines));
@@ -182,8 +179,7 @@
   /**
    * {@inheritDoc}
    */
-  public ChangeRecord readChangeRecord() throws DecodeException,
-      IOException
+  public ChangeRecord readChangeRecord() throws DecodeException, IOException
   {
     // Continue until an unfiltered entry is obtained.
     while (true)
@@ -230,27 +226,25 @@
         if (!record.iterator.hasNext())
         {
           // FIXME: improve error.
-          final LocalizableMessage message = LocalizableMessage.raw("Missing changetype");
+          final LocalizableMessage message = LocalizableMessage
+              .raw("Missing changetype");
           throw DecodeException.error(message);
         }
 
         final KeyValuePair pair = new KeyValuePair();
-        final String ldifLine = readLDIFRecordKeyValuePair(record,
-            pair, false);
+        final String ldifLine = readLDIFRecordKeyValuePair(record, pair, false);
 
         if (!toLowerCase(pair.key).equals("changetype"))
         {
           // Default to add change record.
-          changeRecord = parseAddChangeRecordEntry(entryDN, ldifLine,
-              record);
+          changeRecord = parseAddChangeRecordEntry(entryDN, ldifLine, record);
         }
         else
         {
           final String changeType = toLowerCase(pair.value);
           if (changeType.equals("add"))
           {
-            changeRecord = parseAddChangeRecordEntry(entryDN, null,
-                record);
+            changeRecord = parseAddChangeRecordEntry(entryDN, null, record);
           }
           else if (changeType.equals("delete"))
           {
@@ -262,13 +256,11 @@
           }
           else if (changeType.equals("modrdn"))
           {
-            changeRecord = parseModifyDNChangeRecordEntry(entryDN,
-                record);
+            changeRecord = parseModifyDNChangeRecordEntry(entryDN, record);
           }
           else if (changeType.equals("moddn"))
           {
-            changeRecord = parseModifyDNChangeRecordEntry(entryDN,
-                record);
+            changeRecord = parseModifyDNChangeRecordEntry(entryDN, record);
           }
           else
           {
@@ -295,17 +287,16 @@
 
 
   /**
-   * Specifies whether or not all operational attributes should be
-   * excluded from any change records that are read from LDIF. The
-   * default is {@code false}.
+   * Specifies whether or not all operational attributes should be excluded from
+   * any change records that are read from LDIF. The default is {@code false}.
    *
    * @param excludeOperationalAttributes
-   *          {@code true} if all operational attributes should be
-   *          excluded, or {@code false} otherwise.
+   *          {@code true} if all operational attributes should be excluded, or
+   *          {@code false} otherwise.
    * @return A reference to this {@code LDIFChangeRecordReader}.
    */
   public LDIFChangeRecordReader setExcludeAllOperationalAttributes(
-      boolean excludeOperationalAttributes)
+      final boolean excludeOperationalAttributes)
   {
     this.excludeOperationalAttributes = excludeOperationalAttributes;
     return this;
@@ -314,17 +305,16 @@
 
 
   /**
-   * Specifies whether or not all user attributes should be excluded
-   * from any change records that are read from LDIF. The default is
-   * {@code false}.
+   * Specifies whether or not all user attributes should be excluded from any
+   * change records that are read from LDIF. The default is {@code false}.
    *
    * @param excludeUserAttributes
-   *          {@code true} if all user attributes should be excluded, or
-   *          {@code false} otherwise.
+   *          {@code true} if all user attributes should be excluded, or {@code
+   *          false} otherwise.
    * @return A reference to this {@code LDIFChangeRecordReader}.
    */
   public LDIFChangeRecordReader setExcludeAllUserAttributes(
-      boolean excludeUserAttributes)
+      final boolean excludeUserAttributes)
   {
     this.excludeUserAttributes = excludeUserAttributes;
     return this;
@@ -333,16 +323,15 @@
 
 
   /**
-   * Excludes the named attribute from any change records that are read
-   * from LDIF. By default all attributes are included unless explicitly
-   * excluded.
+   * Excludes the named attribute from any change records that are read from
+   * LDIF. By default all attributes are included unless explicitly excluded.
    *
    * @param attributeDescription
    *          The name of the attribute to be excluded.
    * @return A reference to this {@code LDIFChangeRecordReader}.
    */
   public LDIFChangeRecordReader setExcludeAttribute(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
   {
     Validator.ensureNotNull(attributeDescription);
     excludeAttributes.add(attributeDescription);
@@ -352,15 +341,15 @@
 
 
   /**
-   * Excludes all change records which target entries beneath the named
-   * entry (inclusive) from being read from LDIF. By default all change
-   * records are read unless explicitly excluded or included.
+   * Excludes all change records which target entries beneath the named entry
+   * (inclusive) from being read from LDIF. By default all change records are
+   * read unless explicitly excluded or included.
    *
    * @param excludeBranch
    *          The distinguished name of the branch to be excluded.
    * @return A reference to this {@code LDIFChangeRecordReader}.
    */
-  public LDIFChangeRecordReader setExcludeBranch(DN excludeBranch)
+  public LDIFChangeRecordReader setExcludeBranch(final DN excludeBranch)
   {
     Validator.ensureNotNull(excludeBranch);
     excludeBranches.add(excludeBranch);
@@ -370,16 +359,16 @@
 
 
   /**
-   * Ensures that the named attribute is not excluded from any change
-   * records that are read from LDIF. By default all attributes are
-   * included unless explicitly excluded.
+   * Ensures that the named attribute is not excluded from any change records
+   * that are read from LDIF. By default all attributes are included unless
+   * explicitly excluded.
    *
    * @param attributeDescription
    *          The name of the attribute to be included.
    * @return A reference to this {@code LDIFChangeRecordReader}.
    */
   public LDIFChangeRecordReader setIncludeAttribute(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
   {
     Validator.ensureNotNull(attributeDescription);
     includeAttributes.add(attributeDescription);
@@ -389,15 +378,15 @@
 
 
   /**
-   * Ensures that all change records which target entries beneath the
-   * named entry (inclusive) are read from LDIF. By default all change
-   * records are read unless explicitly excluded or included.
+   * Ensures that all change records which target entries beneath the named
+   * entry (inclusive) are read from LDIF. By default all change records are
+   * read unless explicitly excluded or included.
    *
    * @param includeBranch
    *          The distinguished name of the branch to be included.
    * @return A reference to this {@code LDIFChangeRecordReader}.
    */
-  public LDIFChangeRecordReader setIncludeBranch(DN includeBranch)
+  public LDIFChangeRecordReader setIncludeBranch(final DN includeBranch)
   {
     Validator.ensureNotNull(includeBranch);
     includeBranches.add(includeBranch);
@@ -407,16 +396,15 @@
 
 
   /**
-   * Sets the schema which should be used for decoding change records
-   * that are read from LDIF. The default schema is used if no other is
-   * specified.
+   * Sets the schema which should be used for decoding change records that are
+   * read from LDIF. The default schema is used if no other is specified.
    *
    * @param schema
-   *          The schema which should be used for decoding change
-   *          records that are read from LDIF.
+   *          The schema which should be used for decoding change records that
+   *          are read from LDIF.
    * @return A reference to this {@code LDIFChangeRecordReader}.
    */
-  public LDIFChangeRecordReader setSchema(Schema schema)
+  public LDIFChangeRecordReader setSchema(final Schema schema)
   {
     Validator.ensureNotNull(schema);
     this.schema = schema;
@@ -426,16 +414,15 @@
 
 
   /**
-   * Specifies whether or not schema validation should be performed for
-   * change records that are read from LDIF. The default is {@code true}
-   * .
+   * Specifies whether or not schema validation should be performed for change
+   * records that are read from LDIF. The default is {@code true} .
    *
    * @param validateSchema
-   *          {@code true} if schema validation should be performed, or
-   *          {@code false} otherwise.
+   *          {@code true} if schema validation should be performed, or {@code
+   *          false} otherwise.
    * @return A reference to this {@code LDIFChangeRecordReader}.
    */
-  public LDIFChangeRecordReader setValidateSchema(boolean validateSchema)
+  public LDIFChangeRecordReader setValidateSchema(final boolean validateSchema)
   {
     this.validateSchema = validateSchema;
     return this;
@@ -443,11 +430,12 @@
 
 
 
-  private ChangeRecord parseAddChangeRecordEntry(DN entryDN,
-      String lastLDIFLine, LDIFRecord record) throws DecodeException
+  private ChangeRecord parseAddChangeRecordEntry(final DN entryDN,
+      final String lastLDIFLine, final LDIFRecord record)
+      throws DecodeException
   {
     // Use an Entry for the AttributeSequence.
-    final Entry entry = new SortedEntry(entryDN);
+    final Entry entry = new LinkedHashMapEntry(entryDN);
 
     if (lastLDIFLine != null)
     {
@@ -466,13 +454,14 @@
 
 
 
-  private ChangeRecord parseDeleteChangeRecordEntry(DN entryDN,
-      LDIFRecord record) throws DecodeException
+  private ChangeRecord parseDeleteChangeRecordEntry(final DN entryDN,
+      final LDIFRecord record) throws DecodeException
   {
     if (record.iterator.hasNext())
     {
       // FIXME: include line number in error.
-      final LocalizableMessage message = ERR_LDIF_INVALID_DELETE_ATTRIBUTES.get();
+      final LocalizableMessage message = ERR_LDIF_INVALID_DELETE_ATTRIBUTES
+          .get();
       throw DecodeException.error(message);
     }
 
@@ -481,11 +470,10 @@
 
 
 
-  private ChangeRecord parseModifyChangeRecordEntry(DN entryDN,
-      LDIFRecord record) throws DecodeException
+  private ChangeRecord parseModifyChangeRecordEntry(final DN entryDN,
+      final LDIFRecord record) throws DecodeException
   {
-    final ModifyRequest modifyRequest = Requests
-        .newModifyRequest(entryDN);
+    final ModifyRequest modifyRequest = Requests.newModifyRequest(entryDN);
 
     final KeyValuePair pair = new KeyValuePair();
     final List<ByteString> attributeValues = new ArrayList<ByteString>();
@@ -515,16 +503,15 @@
       else
       {
         // FIXME: improve error.
-        final LocalizableMessage message = ERR_LDIF_INVALID_MODIFY_ATTRIBUTE.get(
-            pair.key, "add, delete, replace, increment");
+        final LocalizableMessage message = ERR_LDIF_INVALID_MODIFY_ATTRIBUTE
+            .get(pair.key, "add, delete, replace, increment");
         throw DecodeException.error(message);
       }
 
       AttributeDescription attributeDescription;
       try
       {
-        attributeDescription = AttributeDescription.valueOf(pair.value,
-            schema);
+        attributeDescription = AttributeDescription.valueOf(pair.value, schema);
       }
       catch (final LocalizedIllegalArgumentException e)
       {
@@ -543,8 +530,7 @@
       if (!attributeDescription.getAttributeType().getSyntax()
           .isBEREncodingRequired())
       {
-        if (validateSchema
-            && attributeDescription.containsOption("binary"))
+        if (validateSchema && attributeDescription.containsOption("binary"))
         {
           final LocalizableMessage message = ERR_LDIF_INVALID_ATTR_OPTION.get(
               entryDN.toString(), record.lineNumber, pair.value);
@@ -575,8 +561,8 @@
         AttributeDescription attributeDescription2;
         try
         {
-          attributeDescription2 = AttributeDescription.valueOf(
-              attrDescr, schema);
+          attributeDescription2 = AttributeDescription.valueOf(attrDescr,
+              schema);
         }
         catch (final LocalizedIllegalArgumentException e)
         {
@@ -595,8 +581,8 @@
         {
           // TODO: include line number.
           final LocalizableMessage message = ERR_LDIF_INVALID_CHANGERECORD_ATTRIBUTE
-              .get(attributeDescription2.toString(),
-                  attributeDescription.toString());
+              .get(attributeDescription2.toString(), attributeDescription
+                  .toString());
           throw DecodeException.error(message);
         }
 
@@ -605,9 +591,9 @@
             colonPos, attrDescr));
       }
 
-      Change change = new Change(modType, new LinkedAttribute(
-          attributeDescription, attributeValues));
-      modifyRequest.addChange(change);
+      final Modification change = new Modification(modType,
+          new LinkedAttribute(attributeDescription, attributeValues));
+      modifyRequest.addModification(change);
     }
 
     return modifyRequest;
@@ -615,8 +601,8 @@
 
 
 
-  private ChangeRecord parseModifyDNChangeRecordEntry(DN entryDN,
-      LDIFRecord record) throws DecodeException
+  private ChangeRecord parseModifyDNChangeRecordEntry(final DN entryDN,
+      final LDIFRecord record) throws DecodeException
   {
     ModifyDNRequest modifyDNRequest;
 
@@ -634,7 +620,8 @@
     if (!toLowerCase(pair.key).equals("newrdn"))
     {
       // FIXME: improve error.
-      final LocalizableMessage message = LocalizableMessage.raw("Missing newrdn");
+      final LocalizableMessage message = LocalizableMessage
+          .raw("Missing newrdn");
       throw DecodeException.error(message);
     }
 
@@ -654,7 +641,8 @@
     if (!record.iterator.hasNext())
     {
       // TODO: include line number.
-      final LocalizableMessage message = ERR_LDIF_NO_DELETE_OLDRDN_ATTRIBUTE.get();
+      final LocalizableMessage message = ERR_LDIF_NO_DELETE_OLDRDN_ATTRIBUTE
+          .get();
       throw DecodeException.error(message);
     }
 
@@ -663,13 +651,13 @@
     if (!toLowerCase(pair.key).equals("deleteoldrdn"))
     {
       // FIXME: improve error.
-      final LocalizableMessage message = LocalizableMessage.raw("Missing deleteoldrdn");
+      final LocalizableMessage message = LocalizableMessage
+          .raw("Missing deleteoldrdn");
       throw DecodeException.error(message);
     }
 
     final String delStr = toLowerCase(pair.value);
-    if (delStr.equals("false") || delStr.equals("no")
-        || delStr.equals("0"))
+    if (delStr.equals("false") || delStr.equals("no") || delStr.equals("0"))
     {
       modifyDNRequest.setDeleteOldRDN(false);
     }
@@ -694,7 +682,8 @@
       if (!toLowerCase(pair.key).equals("newsuperior"))
       {
         // FIXME: improve error.
-        final LocalizableMessage message = LocalizableMessage.raw("Missing newsuperior");
+        final LocalizableMessage message = LocalizableMessage
+            .raw("Missing newsuperior");
         throw DecodeException.error(message);
       }
 
diff --git a/sdk/src/org/opends/sdk/ldif/LDIFChangeRecordWriter.java b/sdk/src/org/opends/sdk/ldif/LDIFChangeRecordWriter.java
index 188af66..b5862ff 100644
--- a/sdk/src/org/opends/sdk/ldif/LDIFChangeRecordWriter.java
+++ b/sdk/src/org/opends/sdk/ldif/LDIFChangeRecordWriter.java
@@ -45,24 +45,24 @@
 
 
 /**
- * An LDIF change record writer writes change records using the LDAP
- * Data Interchange Format (LDIF) to a user defined destination.
+ * An LDIF change record writer writes change records using the LDAP Data
+ * Interchange Format (LDIF) to a user defined destination.
  *
- * @see <a href="http://tools.ietf.org/html/rfc2849">RFC 2849 - The LDAP
- *      Data Interchange Format (LDIF) - Technical Specification </a>
+ * @see <a href="http://tools.ietf.org/html/rfc2849">RFC 2849 - The LDAP Data
+ *      Interchange Format (LDIF) - Technical Specification </a>
  */
-public final class LDIFChangeRecordWriter extends AbstractLDIFWriter
-    implements ChangeRecordWriter
+public final class LDIFChangeRecordWriter extends AbstractLDIFWriter implements
+    ChangeRecordWriter
 {
 
   /**
-   * Creates a new LDIF change record writer which will append lines of
-   * LDIF to the provided list.
+   * Creates a new LDIF change record writer which will append lines of LDIF to
+   * the provided list.
    *
    * @param ldifLines
    *          The list to which lines of LDIF should be appended.
    */
-  public LDIFChangeRecordWriter(List<String> ldifLines)
+  public LDIFChangeRecordWriter(final List<String> ldifLines)
   {
     super(ldifLines);
   }
@@ -70,13 +70,13 @@
 
 
   /**
-   * Creates a new LDIF change record writer whose destination is the
-   * provided output stream.
+   * Creates a new LDIF change record writer whose destination is the provided
+   * output stream.
    *
    * @param out
    *          The output stream to use.
    */
-  public LDIFChangeRecordWriter(OutputStream out)
+  public LDIFChangeRecordWriter(final OutputStream out)
   {
     super(out);
   }
@@ -104,18 +104,17 @@
 
 
   /**
-   * Specifies whether or not user-friendly comments should be added
-   * whenever distinguished names or UTF-8 attribute values are
-   * encountered which contained non-ASCII characters. The default is
-   * {@code false}.
+   * Specifies whether or not user-friendly comments should be added whenever
+   * distinguished names or UTF-8 attribute values are encountered which
+   * contained non-ASCII characters. The default is {@code false}.
    *
    * @param addUserFriendlyComments
-   *          {@code true} if user-friendly comments should be added, or
-   *          {@code false} otherwise.
+   *          {@code true} if user-friendly comments should be added, or {@code
+   *          false} otherwise.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
   public LDIFChangeRecordWriter setAddUserFriendlyComments(
-      boolean addUserFriendlyComments)
+      final boolean addUserFriendlyComments)
   {
     this.addUserFriendlyComments = addUserFriendlyComments;
     return this;
@@ -124,17 +123,16 @@
 
 
   /**
-   * Specifies whether or not all operational attributes should be
-   * excluded from any change records that are written to LDIF. The
-   * default is {@code false}.
+   * Specifies whether or not all operational attributes should be excluded from
+   * any change records that are written to LDIF. The default is {@code false}.
    *
    * @param excludeOperationalAttributes
-   *          {@code true} if all operational attributes should be
-   *          excluded, or {@code false} otherwise.
+   *          {@code true} if all operational attributes should be excluded, or
+   *          {@code false} otherwise.
    * @return A reference to this {@code LDIFChangeRecordWriter}.
    */
   public LDIFChangeRecordWriter setExcludeAllOperationalAttributes(
-      boolean excludeOperationalAttributes)
+      final boolean excludeOperationalAttributes)
   {
     this.excludeOperationalAttributes = excludeOperationalAttributes;
     return this;
@@ -143,17 +141,16 @@
 
 
   /**
-   * Specifies whether or not all user attributes should be excluded
-   * from any change records that are written to LDIF. The default is
-   * {@code false}.
+   * Specifies whether or not all user attributes should be excluded from any
+   * change records that are written to LDIF. The default is {@code false}.
    *
    * @param excludeUserAttributes
-   *          {@code true} if all user attributes should be excluded, or
-   *          {@code false} otherwise.
+   *          {@code true} if all user attributes should be excluded, or {@code
+   *          false} otherwise.
    * @return A reference to this {@code LDIFChangeRecordWriter}.
    */
   public LDIFChangeRecordWriter setExcludeAllUserAttributes(
-      boolean excludeUserAttributes)
+      final boolean excludeUserAttributes)
   {
     this.excludeUserAttributes = excludeUserAttributes;
     return this;
@@ -162,16 +159,15 @@
 
 
   /**
-   * Excludes the named attribute from any change records that are
-   * written to LDIF. By default all attributes are included unless
-   * explicitly excluded.
+   * Excludes the named attribute from any change records that are written to
+   * LDIF. By default all attributes are included unless explicitly excluded.
    *
    * @param attributeDescription
    *          The name of the attribute to be excluded.
    * @return A reference to this {@code LDIFChangeRecordWriter}.
    */
   public LDIFChangeRecordWriter setExcludeAttribute(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
   {
     Validator.ensureNotNull(attributeDescription);
     excludeAttributes.add(attributeDescription);
@@ -181,15 +177,15 @@
 
 
   /**
-   * Excludes all change records which target entries beneath the named
-   * entry (inclusive) from being written to LDIF. By default all change
-   * records are written unless explicitly excluded or included.
+   * Excludes all change records which target entries beneath the named entry
+   * (inclusive) from being written to LDIF. By default all change records are
+   * written unless explicitly excluded or included.
    *
    * @param excludeBranch
    *          The distinguished name of the branch to be excluded.
    * @return A reference to this {@code LDIFChangeRecordWriter}.
    */
-  public LDIFChangeRecordWriter setExcludeBranch(DN excludeBranch)
+  public LDIFChangeRecordWriter setExcludeBranch(final DN excludeBranch)
   {
     Validator.ensureNotNull(excludeBranch);
     excludeBranches.add(excludeBranch);
@@ -199,16 +195,16 @@
 
 
   /**
-   * Ensures that the named attribute is not excluded from any change
-   * records that are written to LDIF. By default all attributes are
-   * included unless explicitly excluded.
+   * Ensures that the named attribute is not excluded from any change records
+   * that are written to LDIF. By default all attributes are included unless
+   * explicitly excluded.
    *
    * @param attributeDescription
    *          The name of the attribute to be included.
    * @return A reference to this {@code LDIFChangeRecordWriter}.
    */
   public LDIFChangeRecordWriter setIncludeAttribute(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
   {
     Validator.ensureNotNull(attributeDescription);
     includeAttributes.add(attributeDescription);
@@ -218,15 +214,15 @@
 
 
   /**
-   * Ensures that all change records which target entries beneath the
-   * named entry (inclusive) are written to LDIF. By default all change
-   * records are written unless explicitly excluded or included.
+   * Ensures that all change records which target entries beneath the named
+   * entry (inclusive) are written to LDIF. By default all change records are
+   * written unless explicitly excluded or included.
    *
    * @param includeBranch
    *          The distinguished name of the branch to be included.
    * @return A reference to this {@code LDIFChangeRecordWriter}.
    */
-  public LDIFChangeRecordWriter setIncludeBranch(DN includeBranch)
+  public LDIFChangeRecordWriter setIncludeBranch(final DN includeBranch)
   {
     Validator.ensureNotNull(includeBranch);
     includeBranches.add(includeBranch);
@@ -236,16 +232,15 @@
 
 
   /**
-   * Sets the schema which should be used when filtering change records
-   * (not required if no filtering is to be performed). The default
-   * schema is used if no other is specified.
+   * Sets the schema which should be used when filtering change records (not
+   * required if no filtering is to be performed). The default schema is used if
+   * no other is specified.
    *
    * @param schema
-   *          The schema which should be used when filtering change
-   *          records.
+   *          The schema which should be used when filtering change records.
    * @return A reference to this {@code LDIFChangeRecordWriter}.
    */
-  public LDIFChangeRecordWriter setSchema(Schema schema)
+  public LDIFChangeRecordWriter setSchema(final Schema schema)
   {
     Validator.ensureNotNull(schema);
     this.schema = schema;
@@ -255,15 +250,15 @@
 
 
   /**
-   * Specifies the column at which long lines should be wrapped. A value
-   * less than or equal to zero (the default) indicates that no wrapping
-   * should be performed.
+   * Specifies the column at which long lines should be wrapped. A value less
+   * than or equal to zero (the default) indicates that no wrapping should be
+   * performed.
    *
    * @param wrapColumn
    *          The column at which long lines should be wrapped.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
-  public LDIFChangeRecordWriter setWrapColumn(int wrapColumn)
+  public LDIFChangeRecordWriter setWrapColumn(final int wrapColumn)
   {
     this.wrapColumn = wrapColumn;
     return this;
@@ -274,7 +269,7 @@
   /**
    * {@inheritDoc}
    */
-  public LDIFChangeRecordWriter writeChangeRecord(AddRequest change)
+  public LDIFChangeRecordWriter writeChangeRecord(final AddRequest change)
       throws IOException, NullPointerException
   {
     Validator.ensureNotNull(change);
@@ -288,7 +283,7 @@
     writeKeyAndValue("dn", change.getName().toString());
     writeControls(change.getControls());
     writeLine("changetype: add");
-    for (final Attribute attribute : change.getAttributes())
+    for (final Attribute attribute : change.getAllAttributes())
     {
       // Filter the attribute if required.
       if (isAttributeExcluded(attribute.getAttributeDescription()))
@@ -296,8 +291,8 @@
         continue;
       }
 
-      final String attributeDescription =
-          attribute.getAttributeDescriptionAsString();
+      final String attributeDescription = attribute
+          .getAttributeDescriptionAsString();
       for (final ByteString value : attribute)
       {
         writeKeyAndValue(attributeDescription, value);
@@ -315,7 +310,7 @@
   /**
    * {@inheritDoc}
    */
-  public LDIFChangeRecordWriter writeChangeRecord(ChangeRecord change)
+  public LDIFChangeRecordWriter writeChangeRecord(final ChangeRecord change)
       throws IOException, NullPointerException
   {
     Validator.ensureNotNull(change);
@@ -326,8 +321,8 @@
       return this;
     }
 
-    final IOException e =
-        change.accept(ChangeRecordVisitorWriter.getInstance(), this);
+    final IOException e = change.accept(
+        ChangeRecordVisitorWriter.getInstance(), this);
     if (e != null)
     {
       throw e;
@@ -343,7 +338,7 @@
   /**
    * {@inheritDoc}
    */
-  public LDIFChangeRecordWriter writeChangeRecord(DeleteRequest change)
+  public LDIFChangeRecordWriter writeChangeRecord(final DeleteRequest change)
       throws IOException, NullPointerException
   {
     Validator.ensureNotNull(change);
@@ -369,7 +364,7 @@
   /**
    * {@inheritDoc}
    */
-  public LDIFChangeRecordWriter writeChangeRecord(ModifyDNRequest change)
+  public LDIFChangeRecordWriter writeChangeRecord(final ModifyDNRequest change)
       throws IOException, NullPointerException
   {
     Validator.ensureNotNull(change);
@@ -396,12 +391,10 @@
     }
 
     writeKeyAndValue("newrdn", change.getNewRDN().toString());
-    writeKeyAndValue("deleteoldrdn", change.isDeleteOldRDN() ? "1"
-        : "0");
+    writeKeyAndValue("deleteoldrdn", change.isDeleteOldRDN() ? "1" : "0");
     if (change.getNewSuperior() != null)
     {
-      writeKeyAndValue("newsuperior", change.getNewSuperior()
-          .toString());
+      writeKeyAndValue("newsuperior", change.getNewSuperior().toString());
     }
 
     // Make sure there is a blank line after the entry.
@@ -415,13 +408,13 @@
   /**
    * {@inheritDoc}
    */
-  public LDIFChangeRecordWriter writeChangeRecord(ModifyRequest change)
+  public LDIFChangeRecordWriter writeChangeRecord(final ModifyRequest change)
       throws IOException, NullPointerException
   {
     Validator.ensureNotNull(change);
 
     // If there aren't any modifications, then there's nothing to do.
-    if (!change.hasChanges())
+    if (change.getModifications().isEmpty())
     {
       return this;
     }
@@ -436,12 +429,12 @@
     writeControls(change.getControls());
     writeLine("changetype: modify");
 
-    for (final Change modification : change.getChanges())
+    for (final Modification modification : change.getModifications())
     {
       final ModificationType type = modification.getModificationType();
       final Attribute attribute = modification.getAttribute();
-      final String attributeDescription =
-          attribute.getAttributeDescriptionAsString();
+      final String attributeDescription = attribute
+          .getAttributeDescriptionAsString();
 
       // Filter the attribute if required.
       if (isAttributeExcluded(attribute.getAttributeDescription()))
@@ -468,7 +461,7 @@
   /**
    * {@inheritDoc}
    */
-  public LDIFChangeRecordWriter writeComment(CharSequence comment)
+  public LDIFChangeRecordWriter writeComment(final CharSequence comment)
       throws IOException, NullPointerException
   {
     writeComment0(comment);
diff --git a/sdk/src/org/opends/sdk/ldif/LDIFEntryReader.java b/sdk/src/org/opends/sdk/ldif/LDIFEntryReader.java
index a0a886d..4eb257c 100644
--- a/sdk/src/org/opends/sdk/ldif/LDIFEntryReader.java
+++ b/sdk/src/org/opends/sdk/ldif/LDIFEntryReader.java
@@ -29,7 +29,12 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.
+  WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND;
+import static com.sun.opends.sdk.messages.Messages.
+  WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND;
+import static com.sun.opends.sdk.messages.Messages.
+  WARN_READ_LDIF_RECORD_UNEXPECTED_IO_ERROR;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -44,11 +49,11 @@
 
 
 /**
- * An LDIF entry reader reads attribute value records (entries) using
- * the LDAP Data Interchange Format (LDIF) from a user defined source.
+ * An LDIF entry reader reads attribute value records (entries) using the LDAP
+ * Data Interchange Format (LDIF) from a user defined source.
  *
- * @see <a href="http://tools.ietf.org/html/rfc2849">RFC 2849 - The LDAP
- *      Data Interchange Format (LDIF) - Technical Specification </a>
+ * @see <a href="http://tools.ietf.org/html/rfc2849">RFC 2849 - The LDAP Data
+ *      Interchange Format (LDIF) - Technical Specification </a>
  */
 public final class LDIFEntryReader extends AbstractLDIFReader implements
     EntryReader
@@ -61,24 +66,23 @@
    * @return The parsed LDIF entry.
    * @throws LocalizedIllegalArgumentException
    *           If {@code ldifLines} did not contain an LDIF entry, if it
-   *           contained multiple entries, if contained malformed LDIF,
-   *           or if the entry could not be decoded using the default
-   *           schema.
+   *           contained multiple entries, if contained malformed LDIF, or if
+   *           the entry could not be decoded using the default schema.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null}.
    */
-  public static Entry valueOfLDIFEntry(String... ldifLines)
+  public static Entry valueOfLDIFEntry(final String... ldifLines)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
-    LDIFEntryReader reader = new LDIFEntryReader(ldifLines);
+    final LDIFEntryReader reader = new LDIFEntryReader(ldifLines);
     try
     {
-      Entry entry = reader.readEntry();
+      final Entry entry = reader.readEntry();
 
       if (entry == null)
       {
         // No change record found.
-        LocalizableMessage message = WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND
+        final LocalizableMessage message = WARN_READ_LDIF_RECORD_NO_CHANGE_RECORD_FOUND
             .get();
         throw new LocalizedIllegalArgumentException(message);
       }
@@ -86,23 +90,23 @@
       if (reader.readEntry() != null)
       {
         // Multiple change records found.
-        LocalizableMessage message = WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND
+        final LocalizableMessage message = WARN_READ_LDIF_RECORD_MULTIPLE_CHANGE_RECORDS_FOUND
             .get();
         throw new LocalizedIllegalArgumentException(message);
       }
 
       return entry;
     }
-    catch (DecodeException e)
+    catch (final DecodeException e)
     {
       // Badly formed LDIF.
       throw new LocalizedIllegalArgumentException(e.getMessageObject());
     }
-    catch (IOException e)
+    catch (final IOException e)
     {
       // This should never happen for a String based reader.
-      LocalizableMessage message = WARN_READ_LDIF_RECORD_UNEXPECTED_IO_ERROR.get(e
-          .getMessage());
+      final LocalizableMessage message = WARN_READ_LDIF_RECORD_UNEXPECTED_IO_ERROR
+          .get(e.getMessage());
       throw new LocalizedIllegalArgumentException(message);
     }
   }
@@ -110,15 +114,14 @@
 
 
   /**
-   * Creates a new LDIF entry reader whose source is the provided input
-   * stream.
+   * Creates a new LDIF entry reader whose source is the provided input stream.
    *
    * @param in
    *          The input stream to use.
    * @throws NullPointerException
    *           If {@code in} was {@code null}.
    */
-  public LDIFEntryReader(InputStream in) throws NullPointerException
+  public LDIFEntryReader(final InputStream in) throws NullPointerException
   {
     super(in);
   }
@@ -126,15 +129,15 @@
 
 
   /**
-   * Creates a new LDIF entry reader which will read lines of LDIF from
-   * the provided list of LDIF lines.
+   * Creates a new LDIF entry reader which will read lines of LDIF from the
+   * provided list of LDIF lines.
    *
    * @param ldifLines
    *          The lines of LDIF to be read.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null}.
    */
-  public LDIFEntryReader(List<String> ldifLines)
+  public LDIFEntryReader(final List<String> ldifLines)
       throws NullPointerException
   {
     super(ldifLines);
@@ -143,16 +146,15 @@
 
 
   /**
-   * Creates a new LDIF entry reader which will read lines of LDIF from
-   * the provided array of LDIF lines.
+   * Creates a new LDIF entry reader which will read lines of LDIF from the
+   * provided array of LDIF lines.
    *
    * @param ldifLines
    *          The lines of LDIF to be read.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null}.
    */
-  public LDIFEntryReader(String... ldifLines)
-      throws NullPointerException
+  public LDIFEntryReader(final String... ldifLines) throws NullPointerException
   {
     super(Arrays.asList(ldifLines));
   }
@@ -214,7 +216,7 @@
       }
 
       // Use an Entry for the AttributeSequence.
-      final Entry entry = new SortedEntry(entryDN);
+      final Entry entry = new LinkedHashMapEntry(entryDN);
       try
       {
         while (record.iterator.hasNext())
@@ -245,17 +247,16 @@
 
 
   /**
-   * Specifies whether or not all operational attributes should be
-   * excluded from any entries that are read from LDIF. The default is
-   * {@code false}.
+   * Specifies whether or not all operational attributes should be excluded from
+   * any entries that are read from LDIF. The default is {@code false}.
    *
    * @param excludeOperationalAttributes
-   *          {@code true} if all operational attributes should be
-   *          excluded, or {@code false} otherwise.
+   *          {@code true} if all operational attributes should be excluded, or
+   *          {@code false} otherwise.
    * @return A reference to this {@code LDIFEntryReader}.
    */
   public LDIFEntryReader setExcludeAllOperationalAttributes(
-      boolean excludeOperationalAttributes)
+      final boolean excludeOperationalAttributes)
   {
     this.excludeOperationalAttributes = excludeOperationalAttributes;
     return this;
@@ -264,17 +265,16 @@
 
 
   /**
-   * Specifies whether or not all user attributes should be excluded
-   * from any entries that are read from LDIF. The default is {@code
-   * false}.
+   * Specifies whether or not all user attributes should be excluded from any
+   * entries that are read from LDIF. The default is {@code false}.
    *
    * @param excludeUserAttributes
-   *          {@code true} if all user attributes should be excluded, or
-   *          {@code false} otherwise.
+   *          {@code true} if all user attributes should be excluded, or {@code
+   *          false} otherwise.
    * @return A reference to this {@code LDIFEntryReader}.
    */
   public LDIFEntryReader setExcludeAllUserAttributes(
-      boolean excludeUserAttributes)
+      final boolean excludeUserAttributes)
   {
     this.excludeUserAttributes = excludeUserAttributes;
     return this;
@@ -283,16 +283,15 @@
 
 
   /**
-   * Excludes the named attribute from any entries that are read from
-   * LDIF. By default all attributes are included unless explicitly
-   * excluded.
+   * Excludes the named attribute from any entries that are read from LDIF. By
+   * default all attributes are included unless explicitly excluded.
    *
    * @param attributeDescription
    *          The name of the attribute to be excluded.
    * @return A reference to this {@code LDIFEntryReader}.
    */
   public LDIFEntryReader setExcludeAttribute(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
   {
     Validator.ensureNotNull(attributeDescription);
     excludeAttributes.add(attributeDescription);
@@ -302,15 +301,15 @@
 
 
   /**
-   * Excludes all entries beneath the named entry (inclusive) from being
-   * read from LDIF. By default all entries are written unless
-   * explicitly excluded or included by branches or filters.
+   * Excludes all entries beneath the named entry (inclusive) from being read
+   * from LDIF. By default all entries are written unless explicitly excluded or
+   * included by branches or filters.
    *
    * @param excludeBranch
    *          The distinguished name of the branch to be excluded.
    * @return A reference to this {@code LDIFEntryReader}.
    */
-  public LDIFEntryReader setExcludeBranch(DN excludeBranch)
+  public LDIFEntryReader setExcludeBranch(final DN excludeBranch)
   {
     Validator.ensureNotNull(excludeBranch);
     excludeBranches.add(excludeBranch);
@@ -320,15 +319,15 @@
 
 
   /**
-   * Excludes all entries which match the provided filter matcher from
-   * being read from LDIF. By default all entries are read unless
-   * explicitly excluded or included by branches or filters.
+   * Excludes all entries which match the provided filter matcher from being
+   * read from LDIF. By default all entries are read unless explicitly excluded
+   * or included by branches or filters.
    *
    * @param excludeFilter
    *          The filter matcher.
    * @return A reference to this {@code LDIFEntryReader}.
    */
-  public LDIFEntryReader setExcludeFilter(Matcher excludeFilter)
+  public LDIFEntryReader setExcludeFilter(final Matcher excludeFilter)
   {
     Validator.ensureNotNull(excludeFilter);
     excludeFilters.add(excludeFilter);
@@ -338,16 +337,16 @@
 
 
   /**
-   * Ensures that the named attribute is not excluded from any entries
-   * that are read from LDIF. By default all attributes are included
-   * unless explicitly excluded.
+   * Ensures that the named attribute is not excluded from any entries that are
+   * read from LDIF. By default all attributes are included unless explicitly
+   * excluded.
    *
    * @param attributeDescription
    *          The name of the attribute to be included.
    * @return A reference to this {@code LDIFEntryReader}.
    */
   public LDIFEntryReader setIncludeAttribute(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
   {
     Validator.ensureNotNull(attributeDescription);
     includeAttributes.add(attributeDescription);
@@ -357,15 +356,15 @@
 
 
   /**
-   * Ensures that all entries beneath the named entry (inclusive) are
-   * read from LDIF. By default all entries are written unless
-   * explicitly excluded or included by branches or filters.
+   * Ensures that all entries beneath the named entry (inclusive) are read from
+   * LDIF. By default all entries are written unless explicitly excluded or
+   * included by branches or filters.
    *
    * @param includeBranch
    *          The distinguished name of the branch to be included.
    * @return A reference to this {@code LDIFEntryReader}.
    */
-  public LDIFEntryReader setIncludeBranch(DN includeBranch)
+  public LDIFEntryReader setIncludeBranch(final DN includeBranch)
   {
     Validator.ensureNotNull(includeBranch);
     includeBranches.add(includeBranch);
@@ -375,15 +374,15 @@
 
 
   /**
-   * Ensures that all entries which match the provided filter matcher
-   * are read from LDIF. By default all entries are read unless
-   * explicitly excluded or included by branches or filters.
+   * Ensures that all entries which match the provided filter matcher are read
+   * from LDIF. By default all entries are read unless explicitly excluded or
+   * included by branches or filters.
    *
    * @param includeFilter
    *          The filter matcher.
    * @return A reference to this {@code LDIFEntryReader}.
    */
-  public LDIFEntryReader setIncludeFilter(Matcher includeFilter)
+  public LDIFEntryReader setIncludeFilter(final Matcher includeFilter)
   {
     Validator.ensureNotNull(includeFilter);
     includeFilters.add(includeFilter);
@@ -393,16 +392,15 @@
 
 
   /**
-   * Sets the schema which should be used for decoding entries that are
-   * read from LDIF. The default schema is used if no other is
-   * specified.
+   * Sets the schema which should be used for decoding entries that are read
+   * from LDIF. The default schema is used if no other is specified.
    *
    * @param schema
-   *          The schema which should be used for decoding entries that
-   *          are read from LDIF.
+   *          The schema which should be used for decoding entries that are read
+   *          from LDIF.
    * @return A reference to this {@code LDIFEntryReader}.
    */
-  public LDIFEntryReader setSchema(Schema schema)
+  public LDIFEntryReader setSchema(final Schema schema)
   {
     Validator.ensureNotNull(schema);
     this.schema = schema;
@@ -412,15 +410,15 @@
 
 
   /**
-   * Specifies whether or not schema validation should be performed for
-   * entries that are read from LDIF. The default is {@code true}.
+   * Specifies whether or not schema validation should be performed for entries
+   * that are read from LDIF. The default is {@code true}.
    *
    * @param validateSchema
-   *          {@code true} if schema validation should be performed, or
-   *          {@code false} otherwise.
+   *          {@code true} if schema validation should be performed, or {@code
+   *          false} otherwise.
    * @return A reference to this {@code LDIFEntryReader}.
    */
-  public LDIFEntryReader setValidateSchema(boolean validateSchema)
+  public LDIFEntryReader setValidateSchema(final boolean validateSchema)
   {
     this.validateSchema = validateSchema;
     return this;
diff --git a/sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java b/sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java
index ff70ec7..6914a81 100644
--- a/sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java
+++ b/sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java
@@ -41,25 +41,24 @@
 
 
 /**
- * An LDIF entry writer writes attribute value records (entries) using
- * the LDAP Data Interchange Format (LDIF) to a user defined
- * destination.
+ * An LDIF entry writer writes attribute value records (entries) using the LDAP
+ * Data Interchange Format (LDIF) to a user defined destination.
  *
- * @see <a href="http://tools.ietf.org/html/rfc2849">RFC 2849 - The LDAP
- *      Data Interchange Format (LDIF) - Technical Specification </a>
+ * @see <a href="http://tools.ietf.org/html/rfc2849">RFC 2849 - The LDAP Data
+ *      Interchange Format (LDIF) - Technical Specification </a>
  */
 public final class LDIFEntryWriter extends AbstractLDIFWriter implements
     EntryWriter
 {
 
   /**
-   * Creates a new LDIF entry writer which will append lines of LDIF to
-   * the provided list.
+   * Creates a new LDIF entry writer which will append lines of LDIF to the
+   * provided list.
    *
    * @param ldifLines
    *          The list to which lines of LDIF should be appended.
    */
-  public LDIFEntryWriter(List<String> ldifLines)
+  public LDIFEntryWriter(final List<String> ldifLines)
   {
     super(ldifLines);
   }
@@ -67,13 +66,13 @@
 
 
   /**
-   * Creates a new LDIF entry writer whose destination is the provided
-   * output stream.
+   * Creates a new LDIF entry writer whose destination is the provided output
+   * stream.
    *
    * @param out
    *          The output stream to use.
    */
-  public LDIFEntryWriter(OutputStream out)
+  public LDIFEntryWriter(final OutputStream out)
   {
     super(out);
   }
@@ -101,18 +100,17 @@
 
 
   /**
-   * Specifies whether or not user-friendly comments should be added
-   * whenever distinguished names or UTF-8 attribute values are
-   * encountered which contained non-ASCII characters. The default is
-   * {@code false}.
+   * Specifies whether or not user-friendly comments should be added whenever
+   * distinguished names or UTF-8 attribute values are encountered which
+   * contained non-ASCII characters. The default is {@code false}.
    *
    * @param addUserFriendlyComments
-   *          {@code true} if user-friendly comments should be added, or
-   *          {@code false} otherwise.
+   *          {@code true} if user-friendly comments should be added, or {@code
+   *          false} otherwise.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
   public LDIFEntryWriter setAddUserFriendlyComments(
-      boolean addUserFriendlyComments)
+      final boolean addUserFriendlyComments)
   {
     this.addUserFriendlyComments = addUserFriendlyComments;
     return this;
@@ -121,17 +119,16 @@
 
 
   /**
-   * Specifies whether or not all operational attributes should be
-   * excluded from any entries that are written to LDIF. The default is
-   * {@code false}.
+   * Specifies whether or not all operational attributes should be excluded from
+   * any entries that are written to LDIF. The default is {@code false}.
    *
    * @param excludeOperationalAttributes
-   *          {@code true} if all operational attributes should be
-   *          excluded, or {@code false} otherwise.
+   *          {@code true} if all operational attributes should be excluded, or
+   *          {@code false} otherwise.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
   public LDIFEntryWriter setExcludeAllOperationalAttributes(
-      boolean excludeOperationalAttributes)
+      final boolean excludeOperationalAttributes)
   {
     this.excludeOperationalAttributes = excludeOperationalAttributes;
     return this;
@@ -140,17 +137,16 @@
 
 
   /**
-   * Specifies whether or not all user attributes should be excluded
-   * from any entries that are written to LDIF. The default is {@code
-   * false}.
+   * Specifies whether or not all user attributes should be excluded from any
+   * entries that are written to LDIF. The default is {@code false}.
    *
    * @param excludeUserAttributes
-   *          {@code true} if all user attributes should be excluded, or
-   *          {@code false} otherwise.
+   *          {@code true} if all user attributes should be excluded, or {@code
+   *          false} otherwise.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
   public LDIFEntryWriter setExcludeAllUserAttributes(
-      boolean excludeUserAttributes)
+      final boolean excludeUserAttributes)
   {
     this.excludeUserAttributes = excludeUserAttributes;
     return this;
@@ -159,16 +155,15 @@
 
 
   /**
-   * Excludes the named attribute from any entries that are written to
-   * LDIF. By default all attributes are included unless explicitly
-   * excluded.
+   * Excludes the named attribute from any entries that are written to LDIF. By
+   * default all attributes are included unless explicitly excluded.
    *
    * @param attributeDescription
    *          The name of the attribute to be excluded.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
   public LDIFEntryWriter setExcludeAttribute(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
   {
     Validator.ensureNotNull(attributeDescription);
     excludeAttributes.add(attributeDescription);
@@ -178,15 +173,15 @@
 
 
   /**
-   * Excludes all entries beneath the named entry (inclusive) from being
-   * written to LDIF. By default all entries are written unless
-   * explicitly excluded or included by branches or filters.
+   * Excludes all entries beneath the named entry (inclusive) from being written
+   * to LDIF. By default all entries are written unless explicitly excluded or
+   * included by branches or filters.
    *
    * @param excludeBranch
    *          The distinguished name of the branch to be excluded.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
-  public LDIFEntryWriter setExcludeBranch(DN excludeBranch)
+  public LDIFEntryWriter setExcludeBranch(final DN excludeBranch)
   {
     Validator.ensureNotNull(excludeBranch);
     excludeBranches.add(excludeBranch);
@@ -196,15 +191,15 @@
 
 
   /**
-   * Excludes all entries which match the provided filter matcher from
-   * being written to LDIF. By default all entries are written unless
-   * explicitly excluded or included by branches or filters.
+   * Excludes all entries which match the provided filter matcher from being
+   * written to LDIF. By default all entries are written unless explicitly
+   * excluded or included by branches or filters.
    *
    * @param excludeFilter
    *          The filter matcher.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
-  public LDIFEntryWriter setExcludeFilter(Matcher excludeFilter)
+  public LDIFEntryWriter setExcludeFilter(final Matcher excludeFilter)
   {
     Validator.ensureNotNull(excludeFilter);
     excludeFilters.add(excludeFilter);
@@ -214,16 +209,16 @@
 
 
   /**
-   * Ensures that the named attribute is not excluded from any entries
-   * that are written to LDIF. By default all attributes are included
-   * unless explicitly excluded.
+   * Ensures that the named attribute is not excluded from any entries that are
+   * written to LDIF. By default all attributes are included unless explicitly
+   * excluded.
    *
    * @param attributeDescription
    *          The name of the attribute to be included.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
   public LDIFEntryWriter setIncludeAttribute(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
   {
     Validator.ensureNotNull(attributeDescription);
     includeAttributes.add(attributeDescription);
@@ -233,15 +228,15 @@
 
 
   /**
-   * Ensures that all entries beneath the named entry (inclusive) are
-   * written to LDIF. By default all entries are written unless
-   * explicitly excluded or included by branches or filters.
+   * Ensures that all entries beneath the named entry (inclusive) are written to
+   * LDIF. By default all entries are written unless explicitly excluded or
+   * included by branches or filters.
    *
    * @param includeBranch
    *          The distinguished name of the branch to be included.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
-  public LDIFEntryWriter setIncludeBranch(DN includeBranch)
+  public LDIFEntryWriter setIncludeBranch(final DN includeBranch)
   {
     Validator.ensureNotNull(includeBranch);
     includeBranches.add(includeBranch);
@@ -251,15 +246,15 @@
 
 
   /**
-   * Ensures that all entries which match the provided filter matcher
-   * are written to LDIF. By default all entries are written unless
-   * explicitly excluded or included by branches or filters.
+   * Ensures that all entries which match the provided filter matcher are
+   * written to LDIF. By default all entries are written unless explicitly
+   * excluded or included by branches or filters.
    *
    * @param includeFilter
    *          The filter matcher.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
-  public LDIFEntryWriter setIncludeFilter(Matcher includeFilter)
+  public LDIFEntryWriter setIncludeFilter(final Matcher includeFilter)
   {
     Validator.ensureNotNull(includeFilter);
     includeFilters.add(includeFilter);
@@ -269,15 +264,15 @@
 
 
   /**
-   * Sets the schema which should be used when filtering entries (not
-   * required if no filtering is to be performed). The default schema is
-   * used if no other is specified.
+   * Sets the schema which should be used when filtering entries (not required
+   * if no filtering is to be performed). The default schema is used if no other
+   * is specified.
    *
    * @param schema
    *          The schema which should be used when filtering entries.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
-  public LDIFEntryWriter setSchema(Schema schema)
+  public LDIFEntryWriter setSchema(final Schema schema)
   {
     Validator.ensureNotNull(schema);
     this.schema = schema;
@@ -287,15 +282,15 @@
 
 
   /**
-   * Specifies the column at which long lines should be wrapped. A value
-   * less than or equal to zero (the default) indicates that no wrapping
-   * should be performed.
+   * Specifies the column at which long lines should be wrapped. A value less
+   * than or equal to zero (the default) indicates that no wrapping should be
+   * performed.
    *
    * @param wrapColumn
    *          The column at which long lines should be wrapped.
    * @return A reference to this {@code LDIFEntryWriter}.
    */
-  public LDIFEntryWriter setWrapColumn(int wrapColumn)
+  public LDIFEntryWriter setWrapColumn(final int wrapColumn)
   {
     this.wrapColumn = wrapColumn;
     return this;
@@ -306,7 +301,7 @@
   /**
    * {@inheritDoc}
    */
-  public LDIFEntryWriter writeComment(CharSequence comment)
+  public LDIFEntryWriter writeComment(final CharSequence comment)
       throws IOException, NullPointerException
   {
     writeComment0(comment);
@@ -318,7 +313,7 @@
   /**
    * {@inheritDoc}
    */
-  public LDIFEntryWriter writeEntry(Entry entry) throws IOException,
+  public LDIFEntryWriter writeEntry(final Entry entry) throws IOException,
       NullPointerException
   {
     Validator.ensureNotNull(entry);
@@ -336,7 +331,7 @@
     }
 
     writeKeyAndValue("dn", entry.getName().toString());
-    for (final Attribute attribute : entry.getAttributes())
+    for (final Attribute attribute : entry.getAllAttributes())
     {
       // Filter the attribute if required.
       if (isAttributeExcluded(attribute.getAttributeDescription()))
@@ -344,8 +339,8 @@
         continue;
       }
 
-      final String attributeDescription =
-          attribute.getAttributeDescriptionAsString();
+      final String attributeDescription = attribute
+          .getAttributeDescriptionAsString();
       for (final ByteString value : attribute)
       {
         writeKeyAndValue(attributeDescription, value);
diff --git a/sdk/src/org/opends/sdk/requests/AbandonRequest.java b/sdk/src/org/opends/sdk/requests/AbandonRequest.java
index e1d07e6..b8e705d 100644
--- a/sdk/src/org/opends/sdk/requests/AbandonRequest.java
+++ b/sdk/src/org/opends/sdk/requests/AbandonRequest.java
@@ -29,28 +29,25 @@
 
 
 
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * The Abandon operation allows a client to request that the server
- * abandon an uncompleted operation.
+ * The Abandon operation allows a client to request that the server abandon an
+ * uncompleted operation.
  * <p>
  * Abandon, Bind, Unbind, and StartTLS operations cannot be abandoned.
  */
 public interface AbandonRequest extends Request
 {
   /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
   AbandonRequest addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -58,45 +55,23 @@
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * {@inheritDoc}
    */
-  AbandonRequest clearControls() throws UnsupportedOperationException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
-
-
-
-  /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
-   */
-  Iterable<Control> getControls();
+  List<Control> getControls();
 
 
 
   /**
    * Returns the message ID of the request to be abandoned.
-   * 
+   *
    * @return The message ID of the request to be abandoned.
    */
   int getMessageID();
@@ -104,44 +79,14 @@
 
 
   /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
    * Sets the message ID of the request to be abandoned.
-   * 
+   *
    * @param id
    *          The message ID of the request to be abandoned.
    * @return This abandon request.
    * @throws UnsupportedOperationException
-   *           If this abandon request does not permit the message ID to
-   *           be set.
+   *           If this abandon request does not permit the message ID to be set.
    */
-  AbandonRequest setMessageID(int id)
-      throws UnsupportedOperationException;
+  AbandonRequest setMessageID(int id) throws UnsupportedOperationException;
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/AbandonRequestImpl.java b/sdk/src/org/opends/sdk/requests/AbandonRequestImpl.java
index 88fa737..21df3a9 100644
--- a/sdk/src/org/opends/sdk/requests/AbandonRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/AbandonRequestImpl.java
@@ -27,11 +27,13 @@
 
 package org.opends.sdk.requests;
 
+
+
 /**
  * Abandon request implementation.
  */
-final class AbandonRequestImpl extends
-    AbstractRequestImpl<AbandonRequest> implements AbandonRequest
+final class AbandonRequestImpl extends AbstractRequestImpl<AbandonRequest>
+    implements AbandonRequest
 {
 
   private int messageID;
@@ -40,11 +42,11 @@
 
   /**
    * Creates a new abandon request using the provided message ID.
-   * 
+   *
    * @param messageID
    *          The message ID of the request to be abandoned.
    */
-  AbandonRequestImpl(int messageID)
+  AbandonRequestImpl(final int messageID)
   {
     this.messageID = messageID;
   }
@@ -61,7 +63,7 @@
   /**
    * {@inheritDoc}
    */
-  public AbandonRequest setMessageID(int id)
+  public AbandonRequest setMessageID(final int id)
       throws UnsupportedOperationException
   {
     this.messageID = id;
@@ -87,6 +89,7 @@
 
 
 
+  @Override
   AbandonRequest getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/requests/AbstractBindRequest.java b/sdk/src/org/opends/sdk/requests/AbstractBindRequest.java
index 612740b..c27281b 100644
--- a/sdk/src/org/opends/sdk/requests/AbstractBindRequest.java
+++ b/sdk/src/org/opends/sdk/requests/AbstractBindRequest.java
@@ -29,19 +29,15 @@
 
 
 
-import org.opends.sdk.DN;
-
-
-
 /**
- * An abstract Bind request which can be used as the basis for
- * implementing new authentication methods.
- * 
+ * An abstract Bind request which can be used as the basis for implementing new
+ * authentication methods.
+ *
  * @param <R>
  *          The type of Bind request.
  */
-public abstract class AbstractBindRequest<R extends BindRequest>
-    extends AbstractRequestImpl<R> implements BindRequest
+abstract class AbstractBindRequest<R extends BindRequest> extends
+    AbstractRequestImpl<R> implements BindRequest
 {
 
   /**
@@ -57,13 +53,14 @@
   /**
    * {@inheritDoc}
    */
-  public abstract DN getName();
+  public abstract String getName();
 
 
 
   /**
    * {@inheritDoc}
    */
+  @Override
   @SuppressWarnings("unchecked")
   final R getThis()
   {
diff --git a/sdk/src/org/opends/sdk/requests/AbstractExtendedRequest.java b/sdk/src/org/opends/sdk/requests/AbstractExtendedRequest.java
index 2be54f2..80f8dc8 100644
--- a/sdk/src/org/opends/sdk/requests/AbstractExtendedRequest.java
+++ b/sdk/src/org/opends/sdk/requests/AbstractExtendedRequest.java
@@ -30,21 +30,24 @@
 
 
 import org.opends.sdk.ByteString;
-import org.opends.sdk.extensions.ExtendedOperation;
-import org.opends.sdk.responses.Result;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+
+import com.sun.opends.sdk.util.StaticUtils;
 
 
 
 /**
- * An abstract Extended request which can be used as the basis for
- * implementing new Extended operations.
- * 
+ * An abstract Extended request which can be used as the basis for implementing
+ * new Extended operations.
+ *
  * @param <R>
  *          The type of extended request.
  * @param <S>
  *          The type of result.
  */
-public abstract class AbstractExtendedRequest<R extends ExtendedRequest<S>, S extends Result>
+public abstract class AbstractExtendedRequest<R extends ExtendedRequest<S>,
+                                              S extends ExtendedResult>
     extends AbstractRequestImpl<R> implements ExtendedRequest<S>
 {
 
@@ -59,29 +62,30 @@
 
 
   /**
-   * Returns the extended operation associated with this extended
-   * request.
-   * <p>
-   * FIXME: this should not be exposed to clients.
-   * 
-   * @return The extended operation associated with this extended
-   *         request.
+   * {@inheritDoc}
    */
-  public abstract ExtendedOperation<R, S> getExtendedOperation();
+  public abstract String getOID();
 
 
 
   /**
    * {@inheritDoc}
    */
-  public abstract String getRequestName();
+  public abstract ExtendedResultDecoder<S> getResultDecoder();
 
 
 
   /**
    * {@inheritDoc}
    */
-  public abstract ByteString getRequestValue();
+  public abstract ByteString getValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public abstract boolean hasValue();
 
 
 
@@ -93,10 +97,12 @@
   {
     final StringBuilder builder = new StringBuilder();
     builder.append("ExtendedRequest(requestName=");
-    builder.append(getRequestName());
-    builder.append(", requestValue=");
-    final ByteString value = getRequestValue();
-    builder.append(value == null ? ByteString.empty() : value);
+    builder.append(getOID());
+    if (hasValue())
+    {
+      builder.append(", requestValue=");
+      StaticUtils.toHexPlusAscii(getValue(), builder, 4);
+    }
     builder.append(", controls=");
     builder.append(getControls());
     builder.append(")");
@@ -108,6 +114,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   @SuppressWarnings("unchecked")
   final R getThis()
   {
diff --git a/sdk/src/org/opends/sdk/requests/AbstractRequestImpl.java b/sdk/src/org/opends/sdk/requests/AbstractRequestImpl.java
index a799c53..c4ca148 100644
--- a/sdk/src/org/opends/sdk/requests/AbstractRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/AbstractRequestImpl.java
@@ -29,11 +29,13 @@
 
 
 
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 import com.sun.opends.sdk.util.Validator;
 
@@ -41,12 +43,11 @@
 
 /**
  * Abstract request implementation.
- * 
+ *
  * @param <R>
  *          The type of request.
  */
-abstract class AbstractRequestImpl<R extends Request> implements
-    Request
+abstract class AbstractRequestImpl<R extends Request> implements Request
 {
   private final List<Control> controls = new LinkedList<Control>();
 
@@ -65,8 +66,7 @@
   /**
    * {@inheritDoc}
    */
-  public final R addControl(Control control)
-      throws NullPointerException
+  public final R addControl(final Control control) throws NullPointerException
   {
     Validator.ensureNotNull(control);
     controls.add(control);
@@ -78,20 +78,11 @@
   /**
    * {@inheritDoc}
    */
-  public final R clearControls()
+  public final <C extends Control> C getControl(
+      final ControlDecoder<C> decoder, final DecodeOptions options)
+      throws DecodeException
   {
-    controls.clear();
-    return getThis();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final Control getControl(String oid)
-  {
-    Validator.ensureNotNull(oid);
+    Validator.ensureNotNull(decoder, options);
 
     // Avoid creating an iterator if possible.
     if (controls.isEmpty())
@@ -101,9 +92,9 @@
 
     for (final Control control : controls)
     {
-      if (control.getOID().equals(oid))
+      if (control.getOID().equals(decoder.getOID()))
       {
-        return control;
+        return decoder.decodeControl(control, options);
       }
     }
 
@@ -115,53 +106,14 @@
   /**
    * {@inheritDoc}
    */
-  public final Iterable<Control> getControls()
+  public final List<Control> getControls()
   {
     return controls;
   }
 
 
 
-  /**
-   * {@inheritDoc}
-   */
-  public final boolean hasControls()
-  {
-    return !controls.isEmpty();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final Control removeControl(String oid)
-      throws NullPointerException
-  {
-    Validator.ensureNotNull(oid);
-
-    // Avoid creating an iterator if possible.
-    if (controls.isEmpty())
-    {
-      return null;
-    }
-
-    final Iterator<Control> iterator = controls.iterator();
-    while (iterator.hasNext())
-    {
-      final Control control = iterator.next();
-      if (control.getOID().equals(oid))
-      {
-        iterator.remove();
-        return control;
-      }
-    }
-
-    return null;
-  }
-
-
-
+  @Override
   public abstract String toString();
 
 
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/src/org/opends/sdk/requests/AbstractSASLBindRequest.java
similarity index 62%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/src/org/opends/sdk/requests/AbstractSASLBindRequest.java
index 62b3ae3..6ecec66 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/src/org/opends/sdk/requests/AbstractSASLBindRequest.java
@@ -25,18 +25,35 @@
  *      Copyright 2009 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package org.opends.sdk.requests;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import static com.sun.opends.sdk.ldap.LDAPConstants.TYPE_AUTHENTICATION_SASL;
 
 
 
 /**
- * Password call-back.
+ * An abstract SASL Bind request which can be used as the basis for implementing
+ * new SASL authentication methods.
+ *
+ * @param <R>
+ *          The type of SASL Bind request.
  */
-public interface PasswordCallbackHandler
+abstract class AbstractSASLBindRequest<R extends SASLBindRequest> extends
+    AbstractBindRequest<R> implements SASLBindRequest
 {
-  public boolean handle(PasswordCallback callback);
+  public final byte getAuthenticationType()
+  {
+    return TYPE_AUTHENTICATION_SASL;
+  }
+
+
+
+  @Override
+  public final String getName()
+  {
+    return "".intern();
+  }
+
 }
diff --git a/sdk/src/org/opends/sdk/requests/AbstractUnmodifiableRequestImpl.java b/sdk/src/org/opends/sdk/requests/AbstractUnmodifiableRequestImpl.java
index b63783b..a3ecd70 100644
--- a/sdk/src/org/opends/sdk/requests/AbstractUnmodifiableRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/AbstractUnmodifiableRequestImpl.java
@@ -29,20 +29,24 @@
 
 
 
-import org.opends.sdk.controls.Control;
+import java.util.Collections;
+import java.util.List;
 
-import com.sun.opends.sdk.util.Iterables;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
  * Unmodifiable request implementation.
- * 
+ *
  * @param <R>
  *          The type of request.
  */
-abstract class AbstractUnmodifiableRequestImpl<R extends Request>
-    implements Request
+abstract class AbstractUnmodifiableRequestImpl<R extends Request> implements
+    Request
 {
 
   private final R impl;
@@ -51,12 +55,11 @@
 
   /**
    * Creates a new unmodifiable request implementation.
-   * 
+   *
    * @param impl
-   *          The underlying request implementation to be made
-   *          unmodifiable.
+   *          The underlying request implementation to be made unmodifiable.
    */
-  AbstractUnmodifiableRequestImpl(R impl)
+  AbstractUnmodifiableRequestImpl(final R impl)
   {
     this.impl = impl;
   }
@@ -66,7 +69,7 @@
   /**
    * {@inheritDoc}
    */
-  public final R addControl(Control control)
+  public final R addControl(final Control control)
       throws UnsupportedOperationException, NullPointerException
   {
     throw new UnsupportedOperationException();
@@ -77,21 +80,12 @@
   /**
    * {@inheritDoc}
    */
-  public final R clearControls() throws UnsupportedOperationException
-  {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final Control getControl(String oid)
-      throws NullPointerException
+  public final <C extends Control> C getControl(
+      final ControlDecoder<C> decoder, final DecodeOptions options)
+      throws NullPointerException, DecodeException
   {
     // FIXME: ensure that controls are immutable.
-    return impl.getControl(oid);
+    return impl.getControl(decoder, options);
   }
 
 
@@ -99,10 +93,10 @@
   /**
    * {@inheritDoc}
    */
-  public final Iterable<Control> getControls()
+  public final List<Control> getControls()
   {
     // FIXME: ensure that controls are immutable.
-    return Iterables.unmodifiable(impl.getControls());
+    return Collections.unmodifiableList(impl.getControls());
   }
 
 
@@ -110,27 +104,7 @@
   /**
    * {@inheritDoc}
    */
-  public final boolean hasControls()
-  {
-    return impl.hasControls();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException
-  {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
+  @Override
   public final String toString()
   {
     return impl.toString();
diff --git a/sdk/src/org/opends/sdk/requests/AddRequest.java b/sdk/src/org/opends/sdk/requests/AddRequest.java
index 14a2542..13ef11c 100644
--- a/sdk/src/org/opends/sdk/requests/AddRequest.java
+++ b/sdk/src/org/opends/sdk/requests/AddRequest.java
@@ -30,26 +30,24 @@
 
 
 import java.util.Collection;
+import java.util.List;
 
 import org.opends.sdk.*;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 import org.opends.sdk.ldif.ChangeRecord;
 import org.opends.sdk.ldif.ChangeRecordVisitor;
-import org.opends.sdk.schema.ObjectClass;
-
 
 
 
 /**
- * The Add operation allows a client to request the addition of an entry
- * into the Directory.
+ * The Add operation allows a client to request the addition of an entry into
+ * the Directory.
  * <p>
  * The RDN attribute(s) may or may not be included in the Add request.
- * NO-USER-MODIFICATION attributes such as the {@code createTimestamp}
- * or {@code creatorsName} attributes must not be included, since the
- * server maintains these automatically.
- * <p>
- * FIXME: clean up methods, clearly define schema behavior.
+ * NO-USER-MODIFICATION attributes such as the {@code createTimestamp} or
+ * {@code creatorsName} attributes must not be included, since the server
+ * maintains these automatically.
  */
 public interface AddRequest extends Request, ChangeRecord, Entry
 {
@@ -81,24 +79,16 @@
    * {@inheritDoc}
    */
   AddRequest addAttribute(String attributeDescription, Object... values)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Adds the provided control to this request.
-   *
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
-  AddRequest addControl(Control control)
-      throws UnsupportedOperationException, NullPointerException;
+  AddRequest addControl(Control control) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
@@ -110,28 +100,17 @@
 
 
   /**
-   * Removes all the controls included with this request.
-   *
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * {@inheritDoc}
    */
-  AddRequest clearControls() throws UnsupportedOperationException;
+  boolean containsAttribute(Attribute attribute,
+      Collection<ByteString> missingValues) throws NullPointerException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  boolean containsAttribute(AttributeDescription attributeDescription)
-      throws NullPointerException;
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  boolean containsAttribute(String attributeDescription)
+  boolean containsAttribute(String attributeDescription, Object... values)
       throws LocalizedIllegalArgumentException, NullPointerException;
 
 
@@ -139,7 +118,14 @@
   /**
    * {@inheritDoc}
    */
-  boolean containsObjectClass(ObjectClass objectClass)
+  Iterable<Attribute> getAllAttributes();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  Iterable<Attribute> getAllAttributes(AttributeDescription attributeDescription)
       throws NullPointerException;
 
 
@@ -147,24 +133,7 @@
   /**
    * {@inheritDoc}
    */
-  boolean containsObjectClass(String objectClass)
-      throws NullPointerException;
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  Iterable<Attribute> findAttributes(
-      AttributeDescription attributeDescription)
-      throws NullPointerException;
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  Iterable<Attribute> findAttributes(String attributeDescription)
+  Iterable<Attribute> getAllAttributes(String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException;
 
 
@@ -195,33 +164,15 @@
   /**
    * {@inheritDoc}
    */
-  Iterable<Attribute> getAttributes();
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   *
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
-
-
-
-  /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   *
-   * @return An {@code Iterable} containing the controls.
-   */
-  Iterable<Control> getControls();
+  List<Control> getControls();
 
 
 
@@ -235,23 +186,6 @@
   /**
    * {@inheritDoc}
    */
-  Iterable<String> getObjectClasses();
-
-
-
-  /**
-   * Indicates whether or not this request has any controls.
-   *
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * {@inheritDoc}
-   */
   boolean removeAttribute(Attribute attribute,
       Collection<ByteString> missingValues)
       throws UnsupportedOperationException, NullPointerException;
@@ -269,36 +203,9 @@
   /**
    * {@inheritDoc}
    */
-  AddRequest removeAttribute(String attributeDescription)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  AddRequest removeAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   *
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  AddRequest removeAttribute(String attributeDescription, Object... values)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 
 
@@ -313,9 +220,9 @@
   /**
    * {@inheritDoc}
    */
-  AddRequest replaceAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
+  AddRequest replaceAttribute(String attributeDescription, Object... values)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 
 
@@ -330,8 +237,7 @@
   /**
    * {@inheritDoc}
    */
-  AddRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
+  AddRequest setName(String dn) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException;
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/AddRequestImpl.java b/sdk/src/org/opends/sdk/requests/AddRequestImpl.java
index f0367f6..94a6ed1 100644
--- a/sdk/src/org/opends/sdk/requests/AddRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/AddRequestImpl.java
@@ -33,16 +33,14 @@
 
 import org.opends.sdk.*;
 import org.opends.sdk.ldif.ChangeRecordVisitor;
-import org.opends.sdk.schema.ObjectClass;
-
 
 
 
 /**
  * Add request implementation.
  */
-final class AddRequestImpl extends AbstractRequestImpl<AddRequest>
-    implements AddRequest
+final class AddRequestImpl extends AbstractRequestImpl<AddRequest> implements
+    AddRequest
 {
 
   private final Entry entry;
@@ -50,18 +48,17 @@
 
 
   /**
-   * Creates a new add request backed by the provided entry.
-   * Modifications made to {@code entry} will be reflected in the
-   * returned add request. The returned add request supports updates to
-   * its list of controls, as well as updates to the name and attributes
-   * if the underlying entry allows.
+   * Creates a new add request backed by the provided entry. Modifications made
+   * to {@code entry} will be reflected in the returned add request. The
+   * returned add request supports updates to its list of controls, as well as
+   * updates to the name and attributes if the underlying entry allows.
    *
    * @param entry
    *          The entry to be added.
    * @throws NullPointerException
    *           If {@code entry} was {@code null} .
    */
-  AddRequestImpl(Entry entry) throws NullPointerException
+  AddRequestImpl(final Entry entry) throws NullPointerException
   {
     this.entry = entry;
   }
@@ -71,7 +68,7 @@
   /**
    * {@inheritDoc}
    */
-  public <R, P> R accept(ChangeRecordVisitor<R, P> v, P p)
+  public <R, P> R accept(final ChangeRecordVisitor<R, P> v, final P p)
   {
     return v.visitChangeRecord(p, this);
   }
@@ -81,7 +78,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean addAttribute(Attribute attribute)
+  public boolean addAttribute(final Attribute attribute)
       throws UnsupportedOperationException, NullPointerException
   {
     return entry.addAttribute(attribute);
@@ -92,8 +89,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean addAttribute(Attribute attribute,
-      Collection<ByteString> duplicateValues)
+  public boolean addAttribute(final Attribute attribute,
+      final Collection<ByteString> duplicateValues)
       throws UnsupportedOperationException, NullPointerException
   {
     return entry.addAttribute(attribute, duplicateValues);
@@ -104,8 +101,8 @@
   /**
    * {@inheritDoc}
    */
-  public AddRequestImpl addAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
+  public AddRequest addAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException
   {
     entry.addAttribute(attributeDescription, values);
@@ -117,8 +114,7 @@
   /**
    * {@inheritDoc}
    */
-  public AddRequestImpl clearAttributes()
-      throws UnsupportedOperationException
+  public AddRequest clearAttributes() throws UnsupportedOperationException
   {
     entry.clearAttributes();
     return this;
@@ -129,11 +125,10 @@
   /**
    * {@inheritDoc}
    */
-  public boolean containsAttribute(
-      AttributeDescription attributeDescription)
-      throws NullPointerException
+  public boolean containsAttribute(final Attribute attribute,
+      final Collection<ByteString> missingValues) throws NullPointerException
   {
-    return entry.containsAttribute(attributeDescription);
+    return entry.containsAttribute(attribute, missingValues);
   }
 
 
@@ -141,10 +136,44 @@
   /**
    * {@inheritDoc}
    */
-  public boolean containsAttribute(String attributeDescription)
+  public boolean containsAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
+      NullPointerException
+  {
+    return entry.containsAttribute(attributeDescription, values);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Iterable<Attribute> getAllAttributes()
+  {
+    return entry.getAllAttributes();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Iterable<Attribute> getAllAttributes(
+      final AttributeDescription attributeDescription)
+      throws NullPointerException
+  {
+    return entry.getAllAttributes(attributeDescription);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Iterable<Attribute> getAllAttributes(final String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
-    return entry.containsAttribute(attributeDescription);
+    return entry.getAllAttributes(attributeDescription);
   }
 
 
@@ -152,53 +181,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean containsObjectClass(ObjectClass objectClass)
-      throws NullPointerException
-  {
-    return entry.containsObjectClass(objectClass);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean containsObjectClass(String objectClass)
-      throws NullPointerException
-  {
-    return entry.containsObjectClass(objectClass);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Iterable<Attribute> findAttributes(
-      AttributeDescription attributeDescription)
-      throws NullPointerException
-  {
-    return entry.findAttributes(attributeDescription);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Iterable<Attribute> findAttributes(String attributeDescription)
-      throws LocalizedIllegalArgumentException, NullPointerException
-  {
-    return entry.findAttributes(attributeDescription);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Attribute getAttribute(
-      AttributeDescription attributeDescription)
+  public Attribute getAttribute(final AttributeDescription attributeDescription)
       throws NullPointerException
   {
     return entry.getAttribute(attributeDescription);
@@ -209,7 +192,7 @@
   /**
    * {@inheritDoc}
    */
-  public Attribute getAttribute(String attributeDescription)
+  public Attribute getAttribute(final String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     return entry.getAttribute(attributeDescription);
@@ -230,16 +213,6 @@
   /**
    * {@inheritDoc}
    */
-  public Iterable<Attribute> getAttributes()
-  {
-    return entry.getAttributes();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
   public DN getName()
   {
     return entry.getName();
@@ -250,18 +223,8 @@
   /**
    * {@inheritDoc}
    */
-  public Iterable<String> getObjectClasses()
-  {
-    return entry.getObjectClasses();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean removeAttribute(Attribute attribute,
-      Collection<ByteString> missingValues)
+  public boolean removeAttribute(final Attribute attribute,
+      final Collection<ByteString> missingValues)
       throws UnsupportedOperationException, NullPointerException
   {
     return entry.removeAttribute(attribute, missingValues);
@@ -272,8 +235,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean removeAttribute(
-      AttributeDescription attributeDescription)
+  public boolean removeAttribute(final AttributeDescription attributeDescription)
       throws UnsupportedOperationException, NullPointerException
   {
     return entry.removeAttribute(attributeDescription);
@@ -284,21 +246,8 @@
   /**
    * {@inheritDoc}
    */
-  public AddRequestImpl removeAttribute(String attributeDescription)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
-  {
-    entry.removeAttribute(attributeDescription);
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public AddRequestImpl removeAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
+  public AddRequest removeAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException
   {
     entry.removeAttribute(attributeDescription, values);
@@ -310,7 +259,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean replaceAttribute(Attribute attribute)
+  public boolean replaceAttribute(final Attribute attribute)
       throws UnsupportedOperationException, NullPointerException
   {
     return entry.replaceAttribute(attribute);
@@ -321,8 +270,8 @@
   /**
    * {@inheritDoc}
    */
-  public AddRequestImpl replaceAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
+  public AddRequest replaceAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException
   {
     entry.replaceAttribute(attributeDescription, values);
@@ -334,8 +283,8 @@
   /**
    * {@inheritDoc}
    */
-  public AddRequestImpl setName(DN dn)
-      throws UnsupportedOperationException, NullPointerException
+  public AddRequest setName(final DN dn) throws UnsupportedOperationException,
+      NullPointerException
   {
     entry.setName(dn);
     return this;
@@ -346,9 +295,9 @@
   /**
    * {@inheritDoc}
    */
-  public AddRequestImpl setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
+  public AddRequest setName(final String dn)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
   {
     entry.setName(dn);
     return this;
@@ -366,7 +315,7 @@
     builder.append("AddRequest(name=");
     builder.append(getName());
     builder.append(", attributes=");
-    builder.append(getAttributes());
+    builder.append(getAllAttributes());
     builder.append(", controls=");
     builder.append(getControls());
     builder.append(")");
@@ -375,6 +324,10 @@
 
 
 
+  /**
+   * {@inheritDoc}
+   */
+  @Override
   AddRequest getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequest.java b/sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequest.java
new file mode 100644
index 0000000..5cc54a6
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequest.java
@@ -0,0 +1,151 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+
+
+/**
+ * The anonymous SASL bind request as defined in RFC 4505. This SASL mechanism
+ * allows a client to authenticate to the server without requiring the user to
+ * establish or otherwise disclose their identity to the server. That is, this
+ * mechanism provides an anonymous login method. This mechanism does not provide
+ * a security layer.
+ * <p>
+ * Clients should provide trace information, which has no semantic value, and
+ * can be used by administrators in order to identify the user. It should take
+ * one of two forms: an Internet email address, or an opaque string that does
+ * not contain the '@' (U+0040) character and that can be interpreted by the
+ * system administrator of the client's domain. For privacy reasons, an Internet
+ * email address or other information identifying the user should only be used
+ * with permission from the user.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4505">RFC 4505 - Anonymous Simple
+ *      Authentication and Security Layer (SASL) Mechanism </a>
+ */
+public interface AnonymousSASLBindRequest extends SASLBindRequest
+{
+
+  /**
+   * The name of the SASL mechanism that does not provide any authentication but
+   * rather uses anonymous access.
+   */
+  public static final String SASL_MECHANISM_NAME = "ANONYMOUS";
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  AnonymousSASLBindRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  BindClient createBindClient(String serverName);
+
+
+
+  /**
+   * Returns the authentication mechanism identifier for this SASL bind request
+   * as defined by the LDAP protocol, which is always {@code 0xA3}.
+   *
+   * @return The authentication mechanism identifier.
+   */
+  byte getAuthenticationType();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * Returns the name of the Directory object that the client wishes to bind as,
+   * which is always the empty string for SASL authentication.
+   *
+   * @return The name of the Directory object that the client wishes to bind as.
+   */
+  String getName();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getSASLMechanism();
+
+
+
+  /**
+   * Returns the trace information, which has no semantic value, and can be used
+   * by administrators in order to identify the user.
+   *
+   * @return The trace information, which has no semantic value, and can be used
+   *         by administrators in order to identify the user.
+   */
+  String getTraceString();
+
+
+
+  /**
+   * Sets the trace information, which has no semantic value, and can be used by
+   * administrators in order to identify the user.
+   *
+   * @param traceString
+   *          The trace information, which has no semantic value, and can be
+   *          used by administrators in order to identify the user.
+   * @return This bind request.
+   * @throws NullPointerException
+   *           If {@code traceString} was {@code null}.
+   */
+  AnonymousSASLBindRequest setTraceString(String traceString)
+      throws NullPointerException;
+}
diff --git a/sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequestImpl.java b/sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequestImpl.java
new file mode 100644
index 0000000..42dabc1
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequestImpl.java
@@ -0,0 +1,129 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.ByteString;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * Anonymous SASL bind request implementation.
+ */
+final class AnonymousSASLBindRequestImpl extends
+    AbstractSASLBindRequest<AnonymousSASLBindRequest> implements
+    AnonymousSASLBindRequest
+{
+  private final static class Client extends SASLBindClientImpl
+  {
+    private Client(final AnonymousSASLBindRequestImpl initialBindRequest,
+        final String serverName)
+    {
+      super(initialBindRequest);
+      setNextSASLCredentials(ByteString.valueOf(initialBindRequest
+          .getTraceString()));
+    }
+  }
+
+
+
+  private String traceString;
+
+
+
+  AnonymousSASLBindRequestImpl(final String traceString)
+  {
+    Validator.ensureNotNull(traceString);
+    this.traceString = traceString;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public BindClient createBindClient(final String serverName)
+  {
+    return new Client(this, serverName);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getSASLMechanism()
+  {
+    return SASL_MECHANISM_NAME;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getTraceString()
+  {
+    return traceString;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public AnonymousSASLBindRequest setTraceString(final String traceString)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(traceString);
+    this.traceString = traceString;
+    return this;
+  }
+
+
+
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("AnonymousSASLBindRequest(bindDN=");
+    builder.append(getName());
+    builder.append(", authentication=SASL");
+    builder.append(", saslMechanism=");
+    builder.append(getSASLMechanism());
+    builder.append(", traceString=");
+    builder.append(traceString);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/requests/BindClient.java b/sdk/src/org/opends/sdk/requests/BindClient.java
new file mode 100644
index 0000000..5738678
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/BindClient.java
@@ -0,0 +1,99 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.ConnectionSecurityLayer;
+import org.opends.sdk.ErrorResultException;
+import org.opends.sdk.responses.BindResult;
+
+
+
+/**
+ * An authentication client which can be used to bind to a server. Specifically,
+ * a bind client manages the state associated with multi-stage authentication
+ * attempts and responds to any challenges returned by the server.
+ */
+public interface BindClient
+{
+  /**
+   * Disposes of any system resources or security-sensitive information that
+   * this bind client might be using. Invoking this method invalidates this
+   * instance.
+   */
+  void dispose();
+
+
+
+  /**
+   * Evaluates the provided bind result and returns {@code true} if
+   * authentication has completed successfully, or {@code false} if additional
+   * authentication steps are required (for example during a multi-stage SASL
+   * authentication attempt).
+   * <p>
+   * If additional steps are required then implementations must update their
+   * internal state based on information contained in the bind result (for
+   * example, using the server provided SASL credentials).
+   *
+   * @param result
+   *          The bind result to be evaluated.
+   * @return {@code true} if authentication has completed successfully, of
+   *         {@code false} if additional steps are required.
+   * @throws ErrorResultException
+   *           If the evaluation failed for some reason and authentication
+   *           cannot continue.
+   */
+  boolean evaluateResult(BindResult result) throws ErrorResultException;
+
+
+
+  /**
+   * Returns a connection security layer, but only if this bind client has
+   * negotiated integrity and/or privacy protection for the underlying
+   * connection. This method should only be called once authentication has
+   * completed.
+   *
+   * @return A connection security layer, or {@code null} if none was
+   *         negotiated.
+   */
+  ConnectionSecurityLayer getConnectionSecurityLayer();
+
+
+
+  /**
+   * Returns the next bind request which should be used for the next stage of
+   * authentication. Initially, this will be a copy of the original bind request
+   * used to create this bind client.
+   *
+   * @return The next bind request which should be used for the next stage of
+   *         authentication.
+   */
+  GenericBindRequest nextBindRequest();
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/BindClientImpl.java b/sdk/src/org/opends/sdk/requests/BindClientImpl.java
new file mode 100644
index 0000000..b88ccc0
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/BindClientImpl.java
@@ -0,0 +1,151 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.ConnectionSecurityLayer;
+import org.opends.sdk.ErrorResultException;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.responses.BindResult;
+
+
+
+/**
+ * Bind client implementation.
+ */
+class BindClientImpl implements BindClient, ConnectionSecurityLayer
+{
+  private final GenericBindRequest nextBindRequest;
+
+
+
+  /**
+   * Creates a new abstract bind client. The next bind request will be a copy of
+   * the provided initial bind request which should be updated in subsequent
+   * bind requests forming part of this authentication.
+   *
+   * @param initialBindRequest
+   *          The initial bind request.
+   */
+  BindClientImpl(final BindRequest initialBindRequest)
+  {
+    this.nextBindRequest = new GenericBindRequestImpl(initialBindRequest
+        .getName(), initialBindRequest.getAuthenticationType(), ByteString
+        .empty(), this);
+    for (final Control control : initialBindRequest.getControls())
+    {
+      this.nextBindRequest.addControl(control);
+    }
+  }
+
+
+
+  /**
+   * Default implementation does nothing.
+   */
+  public void dispose()
+  {
+    // Do nothing.
+  }
+
+
+
+  /**
+   * Default implementation does nothing and always returns {@code true}.
+   */
+  public boolean evaluateResult(final BindResult result)
+      throws ErrorResultException
+  {
+    return true;
+  }
+
+
+
+  /**
+   * Default implementation always returns {@code null}.
+   */
+  public ConnectionSecurityLayer getConnectionSecurityLayer()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * Returns the next bind request.
+   */
+  public final GenericBindRequest nextBindRequest()
+  {
+    return nextBindRequest;
+  }
+
+
+
+  /**
+   * Default implementation just returns the copy of the bytes.
+   */
+  public byte[] unwrap(final byte[] incoming, final int offset, final int len)
+      throws ErrorResultException
+  {
+    final byte[] copy = new byte[len];
+    System.arraycopy(incoming, offset, copy, 0, len);
+    return copy;
+  }
+
+
+
+  /**
+   * Default implementation just returns the copy of the bytes.
+   */
+  public byte[] wrap(final byte[] outgoing, final int offset, final int len)
+      throws ErrorResultException
+  {
+    final byte[] copy = new byte[len];
+    System.arraycopy(outgoing, offset, copy, 0, len);
+    return copy;
+  }
+
+
+
+  /**
+   * Sets the authentication value to be used in the next bind request.
+   *
+   * @param authenticationValue
+   *          The authentication value to be used in the next bind request.
+   * @return A reference to this bind client.
+   */
+  final BindClient setNextAuthenticationValue(
+      final ByteString authenticationValue)
+  {
+    nextBindRequest.setAuthenticationValue(authenticationValue);
+    return this;
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/BindRequest.java b/sdk/src/org/opends/sdk/requests/BindRequest.java
index 62a466d..5d38914 100644
--- a/sdk/src/org/opends/sdk/requests/BindRequest.java
+++ b/sdk/src/org/opends/sdk/requests/BindRequest.java
@@ -29,109 +29,86 @@
 
 
 
-import org.opends.sdk.DN;
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.ErrorResultException;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * The Bind operation allows authentication information to be exchanged
- * between the client and server. The Bind operation should be thought
- * of as the "authenticate" operation.
+ * The Bind operation allows authentication information to be exchanged between
+ * the client and server. The Bind operation should be thought of as the
+ * "authenticate" operation.
  */
 public interface BindRequest extends Request
 {
   /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
-  BindRequest addControl(Control control)
-      throws UnsupportedOperationException, NullPointerException;
+  BindRequest addControl(Control control) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * Creates a new bind client which can be used to perform the authentication
+   * process. This method is called by protocol implementations and is not
+   * intended for use by applications.
+   *
+   * @param serverName
+   *          The non-null fully-qualified host name of the server to
+   *          authenticate to.
+   * @return The new bind client.
+   * @throws ErrorResultException
+   *           If an error occurred while creating the bind client context.
    */
-  BindRequest clearControls() throws UnsupportedOperationException;
+  BindClient createBindClient(String serverName) throws ErrorResultException;
 
 
 
   /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * Returns the authentication mechanism identifier for this generic bind
+   * request as defined by the LDAP protocol. Note that value {@code 0x80} is
+   * reserved for simple authentication and {@code 0xA3} is reserved for SASL
+   * authentication.
+   *
+   * @return The authentication mechanism identifier.
    */
-  Control getControl(String oid) throws NullPointerException;
+  byte getAuthenticationType();
 
 
 
   /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
+   * {@inheritDoc}
    */
-  Iterable<Control> getControls();
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns the distinguished name of the Directory object that the
-   * client wishes to bind as. The distinguished name may be empty (but
-   * never {@code null}) when used for of anonymous binds, or when using
-   * SASL authentication. The server shall not dereference any aliases
-   * in locating the named object.
-   * 
-   * @return The distinguished name of the Directory object that the
-   *         client wishes to bind as.
+   * {@inheritDoc}
    */
-  DN getName();
+  List<Control> getControls();
 
 
 
   /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
+   * Returns the name of the Directory object that the client wishes to bind as.
+   * The name may be empty (but never {@code null}) when used for of anonymous
+   * binds, or when using SASL authentication. The server shall not dereference
+   * any aliases in locating the named object.
+   * <p>
+   * The LDAP protocol defines the Bind name to be a distinguished name, however
+   * some LDAP implementations have relaxed this constraint and allow other
+   * identities to be used, such as the user's email address.
+   *
+   * @return The name of the Directory object that the client wishes to bind as.
    */
-  boolean hasControls();
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  String getName();
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequest.java b/sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequest.java
new file mode 100644
index 0000000..fdd63c3
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequest.java
@@ -0,0 +1,197 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.*;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+
+
+/**
+ * The CRAM-MD5 SASL bind request as defined in draft-ietf-sasl-crammd5. This
+ * SASL mechanism allows a client to perform a simple challenge-response
+ * authentication method, using a keyed MD5 digest. This mechanism does not
+ * provide a security layer.
+ * <p>
+ * The CRAM-MD5 mechanism is intended to have limited use on the Internet. The
+ * mechanism offers inadequate protection against common attacks against
+ * application-level protocols and is prone to interoperability problems.
+ * <p>
+ * The authentication identity is specified using an authorization ID, or
+ * {@code authzId}, as defined in RFC 4513 section 5.2.1.8.
+ *
+ * @see <a
+ *      href="http://tools.ietf.org/html/draft-ietf-sasl-crammd5">draft-ietf-sasl-crammd5
+ *      - The CRAM-MD5 SASL Mechanism </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513 -
+ *      SASL Authorization Identities (authzId) </a>
+ */
+public interface CRAMMD5SASLBindRequest extends SASLBindRequest
+{
+
+  /**
+   * The name of the SASL mechanism based on CRAM-MD5 authentication.
+   */
+  public static final String SASL_MECHANISM_NAME = "CRAM-MD5";
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  CRAMMD5SASLBindRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  BindClient createBindClient(String serverName) throws ErrorResultException;
+
+
+
+  /**
+   * Returns the authentication ID of the user. The authentication ID usually
+   * has the form "dn:" immediately followed by the distinguished name of the
+   * user, or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @return The authentication ID of the user.
+   */
+  String getAuthenticationID();
+
+
+
+  /**
+   * Returns the authentication mechanism identifier for this SASL bind request
+   * as defined by the LDAP protocol, which is always {@code 0xA3}.
+   *
+   * @return The authentication mechanism identifier.
+   */
+  byte getAuthenticationType();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * Returns the name of the Directory object that the client wishes to bind as,
+   * which is always the empty string for SASL authentication.
+   *
+   * @return The name of the Directory object that the client wishes to bind as.
+   */
+  String getName();
+
+
+
+  /**
+   * Returns the password of the user that the client wishes to bind as.
+   *
+   * @return The password of the user that the client wishes to bind as.
+   */
+  ByteString getPassword();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getSASLMechanism();
+
+
+
+  /**
+   * Sets the authentication ID of the user. The authentication ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @param authenticationID
+   *          The authentication ID of the user.
+   * @return This bind request.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authenticationID} was non-empty and did not contain a
+   *           valid authorization ID type.
+   * @throws NullPointerException
+   *           If {@code authenticationID} was {@code null}.
+   */
+  CRAMMD5SASLBindRequest setAuthenticationID(String authenticationID)
+      throws LocalizedIllegalArgumentException, NullPointerException;
+
+
+
+  /**
+   * Sets the password of the user that the client wishes to bind as.
+   *
+   * @param password
+   *          The password of the user that the client wishes to bind as, which
+   *          may be empty.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the password to be set.
+   * @throws NullPointerException
+   *           If {@code password} was {@code null}.
+   */
+  CRAMMD5SASLBindRequest setPassword(ByteString password)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * Sets the password of the user that the client wishes to bind as. The
+   * password will be converted to a UTF-8 octet string.
+   *
+   * @param password
+   *          The password of the user that the client wishes to bind as.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the password to be set.
+   * @throws NullPointerException
+   *           If {@code password} was {@code null}.
+   */
+  CRAMMD5SASLBindRequest setPassword(String password)
+      throws UnsupportedOperationException, NullPointerException;
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestImpl.java b/sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestImpl.java
new file mode 100644
index 0000000..9b925ac
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestImpl.java
@@ -0,0 +1,272 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.ErrorResultException;
+import org.opends.sdk.ResultCode;
+import org.opends.sdk.responses.BindResult;
+import org.opends.sdk.responses.Responses;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * CRAM-MD5 SASL bind request implementation.
+ */
+final class CRAMMD5SASLBindRequestImpl extends
+    AbstractSASLBindRequest<CRAMMD5SASLBindRequest> implements
+    CRAMMD5SASLBindRequest
+{
+  private final static class Client extends SASLBindClientImpl
+  {
+    private final SaslClient saslClient;
+    private final String authenticationID;
+    private final ByteString password;
+
+
+
+    private Client(final CRAMMD5SASLBindRequestImpl initialBindRequest,
+        final String serverName) throws ErrorResultException
+    {
+      super(initialBindRequest);
+
+      this.authenticationID = initialBindRequest.getAuthenticationID();
+      this.password = initialBindRequest.getPassword();
+
+      try
+      {
+        saslClient = Sasl.createSaslClient(
+            new String[] { SASL_MECHANISM_NAME }, null, SASL_DEFAULT_PROTOCOL,
+            serverName, null, this);
+        if (saslClient.hasInitialResponse())
+        {
+          setNextSASLCredentials(saslClient.evaluateChallenge(new byte[0]));
+        }
+        else
+        {
+          setNextSASLCredentials((ByteString) null);
+        }
+      }
+      catch (final SaslException e)
+      {
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
+      }
+    }
+
+
+
+    @Override
+    public void dispose()
+    {
+      try
+      {
+        saslClient.dispose();
+      }
+      catch (final SaslException ignored)
+      {
+        // Ignore the SASL exception.
+      }
+    }
+
+
+
+    @Override
+    public boolean evaluateResult(final BindResult result)
+        throws ErrorResultException
+    {
+      if (result.getResultCode() == ResultCode.SASL_BIND_IN_PROGRESS
+          && result.getServerSASLCredentials() != null)
+      {
+        try
+        {
+          setNextSASLCredentials(saslClient.evaluateChallenge(result
+              .getServerSASLCredentials().toByteArray()));
+          return false;
+        }
+        catch (final SaslException e)
+        {
+          // FIXME: I18N need to have a better error message.
+          // FIXME: Is this the best result code?
+          throw ErrorResultException.wrap(Responses.newResult(
+              ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+              "An error occurred during multi-stage authentication")
+              .setCause(e));
+        }
+      }
+
+      return true;
+    }
+
+
+
+    @Override
+    void handle(final NameCallback callback)
+        throws UnsupportedCallbackException
+    {
+      callback.setName(authenticationID);
+    }
+
+
+
+    @Override
+    void handle(final PasswordCallback callback)
+        throws UnsupportedCallbackException
+    {
+      callback.setPassword(password.toString().toCharArray());
+    }
+  }
+
+
+
+  private String authenticationID;
+
+  private ByteString password;
+
+
+
+  CRAMMD5SASLBindRequestImpl(final String authenticationID,
+      final ByteString password)
+  {
+    Validator.ensureNotNull(authenticationID, password);
+    this.authenticationID = authenticationID;
+    this.password = password;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public BindClient createBindClient(final String serverName)
+      throws ErrorResultException
+  {
+    return new Client(this, serverName);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getAuthenticationID()
+  {
+    return authenticationID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getPassword()
+  {
+    return password;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getSASLMechanism()
+  {
+    return SASL_MECHANISM_NAME;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public CRAMMD5SASLBindRequest setAuthenticationID(
+      final String authenticationID) throws NullPointerException
+  {
+    Validator.ensureNotNull(authenticationID);
+    this.authenticationID = authenticationID;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public CRAMMD5SASLBindRequest setPassword(final ByteString password)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(password);
+    this.password = password;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public CRAMMD5SASLBindRequest setPassword(final String password)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(password);
+    this.password = ByteString.valueOf(password);
+    return this;
+  }
+
+
+
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("CRAMMD5SASLBindRequest(bindDN=");
+    builder.append(getName());
+    builder.append(", authentication=SASL");
+    builder.append(", saslMechanism=");
+    builder.append(getSASLMechanism());
+    builder.append(", authenticationID=");
+    builder.append(authenticationID);
+    builder.append(", password=");
+    builder.append(password);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/requests/CancelExtendedRequest.java b/sdk/src/org/opends/sdk/requests/CancelExtendedRequest.java
new file mode 100644
index 0000000..7bae585
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/CancelExtendedRequest.java
@@ -0,0 +1,143 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+
+
+
+/**
+ * The cancel extended request as defined in RFC 3909. This operation is similar
+ * to the abandon operation, except that it has a response and also requires the
+ * abandoned operation to return a response indicating it was canceled. This
+ * operation should be used instead of the abandon operation when the client
+ * needs an indication of the outcome. This operation may be used to cancel both
+ * interrogation and update operations.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc3909">RFC 3909 - Lightweight
+ *      Directory Access Protocol (LDAP) Cancel Operation </a>
+ */
+public interface CancelExtendedRequest extends ExtendedRequest<ExtendedResult>
+{
+
+  /**
+   * The OID for the cancel extended operation request.
+   */
+  public static final String OID = "1.3.6.1.1.8";
+
+  /**
+   * A decoder which can be used to decode cancel extended operation requests.
+   */
+  public static final ExtendedRequestDecoder<CancelExtendedRequest,
+                                             ExtendedResult> DECODER =
+    new CancelExtendedRequestImpl.RequestDecoder();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  CancelExtendedRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * Returns the message ID of the request to be abandoned.
+   *
+   * @return The message ID of the request to be abandoned.
+   */
+  int getMessageID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getOID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ExtendedResultDecoder<ExtendedResult> getResultDecoder();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ByteString getValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  boolean hasValue();
+
+
+
+  /**
+   * Sets the message ID of the request to be abandoned.
+   *
+   * @param id
+   *          The message ID of the request to be abandoned.
+   * @return This abandon request.
+   * @throws UnsupportedOperationException
+   *           If this abandon request does not permit the message ID to be set.
+   */
+  CancelExtendedRequest setMessageID(int id)
+      throws UnsupportedOperationException;
+}
diff --git a/sdk/src/org/opends/sdk/requests/CancelExtendedRequestImpl.java b/sdk/src/org/opends/sdk/requests/CancelExtendedRequestImpl.java
new file mode 100644
index 0000000..627fa69
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/CancelExtendedRequestImpl.java
@@ -0,0 +1,230 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_EXTOP_CANCEL_CANNOT_DECODE_REQUEST_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_EXTOP_CANCEL_NO_REQUEST_VALUE;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+import org.opends.sdk.responses.Responses;
+
+
+
+/**
+ * Cancel extended request implementation.
+ */
+final class CancelExtendedRequestImpl extends
+    AbstractExtendedRequest<CancelExtendedRequest, ExtendedResult> implements
+    CancelExtendedRequest
+{
+  static final class RequestDecoder implements
+      ExtendedRequestDecoder<CancelExtendedRequest, ExtendedResult>
+  {
+    public CancelExtendedRequest decodeExtendedRequest(
+        final ExtendedRequest<?> request, final DecodeOptions options)
+        throws DecodeException
+    {
+      final ByteString requestValue = request.getValue();
+      if ((requestValue == null) || (requestValue.length() <= 0))
+      {
+        throw DecodeException.error(ERR_EXTOP_CANCEL_NO_REQUEST_VALUE.get());
+      }
+
+      try
+      {
+        final ASN1Reader reader = ASN1.getReader(requestValue);
+        reader.readStartSequence();
+        final int idToCancel = (int) reader.readInteger();
+        reader.readEndSequence();
+
+        final CancelExtendedRequest newRequest = new CancelExtendedRequestImpl(
+            idToCancel);
+
+        for (final Control control : request.getControls())
+        {
+          newRequest.addControl(control);
+        }
+
+        return newRequest;
+      }
+      catch (final IOException e)
+      {
+        final LocalizableMessage message = ERR_EXTOP_CANCEL_CANNOT_DECODE_REQUEST_VALUE
+            .get(getExceptionMessage(e));
+        throw DecodeException.error(message, e);
+      }
+    }
+  }
+
+
+
+  private static final class ResultDecoder implements
+      ExtendedResultDecoder<ExtendedResult>
+  {
+    public ExtendedResult adaptExtendedErrorResult(final ResultCode resultCode,
+        final String matchedDN, final String diagnosticMessage)
+    {
+      return Responses.newGenericExtendedResult(resultCode).setMatchedDN(
+          matchedDN).setDiagnosticMessage(diagnosticMessage);
+    }
+
+
+
+    public ExtendedResult decodeExtendedResult(final ExtendedResult result,
+        final DecodeOptions options) throws DecodeException
+    {
+      // TODO: Should we check to make sure OID and value is null?
+      return result;
+    }
+  }
+
+
+
+  private int messageID;
+
+  // No need to expose this.
+  private static final ExtendedResultDecoder<ExtendedResult> RESULT_DECODER = new ResultDecoder();
+
+
+
+  // Instantiation via factory.
+  CancelExtendedRequestImpl(final int messageID)
+  {
+    this.messageID = messageID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public int getMessageID()
+  {
+    return messageID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ExtendedResultDecoder<ExtendedResult> getResultDecoder()
+  {
+    return RESULT_DECODER;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder(6);
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+
+    try
+    {
+      writer.writeStartSequence();
+      writer.writeInteger(messageID);
+      writer.writeEndSequence();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+
+    return buffer.toByteString();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public CancelExtendedRequest setMessageID(final int id)
+  {
+    this.messageID = id;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("CancelExtendedRequest(requestName=");
+    builder.append(getOID());
+    builder.append(", messageID=");
+    builder.append(messageID);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/requests/CompareRequest.java b/sdk/src/org/opends/sdk/requests/CompareRequest.java
index 0fa70a1..c99b49a 100644
--- a/sdk/src/org/opends/sdk/requests/CompareRequest.java
+++ b/sdk/src/org/opends/sdk/requests/CompareRequest.java
@@ -29,36 +29,26 @@
 
 
 
-import org.opends.sdk.AttributeDescription;
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-import org.opends.sdk.LocalizedIllegalArgumentException;
-import org.opends.sdk.controls.Control;
+import java.util.List;
 
+import org.opends.sdk.*;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * The Compare operation allows a client to compare an assertion value
- * with the values of a particular attribute in a particular entry in
- * the Directory.
+ * The Compare operation allows a client to compare an assertion value with the
+ * values of a particular attribute in a particular entry in the Directory.
  * <p>
- * Note that some directory systems may establish access controls that
- * permit the values of certain attributes (such as {@code userPassword}
- * ) to be compared but not interrogated by other means.
+ * Note that some directory systems may establish access controls that permit
+ * the values of certain attributes (such as {@code userPassword} ) to be
+ * compared but not interrogated by other means.
  */
 public interface CompareRequest extends Request
 {
   /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
   CompareRequest addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -66,19 +56,8 @@
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   */
-  CompareRequest clearControls() throws UnsupportedOperationException;
-
-
-
-  /**
    * Returns the assertion value to be compared.
-   * 
+   *
    * @return The assertion value.
    */
   ByteString getAssertionValue();
@@ -86,9 +65,8 @@
 
 
   /**
-   * Returns the assertion value to be compared decoded as a UTF-8
-   * string.
-   * 
+   * Returns the assertion value to be compared decoded as a UTF-8 string.
+   *
    * @return The assertion value decoded as a UTF-8 string.
    */
   String getAssertionValueAsString();
@@ -97,7 +75,7 @@
 
   /**
    * Returns the name of the attribute to be compared.
-   * 
+   *
    * @return The name of the attribute.
    */
   AttributeDescription getAttributeDescription();
@@ -105,36 +83,24 @@
 
 
   /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
+   * {@inheritDoc}
    */
-  Iterable<Control> getControls();
+  List<Control> getControls();
 
 
 
   /**
-   * Returns the distinguished name of the entry to be compared. The
-   * server shall not dereference any aliases in locating the entry to
-   * be compared.
-   * 
+   * Returns the distinguished name of the entry to be compared. The server
+   * shall not dereference any aliases in locating the entry to be compared.
+   *
    * @return The distinguished name of the entry.
    */
   DN getName();
@@ -142,42 +108,14 @@
 
 
   /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
    * Sets the assertion value to be compared.
-   * 
+   *
    * @param value
    *          The assertion value to be compared.
    * @return This compare request.
    * @throws UnsupportedOperationException
-   *           If this compare request does not permit the assertion
-   *           value to be set.
+   *           If this compare request does not permit the assertion value to be
+   *           set.
    * @throws NullPointerException
    *           If {@code value} was {@code null}.
    */
@@ -189,16 +127,15 @@
   /**
    * Sets the assertion value to be compared.
    * <p>
-   * If the assertion value is not an instance of {@code ByteString}
-   * then it will be converted using the
-   * {@link ByteString#valueOf(Object)} method.
-   * 
+   * If the assertion value is not an instance of {@code ByteString} then it
+   * will be converted using the {@link ByteString#valueOf(Object)} method.
+   *
    * @param value
    *          The assertion value to be compared.
    * @return This compare request.
    * @throws UnsupportedOperationException
-   *           If this compare request does not permit the assertion
-   *           value to be set.
+   *           If this compare request does not permit the assertion value to be
+   *           set.
    * @throws NullPointerException
    *           If {@code value} was {@code null}.
    */
@@ -209,13 +146,13 @@
 
   /**
    * Sets the name of the attribute to be compared.
-   * 
+   *
    * @param attributeDescription
    *          The name of the attribute to be compared.
    * @return This compare request.
    * @throws UnsupportedOperationException
-   *           If this compare request does not permit the attribute
-   *           description to be set.
+   *           If this compare request does not permit the attribute description
+   *           to be set.
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
@@ -227,36 +164,35 @@
 
   /**
    * Sets the name of the attribute to be compared.
-   * 
+   *
    * @param attributeDescription
    *          The name of the attribute to be compared.
    * @return This compare request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the default schema.
+   *           If {@code attributeDescription} could not be decoded using the
+   *           default schema.
    * @throws UnsupportedOperationException
-   *           If this compare request does not permit the attribute
-   *           description to be set.
+   *           If this compare request does not permit the attribute description
+   *           to be set.
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
   CompareRequest setAttributeDescription(String attributeDescription)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Sets the distinguished name of the entry to be compared. The server
-   * shall not dereference any aliases in locating the entry to be
-   * compared.
-   * 
+   * Sets the distinguished name of the entry to be compared. The server shall
+   * not dereference any aliases in locating the entry to be compared.
+   *
    * @param dn
    *          The distinguished name of the entry to be compared.
    * @return This compare request.
    * @throws UnsupportedOperationException
-   *           If this compare request does not permit the distinguished
-   *           name to be set.
+   *           If this compare request does not permit the distinguished name to
+   *           be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
@@ -266,24 +202,21 @@
 
 
   /**
-   * Sets the distinguished name of the entry to be compared. The server
-   * shall not dereference any aliases in locating the entry to be
-   * compared.
-   * 
+   * Sets the distinguished name of the entry to be compared. The server shall
+   * not dereference any aliases in locating the entry to be compared.
+   *
    * @param dn
    *          The distinguished name of the entry to be compared.
    * @return This compare request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} could not be decoded using the default
-   *           schema.
+   *           If {@code dn} could not be decoded using the default schema.
    * @throws UnsupportedOperationException
-   *           If this compare request does not permit the distinguished
-   *           name to be set.
+   *           If this compare request does not permit the distinguished name to
+   *           be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  CompareRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
+  CompareRequest setName(String dn) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException;
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/CompareRequestImpl.java b/sdk/src/org/opends/sdk/requests/CompareRequestImpl.java
index d922e8a..95f1ed9 100644
--- a/sdk/src/org/opends/sdk/requests/CompareRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/CompareRequestImpl.java
@@ -41,8 +41,8 @@
 /**
  * Compare request implementation.
  */
-final class CompareRequestImpl extends
-    AbstractRequestImpl<CompareRequest> implements CompareRequest
+final class CompareRequestImpl extends AbstractRequestImpl<CompareRequest>
+    implements CompareRequest
 {
 
   private AttributeDescription attributeDescription;
@@ -54,9 +54,9 @@
 
 
   /**
-   * Creates a new compare request using the provided distinguished
-   * name, attribute name, and assertion value.
-   * 
+   * Creates a new compare request using the provided distinguished name,
+   * attribute name, and assertion value.
+   *
    * @param name
    *          The distinguished name of the entry to be compared.
    * @param attributeDescription
@@ -67,9 +67,9 @@
    *           If {@code name}, {@code attributeDescription}, or {@code
    *           assertionValue} was {@code null}.
    */
-  CompareRequestImpl(DN name,
-      AttributeDescription attributeDescription,
-      ByteString assertionValue) throws NullPointerException
+  CompareRequestImpl(final DN name,
+      final AttributeDescription attributeDescription,
+      final ByteString assertionValue) throws NullPointerException
   {
     this.name = name;
     this.attributeDescription = attributeDescription;
@@ -121,7 +121,7 @@
   /**
    * {@inheritDoc}
    */
-  public CompareRequest setAssertionValue(ByteString value)
+  public CompareRequest setAssertionValue(final ByteString value)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(value);
@@ -134,7 +134,7 @@
   /**
    * {@inheritDoc}
    */
-  public CompareRequest setAssertionValue(Object value)
+  public CompareRequest setAssertionValue(final Object value)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(value);
@@ -148,7 +148,7 @@
    * {@inheritDoc}
    */
   public CompareRequest setAttributeDescription(
-      AttributeDescription attributeDescription)
+      final AttributeDescription attributeDescription)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(attributeDescription);
@@ -162,9 +162,9 @@
    * {@inheritDoc}
    */
   public CompareRequest setAttributeDescription(
-      String attributeDescription)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
+      final String attributeDescription)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
   {
     Validator.ensureNotNull(attributeDescription);
     this.attributeDescription = AttributeDescription
@@ -177,7 +177,7 @@
   /**
    * {@inheritDoc}
    */
-  public CompareRequest setName(DN dn)
+  public CompareRequest setName(final DN dn)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(dn);
@@ -190,9 +190,9 @@
   /**
    * {@inheritDoc}
    */
-  public CompareRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
+  public CompareRequest setName(final String dn)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
   {
     Validator.ensureNotNull(dn);
     this.name = DN.valueOf(dn);
@@ -222,6 +222,7 @@
 
 
 
+  @Override
   CompareRequest getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/requests/DeleteRequest.java b/sdk/src/org/opends/sdk/requests/DeleteRequest.java
index e6821ac..74aa974 100644
--- a/sdk/src/org/opends/sdk/requests/DeleteRequest.java
+++ b/sdk/src/org/opends/sdk/requests/DeleteRequest.java
@@ -29,23 +29,26 @@
 
 
 
+import java.util.List;
+
 import org.opends.sdk.DN;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.LocalizedIllegalArgumentException;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 import org.opends.sdk.ldif.ChangeRecord;
 import org.opends.sdk.ldif.ChangeRecordVisitor;
 
 
 
-
 /**
- * The Delete operation allows a client to request the removal of an
- * entry from the Directory.
+ * The Delete operation allows a client to request the removal of an entry from
+ * the Directory.
  * <p>
- * Only leaf entries (those with no subordinate entries) can be deleted
- * with this operation. However, addition of the {@code
- * SubtreeDeleteControl} permits whole sub-trees to be deleted using a
- * single Delete request.
+ * Only leaf entries (those with no subordinate entries) can be deleted with
+ * this operation. However, addition of the {@code SubtreeDeleteControl} permits
+ * whole sub-trees to be deleted using a single Delete request.
  */
 public interface DeleteRequest extends Request, ChangeRecord
 {
@@ -57,15 +60,7 @@
 
 
   /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
   DeleteRequest addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -73,47 +68,24 @@
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * {@inheritDoc}
    */
-  DeleteRequest clearControls() throws UnsupportedOperationException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  List<Control> getControls();
 
 
 
   /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
-   */
-  Iterable<Control> getControls();
-
-
-
-  /**
-   * Returns the distinguished name of the entry to be deleted. The
-   * server shall not dereference any aliases in locating the entry to
-   * be deleted.
-   * 
+   * Returns the distinguished name of the entry to be deleted. The server shall
+   * not dereference any aliases in locating the entry to be deleted.
+   *
    * @return The distinguished name of the entry.
    */
   DN getName();
@@ -121,44 +93,15 @@
 
 
   /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Sets the distinguished name of the entry to be deleted. The server
-   * shall not dereference any aliases in locating the entry to be
-   * deleted.
-   * 
+   * Sets the distinguished name of the entry to be deleted. The server shall
+   * not dereference any aliases in locating the entry to be deleted.
+   *
    * @param dn
    *          The distinguished name of the entry to be deleted.
    * @return This delete request.
    * @throws UnsupportedOperationException
-   *           If this delete request does not permit the distinguished
-   *           name to be set.
+   *           If this delete request does not permit the distinguished name to
+   *           be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
@@ -168,24 +111,21 @@
 
 
   /**
-   * Sets the distinguished name of the entry to be deleted. The server
-   * shall not dereference any aliases in locating the entry to be
-   * deleted.
-   * 
+   * Sets the distinguished name of the entry to be deleted. The server shall
+   * not dereference any aliases in locating the entry to be deleted.
+   *
    * @param dn
    *          The distinguished name of the entry to be deleted.
    * @return This delete request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} could not be decoded using the default
-   *           schema.
+   *           If {@code dn} could not be decoded using the default schema.
    * @throws UnsupportedOperationException
-   *           If this delete request does not permit the distinguished
-   *           name to be set.
+   *           If this delete request does not permit the distinguished name to
+   *           be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  DeleteRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
+  DeleteRequest setName(String dn) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException;
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/DeleteRequestImpl.java b/sdk/src/org/opends/sdk/requests/DeleteRequestImpl.java
index c1d3bec..339a570 100644
--- a/sdk/src/org/opends/sdk/requests/DeleteRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/DeleteRequestImpl.java
@@ -40,8 +40,8 @@
 /**
  * Delete request implementation.
  */
-final class DeleteRequestImpl extends
-    AbstractRequestImpl<DeleteRequest> implements DeleteRequest
+final class DeleteRequestImpl extends AbstractRequestImpl<DeleteRequest>
+    implements DeleteRequest
 {
   private DN name;
 
@@ -49,13 +49,13 @@
 
   /**
    * Creates a new delete request using the provided distinguished name.
-   * 
+   *
    * @param name
    *          The distinguished name of the entry to be deleted.
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  DeleteRequestImpl(DN name) throws NullPointerException
+  DeleteRequestImpl(final DN name) throws NullPointerException
   {
     this.name = name;
   }
@@ -65,7 +65,7 @@
   /**
    * {@inheritDoc}
    */
-  public <R, P> R accept(ChangeRecordVisitor<R, P> v, P p)
+  public <R, P> R accept(final ChangeRecordVisitor<R, P> v, final P p)
   {
     return v.visitChangeRecord(p, this);
   }
@@ -85,7 +85,7 @@
   /**
    * {@inheritDoc}
    */
-  public DeleteRequest setName(DN dn)
+  public DeleteRequest setName(final DN dn)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(dn);
@@ -98,9 +98,9 @@
   /**
    * {@inheritDoc}
    */
-  public DeleteRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
+  public DeleteRequest setName(final String dn)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
   {
     Validator.ensureNotNull(dn);
     this.name = DN.valueOf(dn);
@@ -126,6 +126,7 @@
 
 
 
+  @Override
   DeleteRequest getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequest.java b/sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequest.java
new file mode 100644
index 0000000..8c5c653
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequest.java
@@ -0,0 +1,256 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.*;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+
+
+/**
+ * The DIGEST-MD5 SASL bind request as defined in RFC 2831. This SASL mechanism
+ * allows a client to perform a challenge-response authentication method,
+ * similar to HTTP Digest Access Authentication. This mechanism can be used to
+ * negotiate integrity and/or privacy protection for the underlying connection.
+ * <p>
+ * Compared to CRAM-MD5, DIGEST-MD5 prevents chosen plain-text attacks, and
+ * permits the use of third party authentication servers, mutual authentication,
+ * and optimized re-authentication if a client has recently authenticated to a
+ * server.
+ * <p>
+ * The authentication and optional authorization identity is specified using an
+ * authorization ID, or {@code authzId}, as defined in RFC 4513 section 5.2.1.8.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc2831">RFC 2831 - Using Digest
+ *      Authentication as a SASL Mechanism </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513 -
+ *      SASL Authorization Identities (authzId) </a>
+ */
+public interface DigestMD5SASLBindRequest extends SASLBindRequest
+{
+
+  /**
+   * The name of the SASL mechanism based on DIGEST-MD5 authentication.
+   */
+  public static final String SASL_MECHANISM_NAME = "DIGEST-MD5";
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  DigestMD5SASLBindRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  BindClient createBindClient(String serverName) throws ErrorResultException;
+
+
+
+  /**
+   * Returns the authentication ID of the user. The authentication ID usually
+   * has the form "dn:" immediately followed by the distinguished name of the
+   * user, or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @return The authentication ID of the user.
+   */
+  String getAuthenticationID();
+
+
+
+  /**
+   * Returns the authentication mechanism identifier for this SASL bind request
+   * as defined by the LDAP protocol, which is always {@code 0xA3}.
+   *
+   * @return The authentication mechanism identifier.
+   */
+  byte getAuthenticationType();
+
+
+
+  /**
+   * Returns the optional authorization ID of the user which represents an
+   * alternate authorization identity which should be used for subsequent
+   * operations performed on the connection. The authorization ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @return The authorization ID of the user, which may be {@code null}.
+   */
+  String getAuthorizationID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * Returns the name of the Directory object that the client wishes to bind as,
+   * which is always the empty string for SASL authentication.
+   *
+   * @return The name of the Directory object that the client wishes to bind as.
+   */
+  String getName();
+
+
+
+  /**
+   * Returns the password of the user that the client wishes to bind as.
+   *
+   * @return The password of the user that the client wishes to bind as.
+   */
+  ByteString getPassword();
+
+
+
+  /**
+   * Returns the optional realm containing the user's account.
+   *
+   * @return The name of the realm containing the user's account, which may be
+   *         {@code null}.
+   */
+  String getRealm();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getSASLMechanism();
+
+
+
+  /**
+   * Sets the authentication ID of the user. The authentication ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @param authenticationID
+   *          The authentication ID of the user.
+   * @return This bind request.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authenticationID} was non-empty and did not contain a
+   *           valid authorization ID type.
+   * @throws NullPointerException
+   *           If {@code authenticationID} was {@code null}.
+   */
+  DigestMD5SASLBindRequest setAuthenticationID(String authenticationID)
+      throws LocalizedIllegalArgumentException, NullPointerException;
+
+
+
+  /**
+   * Sets the optional authorization ID of the user which represents an
+   * alternate authorization identity which should be used for subsequent
+   * operations performed on the connection. The authorization ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @param authorizationID
+   *          The authorization ID of the user, which may be {@code null}.
+   * @return This bind request.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authorizationID} was non-empty and did not contain a
+   *           valid authorization ID type.
+   */
+  DigestMD5SASLBindRequest setAuthorizationID(String authorizationID)
+      throws LocalizedIllegalArgumentException;
+
+
+
+  /**
+   * Sets the password of the user that the client wishes to bind as.
+   *
+   * @param password
+   *          The password of the user that the client wishes to bind as, which
+   *          may be empty.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the password to be set.
+   * @throws NullPointerException
+   *           If {@code password} was {@code null}.
+   */
+  DigestMD5SASLBindRequest setPassword(ByteString password)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * Sets the password of the user that the client wishes to bind as. The
+   * password will be converted to a UTF-8 octet string.
+   *
+   * @param password
+   *          The password of the user that the client wishes to bind as.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the password to be set.
+   * @throws NullPointerException
+   *           If {@code password} was {@code null}.
+   */
+  DigestMD5SASLBindRequest setPassword(String password)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * Sets the optional realm containing the user's account.
+   *
+   * @param realm
+   *          The name of the realm containing the user's account, which may be
+   *          {@code null}.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the realm to be set.
+   * @throws NullPointerException
+   *           If {@code realm} was {@code null}.
+   */
+  DigestMD5SASLBindRequest setRealm(String realm)
+      throws UnsupportedOperationException, NullPointerException;
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequestImpl.java b/sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequestImpl.java
new file mode 100644
index 0000000..3917be4
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequestImpl.java
@@ -0,0 +1,404 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_SASL_PROTOCOL_ERROR;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.RealmCallback;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.responses.BindResult;
+import org.opends.sdk.responses.Responses;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * Digest-MD5 SASL bind request implementation.
+ */
+final class DigestMD5SASLBindRequestImpl extends
+    AbstractSASLBindRequest<DigestMD5SASLBindRequest> implements
+    DigestMD5SASLBindRequest
+{
+  private final static class Client extends SASLBindClientImpl
+  {
+    private final SaslClient saslClient;
+    private final String authenticationID;
+    private final ByteString password;
+    private final String realm;
+
+
+
+    private Client(final DigestMD5SASLBindRequestImpl initialBindRequest,
+        final String serverName) throws ErrorResultException
+    {
+      super(initialBindRequest);
+
+      this.authenticationID = initialBindRequest.getAuthenticationID();
+      this.password = initialBindRequest.getPassword();
+      this.realm = initialBindRequest.getRealm();
+
+      final Map<String, String> props = new HashMap<String, String>();
+      props.put(Sasl.QOP, "auth-conf,auth-int,auth");
+
+      try
+      {
+        saslClient = Sasl.createSaslClient(
+            new String[] { SASL_MECHANISM_NAME }, initialBindRequest
+                .getAuthorizationID(), SASL_DEFAULT_PROTOCOL, serverName,
+            props, this);
+        if (saslClient.hasInitialResponse())
+        {
+          setNextSASLCredentials(saslClient.evaluateChallenge(new byte[0]));
+        }
+        else
+        {
+          setNextSASLCredentials((ByteString) null);
+        }
+      }
+      catch (final SaslException e)
+      {
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
+      }
+    }
+
+
+
+    @Override
+    public void dispose()
+    {
+      try
+      {
+        saslClient.dispose();
+      }
+      catch (final SaslException ignored)
+      {
+        // Ignore the SASL exception.
+      }
+    }
+
+
+
+    @Override
+    public boolean evaluateResult(final BindResult result)
+        throws ErrorResultException
+    {
+      if (result.getResultCode() == ResultCode.SASL_BIND_IN_PROGRESS
+          && result.getServerSASLCredentials() != null)
+      {
+        try
+        {
+          setNextSASLCredentials(saslClient.evaluateChallenge(result
+              .getServerSASLCredentials().toByteArray()));
+          return false;
+        }
+        catch (final SaslException e)
+        {
+          // FIXME: I18N need to have a better error message.
+          // FIXME: Is this the best result code?
+          throw ErrorResultException.wrap(Responses.newResult(
+              ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+              "An error occurred during multi-stage authentication")
+              .setCause(e));
+        }
+      }
+      return true;
+    }
+
+
+
+    @Override
+    public ConnectionSecurityLayer getConnectionSecurityLayer()
+    {
+      final String qop = (String) saslClient.getNegotiatedProperty(Sasl.QOP);
+      if (qop.equalsIgnoreCase("auth-int") || qop.equalsIgnoreCase("auth-conf"))
+      {
+        return this;
+      }
+      else
+      {
+        return null;
+      }
+    }
+
+
+
+    @Override
+    public byte[] unwrap(final byte[] incoming, final int offset, final int len)
+        throws ErrorResultException
+    {
+      try
+      {
+        return saslClient.unwrap(incoming, offset, len);
+      }
+      catch (final SaslException e)
+      {
+        final LocalizableMessage msg = ERR_SASL_PROTOCOL_ERROR.get(
+            SASL_MECHANISM_NAME, getExceptionMessage(e));
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_DECODING_ERROR).setDiagnosticMessage(
+            msg.toString()).setCause(e));
+      }
+    }
+
+
+
+    @Override
+    public byte[] wrap(final byte[] outgoing, final int offset, final int len)
+        throws ErrorResultException
+    {
+      try
+      {
+        return saslClient.wrap(outgoing, offset, len);
+      }
+      catch (final SaslException e)
+      {
+        final LocalizableMessage msg = ERR_SASL_PROTOCOL_ERROR.get(
+            SASL_MECHANISM_NAME, getExceptionMessage(e));
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_ENCODING_ERROR).setDiagnosticMessage(
+            msg.toString()).setCause(e));
+      }
+    }
+
+
+
+    @Override
+    void handle(final NameCallback callback)
+        throws UnsupportedCallbackException
+    {
+      callback.setName(authenticationID);
+    }
+
+
+
+    @Override
+    void handle(final PasswordCallback callback)
+        throws UnsupportedCallbackException
+    {
+      callback.setPassword(password.toString().toCharArray());
+    }
+
+
+
+    @Override
+    void handle(final RealmCallback callback)
+        throws UnsupportedCallbackException
+    {
+      if (realm == null)
+      {
+        callback.setText(callback.getDefaultText());
+      }
+      else
+      {
+        callback.setText(realm);
+      }
+    }
+
+  }
+
+
+
+  private String authenticationID;
+  private String authorizationID = null;
+  private ByteString password;
+
+  private String realm = null;
+
+
+
+  DigestMD5SASLBindRequestImpl(final String authenticationID,
+      final ByteString password)
+  {
+    Validator.ensureNotNull(authenticationID, password);
+    this.authenticationID = authenticationID;
+    this.password = password;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public BindClient createBindClient(final String serverName)
+      throws ErrorResultException
+  {
+    return new Client(this, serverName);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getAuthenticationID()
+  {
+    return authenticationID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getAuthorizationID()
+  {
+    return authorizationID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getPassword()
+  {
+    return password;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getRealm()
+  {
+    return realm;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getSASLMechanism()
+  {
+    return SASL_MECHANISM_NAME;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public DigestMD5SASLBindRequest setAuthenticationID(
+      final String authenticationID) throws NullPointerException
+  {
+    Validator.ensureNotNull(authenticationID);
+    this.authenticationID = authenticationID;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public DigestMD5SASLBindRequest setAuthorizationID(
+      final String authorizationID)
+  {
+    this.authorizationID = authorizationID;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public DigestMD5SASLBindRequest setPassword(final ByteString password)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(password);
+    this.password = password;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public DigestMD5SASLBindRequest setPassword(final String password)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(password);
+    this.password = ByteString.valueOf(password);
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public DigestMD5SASLBindRequest setRealm(final String realm)
+  {
+    this.realm = realm;
+    return this;
+  }
+
+
+
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("DigestMD5SASLBindRequest(bindDN=");
+    builder.append(getName());
+    builder.append(", authentication=SASL");
+    builder.append(", saslMechanism=");
+    builder.append(getSASLMechanism());
+    builder.append(", authenticationID=");
+    builder.append(authenticationID);
+    builder.append(", authorizationID=");
+    builder.append(authorizationID);
+    builder.append(", realm=");
+    builder.append(realm);
+    builder.append(", password=");
+    builder.append(password);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/requests/ExtendedRequest.java b/sdk/src/org/opends/sdk/requests/ExtendedRequest.java
index 24a0d18..f1ee84c 100644
--- a/sdk/src/org/opends/sdk/requests/ExtendedRequest.java
+++ b/sdk/src/org/opends/sdk/requests/ExtendedRequest.java
@@ -29,35 +29,31 @@
 
 
 
+import java.util.List;
+
 import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
-import org.opends.sdk.extensions.ExtendedOperation;
-import org.opends.sdk.extensions.StartTLSRequest;
-import org.opends.sdk.responses.Result;
+import org.opends.sdk.controls.ControlDecoder;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
 
 
 
 /**
  * The Extended operation allows additional operations to be defined for
- * services not already available in the protocol; for example, to
- * implement an operation which installs transport layer security (see
- * {@link StartTLSRequest}).
- * 
+ * services not already available in the protocol; for example, to implement an
+ * operation which installs transport layer security (see
+ * {@link StartTLSExtendedRequest}).
+ *
  * @param <S>
  *          The type of result.
  */
-public interface ExtendedRequest<S extends Result> extends Request
+public interface ExtendedRequest<S extends ExtendedResult> extends Request
 {
   /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
   ExtendedRequest<S> addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -65,101 +61,60 @@
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * {@inheritDoc}
    */
-  ExtendedRequest<S> clearControls()
-      throws UnsupportedOperationException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  List<Control> getControls();
 
 
 
   /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
+   * Returns the numeric OID associated with this extended request.
+   *
+   * @return The numeric OID associated with this extended request.
    */
-  Iterable<Control> getControls();
+  String getOID();
 
 
 
   /**
-   * Returns the extended operation associated with this extended
+   * Returns a decoder which can be used to decoded responses to this extended
    * request.
-   * <p>
-   * FIXME: this should not be exposed in the public API.
-   * 
-   * @return The extended operation associated with this extended
+   *
+   * @return A decoder which can be used to decoded responses to this extended
    *         request.
    */
-  ExtendedOperation<?, S> getExtendedOperation();
+  ExtendedResultDecoder<S> getResultDecoder();
 
 
 
   /**
-   * Returns the dotted-decimal representation of the unique OID
-   * corresponding to this extended request.
-   * 
-   * @return The dotted-decimal representation of the unique OID.
+   * Returns the value, if any, associated with this extended request. Its
+   * format is defined by the specification of this extended request.
+   *
+   * @return The value associated with this extended request, or {@code null} if
+   *         there is no value.
    */
-  String getRequestName();
+  ByteString getValue();
 
 
 
   /**
-   * Returns the content of this extended request in a form defined by
-   * the extended request.
-   * 
-   * @return The content of this extended request, or {@code null} if
-   *         there is no content.
+   * Returns {@code true} if this extended request has a value. In some
+   * circumstances it may be useful to determine if a extended request has a
+   * value, without actually calculating the value and incurring any performance
+   * costs.
+   *
+   * @return {@code true} if this extended request has a value, or {@code false}
+   *         if there is no value.
    */
-  ByteString getRequestValue();
-
-
-
-  /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  boolean hasValue();
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/ExtendedRequestDecoder.java b/sdk/src/org/opends/sdk/requests/ExtendedRequestDecoder.java
new file mode 100644
index 0000000..104915f
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/ExtendedRequestDecoder.java
@@ -0,0 +1,67 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.responses.ExtendedResult;
+
+
+
+/**
+ * A factory interface for decoding a generic extended request as an extended
+ * request of specific type.
+ *
+ * @param <R>
+ *          The type of extended request.
+ * @param <S>
+ *          The type of result.
+ */
+public interface ExtendedRequestDecoder<R extends ExtendedRequest<S>, S extends ExtendedResult>
+{
+  /**
+   * Decodes the provided extended operation request as an {@code
+   * ExtendedRequest} of type {@code R}.
+   *
+   * @param request
+   *          The extended operation request to be decoded.
+   * @param options
+   *          The set of decode options which should be used when decoding the
+   *          extended operation request.
+   * @return The decoded extended operation request.
+   * @throws DecodeException
+   *           If the provided extended operation request could not be decoded.
+   *           For example, if the request name was wrong, or if the request
+   *           value was invalid.
+   */
+  R decodeExtendedRequest(ExtendedRequest<?> request, DecodeOptions options)
+      throws DecodeException;
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/ExternalSASLBindRequest.java b/sdk/src/org/opends/sdk/requests/ExternalSASLBindRequest.java
new file mode 100644
index 0000000..436d38c
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/ExternalSASLBindRequest.java
@@ -0,0 +1,160 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.ErrorResultException;
+import org.opends.sdk.LocalizedIllegalArgumentException;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+
+
+/**
+ * The External SASL bind request as defined in RFC 4422. This SASL mechanism
+ * allows a client to request the server to use credentials established by means
+ * external to the mechanism to authenticate the client. The external means may
+ * be, for instance, SSL or TLS.
+ * <p>
+ * A client may either request that its authorization identity be automatically
+ * derived from its authentication credentials exchanged at a lower security
+ * layer, or it may explicitly provide a desired authorization identity.
+ * <p>
+ * The optional authorization identity is specified using an authorization ID,
+ * or {@code authzId}, as defined in RFC 4513 section 5.2.1.8.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4422">RFC 4422 - Simple
+ *      Authentication and Security Layer (SASL) </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513 -
+ *      SASL Authorization Identities (authzId) </a>
+ */
+public interface ExternalSASLBindRequest extends SASLBindRequest
+{
+
+  /**
+   * The name of the SASL mechanism based on external authentication.
+   */
+  public static final String SASL_MECHANISM_NAME = "EXTERNAL";
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ExternalSASLBindRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  BindClient createBindClient(String serverName) throws ErrorResultException;
+
+
+
+  /**
+   * Returns the authentication mechanism identifier for this SASL bind request
+   * as defined by the LDAP protocol, which is always {@code 0xA3}.
+   *
+   * @return The authentication mechanism identifier.
+   */
+  byte getAuthenticationType();
+
+
+
+  /**
+   * Returns the optional desired authorization ID of the user, or {@code null}
+   * if the authorization ID should derived from authentication credentials
+   * exchanged at a lower security layer. The authorization ID usually has the
+   * form "dn:" immediately followed by the distinguished name of the user, or
+   * "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @return The desired authorization ID of the user, which may be {@code null}
+   *         .
+   */
+  String getAuthorizationID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * Returns the name of the Directory object that the client wishes to bind as,
+   * which is always the empty string for SASL authentication.
+   *
+   * @return The name of the Directory object that the client wishes to bind as.
+   */
+  String getName();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getSASLMechanism();
+
+
+
+  /**
+   * Sets the optional desired authorization ID of the user, or {@code null} if
+   * the authorization ID should derived from authentication credentials
+   * exchanged at a lower security layer. The authorization ID usually has the
+   * form "dn:" immediately followed by the distinguished name of the user, or
+   * "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @param authorizationID
+   *          The desired authorization ID of the user, which may be {@code
+   *          null}.
+   * @return This bind request.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authorizationID} was non-empty and did not contain a
+   *           valid authorization ID type.
+   */
+  ExternalSASLBindRequest setAuthorizationID(String authorizationID)
+      throws LocalizedIllegalArgumentException;
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/ExternalSASLBindRequestImpl.java b/sdk/src/org/opends/sdk/requests/ExternalSASLBindRequestImpl.java
new file mode 100644
index 0000000..80acd82
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/ExternalSASLBindRequestImpl.java
@@ -0,0 +1,199 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.ErrorResultException;
+import org.opends.sdk.ResultCode;
+import org.opends.sdk.responses.BindResult;
+import org.opends.sdk.responses.Responses;
+
+
+
+/**
+ * External SASL bind request implementation.
+ */
+final class ExternalSASLBindRequestImpl extends
+    AbstractSASLBindRequest<ExternalSASLBindRequest> implements
+    ExternalSASLBindRequest
+{
+  private final static class Client extends SASLBindClientImpl
+  {
+    private final SaslClient saslClient;
+
+
+
+    private Client(final ExternalSASLBindRequestImpl initialBindRequest,
+        final String serverName) throws ErrorResultException
+    {
+      super(initialBindRequest);
+
+      try
+      {
+        saslClient = Sasl.createSaslClient(
+            new String[] { SASL_MECHANISM_NAME }, initialBindRequest
+                .getAuthorizationID(), SASL_DEFAULT_PROTOCOL, serverName, null,
+            this);
+        if (saslClient.hasInitialResponse())
+        {
+          setNextSASLCredentials(saslClient.evaluateChallenge(new byte[0]));
+        }
+        else
+        {
+          setNextSASLCredentials((ByteString) null);
+        }
+      }
+      catch (final SaslException e)
+      {
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
+      }
+    }
+
+
+
+    @Override
+    public void dispose()
+    {
+      try
+      {
+        saslClient.dispose();
+      }
+      catch (final SaslException ignored)
+      {
+        // Ignore the SASL exception.
+      }
+    }
+
+
+
+    @Override
+    public boolean evaluateResult(final BindResult result)
+        throws ErrorResultException
+    {
+      if (result.getResultCode() == ResultCode.SASL_BIND_IN_PROGRESS
+          && result.getServerSASLCredentials() != null)
+      {
+        try
+        {
+          setNextSASLCredentials(saslClient.evaluateChallenge(result
+              .getServerSASLCredentials().toByteArray()));
+          return false;
+        }
+        catch (final SaslException e)
+        {
+          // FIXME: I18N need to have a better error message.
+          // FIXME: Is this the best result code?
+          throw ErrorResultException.wrap(Responses.newResult(
+              ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+              "An error occurred during multi-stage authentication")
+              .setCause(e));
+        }
+      }
+      return true;
+    }
+  }
+
+
+
+  private String authorizationID = null;
+
+
+
+  ExternalSASLBindRequestImpl()
+  {
+    // Nothing to do.
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public BindClient createBindClient(final String serverName)
+      throws ErrorResultException
+  {
+    return new Client(this, serverName);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getAuthorizationID()
+  {
+    return authorizationID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getSASLMechanism()
+  {
+    return SASL_MECHANISM_NAME;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ExternalSASLBindRequest setAuthorizationID(final String authorizationID)
+  {
+    this.authorizationID = authorizationID;
+    return this;
+  }
+
+
+
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("ExternalSASLBindRequest(bindDN=");
+    builder.append(getName());
+    builder.append(", authentication=SASL");
+    builder.append(", saslMechanism=");
+    builder.append(getSASLMechanism());
+    builder.append(", authorizationID=");
+    builder.append(authorizationID);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequest.java b/sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequest.java
new file mode 100644
index 0000000..78b8742
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequest.java
@@ -0,0 +1,330 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import javax.security.auth.Subject;
+
+import org.opends.sdk.*;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+
+
+/**
+ * The GSSAPI SASL bind request as defined in RFC 2831. This SASL mechanism
+ * allows a client to use the Generic Security Service Application Program
+ * Interface (GSS-API) Kerberos V5 to authenticate to the server. This mechanism
+ * can be used to negotiate integrity and/or privacy protection for the
+ * underlying connection.
+ * <p>
+ * The optional authorization identity is specified using an authorization ID,
+ * or {@code authzId}, as defined in RFC 4513 section 5.2.1.8.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4752">RFC 4752 - The Kerberos V5
+ *      ("GSSAPI") Simple Authentication and Security Layer (SASL) Mechanism
+ *      </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513 -
+ *      SASL Authorization Identities (authzId) </a>
+ */
+public interface GSSAPISASLBindRequest extends SASLBindRequest
+{
+
+  /**
+   * The name of the SASL mechanism based on GSS-API authentication.
+   */
+  public static final String SASL_MECHANISM_NAME = "GSSAPI";
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  GSSAPISASLBindRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  BindClient createBindClient(String serverName) throws ErrorResultException;
+
+
+
+  /**
+   * Returns the authentication ID of the user, which should be the user's
+   * Kerberos principal. The authentication ID usually has the form "dn:"
+   * immediately followed by the distinguished name of the user, or "u:"
+   * followed by a user ID string, but other forms are permitted.
+   * <p>
+   * <b>NOTE</b>: this will not be used if a {@code Subject} is specified.
+   *
+   * @return The authentication ID of the user.
+   */
+  String getAuthenticationID();
+
+
+
+  /**
+   * Returns the authentication mechanism identifier for this SASL bind request
+   * as defined by the LDAP protocol, which is always {@code 0xA3}.
+   *
+   * @return The authentication mechanism identifier.
+   */
+  byte getAuthenticationType();
+
+
+
+  /**
+   * Returns the optional authorization ID of the user which represents an
+   * alternate authorization identity which should be used for subsequent
+   * operations performed on the connection. The authorization ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @return The authorization ID of the user, which may be {@code null}.
+   */
+  String getAuthorizationID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * Returns the optional address of the Kerberos KDC (Key Distribution Center).
+   * <p>
+   * <b>NOTE</b>: this will not be used if a {@code Subject} is specified.
+   *
+   * @return The address of the Kerberos KDC (Key Distribution Center), which
+   *         may be {@code null}.
+   */
+  String getKDCAddress();
+
+
+
+  /**
+   * Returns the name of the Directory object that the client wishes to bind as,
+   * which is always the empty string for SASL authentication.
+   *
+   * @return The name of the Directory object that the client wishes to bind as.
+   */
+  String getName();
+
+
+
+  /**
+   * Returns the password of the user that the client wishes to bind as.
+   * <p>
+   * <b>NOTE</b>: this will not be used if a {@code Subject} is specified.
+   *
+   * @return The password of the user that the client wishes to bind as.
+   */
+  ByteString getPassword();
+
+
+
+  /**
+   * Returns the optional realm containing the user's account.
+   * <p>
+   * <b>NOTE</b>: this will not be used if a {@code Subject} is specified.
+   *
+   * @return The name of the realm containing the user's account, which may be
+   *         {@code null}.
+   */
+  String getRealm();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getSASLMechanism();
+
+
+
+  /**
+   * Returns the Kerberos subject of the user to be authenticated.
+   * <p>
+   * <b>NOTE</b>: if a {@code Subject} is specified then the authentication ID,
+   * KDC address, password, and realm, will be ignored.
+   *
+   * @return The Kerberos subject of the user to be authenticated.
+   */
+  Subject getSubject();
+
+
+
+  /**
+   * Sets the authentication ID of the user, which should be the user's Kerberos
+   * principal. The authentication ID usually has the form "dn:" immediately
+   * followed by the distinguished name of the user, or "u:" followed by a user
+   * ID string, but other forms are permitted.
+   * <p>
+   * <b>NOTE</b>: this will not be used if a {@code Subject} is specified.
+   *
+   * @param authenticationID
+   *          The authentication ID of the user.
+   * @return This bind request.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authenticationID} was non-empty and did not contain a
+   *           valid authorization ID type.
+   * @throws NullPointerException
+   *           If {@code authenticationID} was {@code null}.
+   */
+  GSSAPISASLBindRequest setAuthenticationID(String authenticationID)
+      throws LocalizedIllegalArgumentException, NullPointerException;
+
+
+
+  /**
+   * Sets the optional authorization ID of the user which represents an
+   * alternate authorization identity which should be used for subsequent
+   * operations performed on the connection. The authorization ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @param authorizationID
+   *          The authorization ID of the user, which may be {@code null}.
+   * @return This bind request.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authorizationID} was non-empty and did not contain a
+   *           valid authorization ID type.
+   */
+  GSSAPISASLBindRequest setAuthorizationID(String authorizationID)
+      throws LocalizedIllegalArgumentException;
+
+
+
+  /**
+   * Sets the optional address of the Kerberos KDC (Key Distribution Center).
+   * <p>
+   * <b>NOTE</b>: this will not be used if a {@code Subject} is specified.
+   *
+   * @param address
+   *          The address of the Kerberos KDC (Key Distribution Center), which
+   *          may be {@code null}.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the KDC address to be set.
+   * @throws NullPointerException
+   *           If {@code address} was {@code null}.
+   */
+  GSSAPISASLBindRequest setKDCAddress(String address)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * Sets the password of the user that the client wishes to bind as.
+   * <p>
+   * <b>NOTE</b>: this will not be used if a {@code Subject} is specified.
+   *
+   * @param password
+   *          The password of the user that the client wishes to bind as, which
+   *          may be empty.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the password to be set.
+   * @throws NullPointerException
+   *           If {@code password} was {@code null}.
+   */
+  GSSAPISASLBindRequest setPassword(ByteString password)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * Sets the password of the user that the client wishes to bind as. The
+   * password will be converted to a UTF-8 octet string.
+   * <p>
+   * <b>NOTE</b>: this will not be used if a {@code Subject} is specified.
+   *
+   * @param password
+   *          The password of the user that the client wishes to bind as.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the password to be set.
+   * @throws NullPointerException
+   *           If {@code password} was {@code null}.
+   */
+  GSSAPISASLBindRequest setPassword(String password)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * Sets the optional realm containing the user's account.
+   * <p>
+   * <b>NOTE</b>: this will not be used if a {@code Subject} is specified.
+   *
+   * @param realm
+   *          The name of the realm containing the user's account, which may be
+   *          {@code null}.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the realm to be set.
+   * @throws NullPointerException
+   *           If {@code realm} was {@code null}.
+   */
+  GSSAPISASLBindRequest setRealm(String realm)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * Sets the Kerberos subject of the user to be authenticated.
+   * <p>
+   * <b>NOTE</b>: if a {@code Subject} is specified then the authentication ID,
+   * KDC address, password, and realm, will be ignored.
+   *
+   * @param subject
+   *          The Kerberos subject of the user to be authenticated.
+   * @return This bind request.
+   * @throws NullPointerException
+   *           If {@code subject} was {@code null}.
+   */
+  GSSAPISASLBindRequest setSubject(Subject subject) throws NullPointerException;
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequestImpl.java b/sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequestImpl.java
new file mode 100644
index 0000000..18bc856
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequestImpl.java
@@ -0,0 +1,573 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_LDAPAUTH_GSSAPI_LOCAL_AUTHENTICATION_FAILED;
+import static com.sun.opends.sdk.messages.Messages.ERR_SASL_CONTEXT_CREATE_ERROR;
+import static com.sun.opends.sdk.messages.Messages.ERR_SASL_PROTOCOL_ERROR;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+import javax.security.auth.login.LoginException;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.responses.BindResult;
+import org.opends.sdk.responses.Responses;
+
+import com.sun.opends.sdk.util.StaticUtils;
+import com.sun.opends.sdk.util.Validator;
+import com.sun.security.auth.callback.TextCallbackHandler;
+import com.sun.security.auth.module.Krb5LoginModule;
+
+
+
+/**
+ * GSSAPI SASL bind request implementation.
+ */
+final class GSSAPISASLBindRequestImpl extends
+    AbstractSASLBindRequest<GSSAPISASLBindRequest> implements
+    GSSAPISASLBindRequest
+{
+  private final static class Client extends SASLBindClientImpl
+  {
+    private static Subject kerberos5Login(final String authenticationID,
+        final ByteString password, final String realm, final String kdc)
+        throws ErrorResultException
+    {
+      if (authenticationID == null)
+      {
+        // FIXME: I18N need to have a better error message.
+        // FIXME: Is this the best result code?
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+            "No authentication ID specified for GSSAPI SASL authentication"));
+      }
+
+      if (password == null)
+      {
+        // FIXME: I18N need to have a better error message.
+        // FIXME: Is this the best result code?
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+            "No password specified for GSSAPI SASL authentication"));
+      }
+
+      final Map<String, Object> state = new HashMap<String, Object>();
+      state.put("javax.security.auth.login.name", authenticationID);
+      state.put("javax.security.auth.login.password", password.toString()
+          .toCharArray());
+      state.put("javax.security.auth.useSubjectCredsOnly", "true");
+      state.put("java.security.krb5.realm", realm);
+      state.put("java.security.krb5.kdc", kdc);
+
+      final Map<String, Object> options = new HashMap<String, Object>();
+      options.put("debug", "true");
+      options.put("tryFirstPass", "true");
+      options.put("useTicketCache", "true");
+      options.put("doNotPrompt", "true");
+      options.put("storePass", "false");
+      options.put("forwardable", "true");
+
+      final Subject subject = new Subject();
+      final Krb5LoginModule login = new Krb5LoginModule();
+      login.initialize(subject, new TextCallbackHandler(), state, options);
+      try
+      {
+        if (login.login())
+        {
+          login.commit();
+        }
+      }
+      catch (final LoginException e)
+      {
+        // FIXME: Is this the best result code?
+        final LocalizableMessage message = ERR_LDAPAUTH_GSSAPI_LOCAL_AUTHENTICATION_FAILED
+            .get(StaticUtils.getExceptionMessage(e));
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+            message.toString()).setCause(e));
+      }
+      return subject;
+    }
+
+
+
+    private final SaslClient saslClient;
+    private final String serverName;
+    private final String authorizationID;
+    private final Subject subject;
+
+    private BindResult lastResult;
+
+    private final PrivilegedExceptionAction<Boolean> evaluateAction =
+      new PrivilegedExceptionAction<Boolean>()
+    {
+      public Boolean run() throws ErrorResultException
+      {
+        if (lastResult.getResultCode() == ResultCode.SASL_BIND_IN_PROGRESS
+            && lastResult.getServerSASLCredentials() != null)
+        {
+          try
+          {
+            setNextSASLCredentials(saslClient.evaluateChallenge(lastResult
+                .getServerSASLCredentials().toByteArray()));
+            return false;
+          }
+          catch (final SaslException e)
+          {
+            // FIXME: I18N need to have a better error message.
+            // FIXME: Is this the best result code?
+            throw ErrorResultException.wrap(Responses.newResult(
+                ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+                "An error occurred during multi-stage authentication")
+                .setCause(e));
+          }
+        }
+        return true;
+      }
+    };
+
+    private final PrivilegedExceptionAction<SaslClient> invokeAction =
+      new PrivilegedExceptionAction<SaslClient>()
+    {
+      public SaslClient run() throws ErrorResultException
+      {
+        final Map<String, String> props = new HashMap<String, String>();
+        props.put(Sasl.QOP, "auth-conf,auth-int,auth");
+
+        try
+        {
+          final SaslClient saslClient = Sasl.createSaslClient(
+              new String[] { SASL_MECHANISM_NAME }, authorizationID,
+              SASL_DEFAULT_PROTOCOL, serverName, props, Client.this);
+          if (saslClient.hasInitialResponse())
+          {
+            setNextSASLCredentials(saslClient.evaluateChallenge(new byte[0]));
+          }
+          else
+          {
+            setNextSASLCredentials((ByteString) null);
+          }
+        }
+        catch (final SaslException e)
+        {
+          throw ErrorResultException.wrap(Responses.newResult(
+              ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
+        }
+        return saslClient;
+      }
+    };
+
+
+
+    private Client(final GSSAPISASLBindRequestImpl initialBindRequest,
+        final String serverName) throws ErrorResultException
+    {
+      super(initialBindRequest);
+
+      this.authorizationID = initialBindRequest.getAuthorizationID();
+      if (initialBindRequest.getSubject() != null)
+      {
+        this.subject = initialBindRequest.getSubject();
+      }
+      else
+      {
+        this.subject = kerberos5Login(initialBindRequest.getAuthenticationID(),
+            initialBindRequest.getPassword(), initialBindRequest.getRealm(),
+            initialBindRequest.getKDCAddress());
+      }
+      this.serverName = serverName;
+
+      try
+      {
+        this.saslClient = Subject.doAs(subject, invokeAction);
+      }
+      catch (final PrivilegedActionException e)
+      {
+        if (e.getCause() instanceof ErrorResultException)
+        {
+          throw (ErrorResultException) e.getCause();
+        }
+        else
+        {
+          // This should not happen. Must be a bug.
+          final LocalizableMessage msg = ERR_SASL_CONTEXT_CREATE_ERROR.get(
+              SASL_MECHANISM_NAME, getExceptionMessage(e));
+          throw ErrorResultException.wrap(Responses.newResult(
+              ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+              msg.toString()).setCause(e));
+        }
+      }
+    }
+
+
+
+    @Override
+    public void dispose()
+    {
+      try
+      {
+        saslClient.dispose();
+      }
+      catch (final SaslException ignored)
+      {
+        // Ignore the SASL exception.
+      }
+    }
+
+
+
+    @Override
+    public boolean evaluateResult(final BindResult result)
+        throws ErrorResultException
+    {
+      this.lastResult = result;
+      try
+      {
+        return Subject.doAs(subject, evaluateAction);
+      }
+      catch (final PrivilegedActionException e)
+      {
+        if (e.getCause() instanceof ErrorResultException)
+        {
+          throw (ErrorResultException) e.getCause();
+        }
+        else
+        {
+          // This should not happen. Must be a bug.
+          final LocalizableMessage msg = ERR_SASL_PROTOCOL_ERROR.get(
+              SASL_MECHANISM_NAME, getExceptionMessage(e));
+          throw ErrorResultException.wrap(Responses.newResult(
+              ResultCode.CLIENT_SIDE_LOCAL_ERROR).setDiagnosticMessage(
+              msg.toString()).setCause(e));
+        }
+      }
+    }
+
+
+
+    @Override
+    public ConnectionSecurityLayer getConnectionSecurityLayer()
+    {
+      final String qop = (String) saslClient.getNegotiatedProperty(Sasl.QOP);
+      if (qop.equalsIgnoreCase("auth-int") || qop.equalsIgnoreCase("auth-conf"))
+      {
+        return this;
+      }
+      else
+      {
+        return null;
+      }
+    }
+
+
+
+    @Override
+    public byte[] unwrap(final byte[] incoming, final int offset, final int len)
+        throws ErrorResultException
+    {
+      try
+      {
+        return saslClient.unwrap(incoming, offset, len);
+      }
+      catch (final SaslException e)
+      {
+        final LocalizableMessage msg = ERR_SASL_PROTOCOL_ERROR.get(
+            SASL_MECHANISM_NAME, getExceptionMessage(e));
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_DECODING_ERROR).setDiagnosticMessage(
+            msg.toString()).setCause(e));
+      }
+    }
+
+
+
+    @Override
+    public byte[] wrap(final byte[] outgoing, final int offset, final int len)
+        throws ErrorResultException
+    {
+      try
+      {
+        return saslClient.wrap(outgoing, offset, len);
+      }
+      catch (final SaslException e)
+      {
+        final LocalizableMessage msg = ERR_SASL_PROTOCOL_ERROR.get(
+            SASL_MECHANISM_NAME, getExceptionMessage(e));
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_ENCODING_ERROR).setDiagnosticMessage(
+            msg.toString()).setCause(e));
+      }
+    }
+
+  }
+
+
+
+  // If null then authenticationID and password must be present.
+  private Subject subject = null;
+  // Ignored if subject is non-null.
+  private String authenticationID = null;
+  private ByteString password = null;
+  private String realm = null;
+
+  private String kdcAddress = null;
+
+  // Optional authorization ID.
+  private String authorizationID = null;
+
+
+
+  GSSAPISASLBindRequestImpl(final String authenticationID,
+      final ByteString password)
+  {
+    Validator.ensureNotNull(authenticationID, password);
+    this.authenticationID = authenticationID;
+    this.password = password;
+  }
+
+
+
+  GSSAPISASLBindRequestImpl(final Subject subject)
+  {
+    Validator.ensureNotNull(subject);
+    this.subject = subject;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public BindClient createBindClient(final String serverName)
+      throws ErrorResultException
+  {
+    return new Client(this, serverName);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getAuthenticationID()
+  {
+    return authenticationID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getAuthorizationID()
+  {
+    return authorizationID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getKDCAddress()
+  {
+    return kdcAddress;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getPassword()
+  {
+    return password;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getRealm()
+  {
+    return realm;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getSASLMechanism()
+  {
+    return SASL_MECHANISM_NAME;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Subject getSubject()
+  {
+    return subject;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public GSSAPISASLBindRequest setAuthenticationID(final String authenticationID)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(authenticationID);
+    this.authenticationID = authenticationID;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public GSSAPISASLBindRequest setAuthorizationID(final String authorizationID)
+  {
+    this.authorizationID = authorizationID;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public GSSAPISASLBindRequest setKDCAddress(final String address)
+  {
+    this.kdcAddress = address;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public GSSAPISASLBindRequest setPassword(final ByteString password)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(password);
+    this.password = password;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public GSSAPISASLBindRequest setPassword(final String password)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(password);
+    this.password = ByteString.valueOf(password);
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public GSSAPISASLBindRequest setRealm(final String realm)
+  {
+    this.realm = realm;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public GSSAPISASLBindRequest setSubject(final Subject subject)
+      throws NullPointerException
+  {
+    this.subject = subject;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("GSSAPISASLBindRequest(bindDN=");
+    builder.append(getName());
+    builder.append(", authentication=SASL");
+    builder.append(", saslMechanism=");
+    builder.append(getSASLMechanism());
+    if (subject != null)
+    {
+      builder.append(", subject=");
+      builder.append(subject);
+    }
+    else
+    {
+      builder.append(", authenticationID=");
+      builder.append(authenticationID);
+      builder.append(", authorizationID=");
+      builder.append(authorizationID);
+      builder.append(", realm=");
+      builder.append(realm);
+      builder.append(", password=");
+      builder.append(password);
+    }
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/GenericBindRequest.java b/sdk/src/org/opends/sdk/requests/GenericBindRequest.java
index a10905e..1776617 100644
--- a/sdk/src/org/opends/sdk/requests/GenericBindRequest.java
+++ b/sdk/src/org/opends/sdk/requests/GenericBindRequest.java
@@ -29,33 +29,24 @@
 
 
 
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-import org.opends.sdk.LocalizedIllegalArgumentException;
-import org.opends.sdk.ResultCode;
-import org.opends.sdk.controls.Control;
+import java.util.List;
 
+import org.opends.sdk.*;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * A generic Bind request which should be used for unsupported
- * authentication methods. Servers that do not support a choice supplied
- * by a client return a Bind response with the result code set to
+ * A generic Bind request which should be used for unsupported authentication
+ * methods. Servers that do not support a choice supplied by a client return a
+ * Bind response with the result code set to
  * {@link ResultCode#AUTH_METHOD_NOT_SUPPORTED}.
  */
 public interface GenericBindRequest extends BindRequest
 {
   /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
   GenericBindRequest addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -63,33 +54,23 @@
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * {@inheritDoc}
    */
-  GenericBindRequest clearControls()
-      throws UnsupportedOperationException;
+  BindClient createBindClient(String serverName) throws ErrorResultException;
 
 
 
   /**
-   * Returns the authentication mechanism identifier for this generic
-   * bind request. Note that value {@code 0} is reserved for simple
-   * authentication, {@code 1} and {@code 2} are reserved but unused,
-   * and {@code 3} is reserved for SASL authentication.
-   * 
-   * @return The authentication mechanism identifier.
+   * {@inheritDoc}
    */
   byte getAuthenticationType();
 
 
 
   /**
-   * Returns the authentication information for this generic bind
-   * request in a form defined by the authentication mechanism.
-   * 
+   * Returns the authentication information for this bind request. The content
+   * is defined by the authentication mechanism.
+   *
    * @return The authentication information.
    */
   ByteString getAuthenticationValue();
@@ -97,79 +78,40 @@
 
 
   /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
-
-
-
-  /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
-   */
-  Iterable<Control> getControls();
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  DN getName();
+  List<Control> getControls();
 
 
 
   /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
+   * {@inheritDoc}
    */
-  boolean hasControls();
+  String getName();
 
 
 
   /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Sets the authentication mechanism identifier for this generic bind
-   * request. Note that value {@code 0} is reserved for simple
-   * authentication, {@code 1} and {@code 2} are reserved but unused,
-   * and {@code 3} is reserved for SASL authentication.
-   * 
+   * Sets the authentication mechanism identifier for this generic bind request.
+   * Note that value {@code 0} is reserved for simple authentication, {@code 1}
+   * and {@code 2} are reserved but unused, and {@code 3} is reserved for SASL
+   * authentication.
+   *
    * @param type
-   *          The authentication mechanism identifier for this generic
-   *          bind request.
+   *          The authentication mechanism identifier for this generic bind
+   *          request.
    * @return This generic bind request.
    * @throws UnsupportedOperationException
-   *           If this generic bind request does not permit the
-   *           authentication type to be set.
+   *           If this generic bind request does not permit the authentication
+   *           type to be set.
    */
   GenericBindRequest setAuthenticationType(byte type)
       throws UnsupportedOperationException;
@@ -177,16 +119,16 @@
 
 
   /**
-   * Sets the authentication information for this generic bind request
-   * in a form defined by the authentication mechanism.
-   * 
+   * Sets the authentication information for this generic bind request in a form
+   * defined by the authentication mechanism.
+   *
    * @param bytes
-   *          The authentication information for this generic bind
-   *          request in a form defined by the authentication mechanism.
+   *          The authentication information for this generic bind request in a
+   *          form defined by the authentication mechanism.
    * @return This generic bind request.
    * @throws UnsupportedOperationException
-   *           If this generic bind request does not permit the
-   *           authentication bytes to be set.
+   *           If this generic bind request does not permit the authentication
+   *           bytes to be set.
    * @throws NullPointerException
    *           If {@code bytes} was {@code null}.
    */
@@ -196,49 +138,26 @@
 
 
   /**
-   * Sets the distinguished name of the Directory object that the client
-   * wishes to bind as. The distinguished name may be empty (but never
-   * {@code null} when used for of anonymous binds, or when using SASL
-   * authentication. The server shall not dereference any aliases in
-   * locating the named object.
-   * 
-   * @param dn
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as.
+   * Sets the name of the Directory object that the client wishes to bind as.
+   * The name may be empty (but never {@code null} when used for of anonymous
+   * binds, or when using SASL authentication. The server shall not dereference
+   * any aliases in locating the named object.
+   * <p>
+   * The LDAP protocol defines the Bind name to be a distinguished name, however
+   * some LDAP implementations have relaxed this constraint and allow other
+   * identities to be used, such as the user's email address.
+   *
+   * @param name
+   *          The name of the Directory object that the client wishes to bind
+   *          as.
    * @return This bind request.
    * @throws UnsupportedOperationException
-   *           If this bind request does not permit the distinguished
-   *           name to be set.
+   *           If this bind request does not permit the distinguished name to be
+   *           set.
    * @throws NullPointerException
-   *           If {@code dn} was {@code null}.
+   *           If {@code name} was {@code null}.
    */
-  GenericBindRequest setName(DN dn)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Sets the distinguished name of the Directory object that the client
-   * wishes to bind as. The distinguished name may be empty (but never
-   * {@code null} when used for of anonymous binds, or when using SASL
-   * authentication. The server shall not dereference any aliases in
-   * locating the named object.
-   * 
-   * @param dn
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as.
-   * @return This bind request.
-   * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} could not be decoded using the default
-   *           schema.
-   * @throws UnsupportedOperationException
-   *           If this bind request does not permit the distinguished
-   *           name to be set.
-   * @throws NullPointerException
-   *           If {@code dn} was {@code null}.
-   */
-  GenericBindRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
+  GenericBindRequest setName(String name) throws UnsupportedOperationException,
+      NullPointerException;
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/GenericBindRequestImpl.java b/sdk/src/org/opends/sdk/requests/GenericBindRequestImpl.java
index bbbb6ff..952dcc1 100644
--- a/sdk/src/org/opends/sdk/requests/GenericBindRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/GenericBindRequestImpl.java
@@ -30,8 +30,7 @@
 
 
 import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-import org.opends.sdk.LocalizedIllegalArgumentException;
+import org.opends.sdk.ErrorResultException;
 
 import com.sun.opends.sdk.util.Validator;
 
@@ -41,11 +40,11 @@
  * Generic bind request implementation.
  */
 final class GenericBindRequestImpl extends
-    AbstractBindRequest<GenericBindRequest> implements
-    GenericBindRequest
+    AbstractBindRequest<GenericBindRequest> implements GenericBindRequest
 {
+  private final BindClient bindClient;
 
-  private DN name;
+  private String name;
 
   private ByteString authenticationValue;
 
@@ -54,28 +53,48 @@
 
 
   /**
-   * Creates a new generic bind request using the provided distinguished
-   * name, authentication type, and authentication information.
-   * 
-   * @param name
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as (may be empty).
-   * @param authenticationType
-   *          The authentication mechanism identifier for this generic
-   *          bind request.
-   * @param authenticationValue
-   *          The authentication information for this generic bind
-   *          request in a form defined by the authentication mechanism.
-   * @throws NullPointerException
-   *           If {@code name}, {@code authenticationType}, or {@code
-   *           authenticationValue} was {@code null}.
+   * Creates a new generic bind request using a generic bind client.
    */
-  GenericBindRequestImpl(DN name, byte authenticationType,
-      ByteString authenticationValue) throws NullPointerException
+  GenericBindRequestImpl(final String name, final byte authenticationType,
+      final ByteString authenticationValue)
   {
     this.name = name;
     this.authenticationType = authenticationType;
     this.authenticationValue = authenticationValue;
+    this.bindClient = null; // Create a new bind client each time.
+  }
+
+
+
+  /**
+   * Creates a new generic bind request using the provided bind client.
+   * <p>
+   * This is intended for use by other bind client implementations in this
+   * package.
+   */
+  GenericBindRequestImpl(final String name, final byte authenticationType,
+      final ByteString authenticationValue, final BindClient bindClient)
+  {
+    this.name = name;
+    this.authenticationType = authenticationType;
+    this.authenticationValue = authenticationValue;
+    this.bindClient = bindClient; // Always return same bind client.
+  }
+
+
+
+  public BindClient createBindClient(final String serverName)
+      throws ErrorResultException
+  {
+    if (bindClient == null)
+    {
+      return new BindClientImpl(this)
+          .setNextAuthenticationValue(authenticationValue);
+    }
+    else
+    {
+      return bindClient;
+    }
   }
 
 
@@ -103,7 +122,8 @@
   /**
    * {@inheritDoc}
    */
-  public DN getName()
+  @Override
+  public String getName()
   {
     return name;
   }
@@ -113,7 +133,7 @@
   /**
    * {@inheritDoc}
    */
-  public GenericBindRequest setAuthenticationType(byte type)
+  public GenericBindRequest setAuthenticationType(final byte type)
       throws UnsupportedOperationException
   {
     this.authenticationType = type;
@@ -125,7 +145,7 @@
   /**
    * {@inheritDoc}
    */
-  public GenericBindRequest setAuthenticationValue(ByteString bytes)
+  public GenericBindRequest setAuthenticationValue(final ByteString bytes)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(bytes);
@@ -138,25 +158,11 @@
   /**
    * {@inheritDoc}
    */
-  public GenericBindRequest setName(DN dn)
+  public GenericBindRequest setName(final String name)
       throws UnsupportedOperationException, NullPointerException
   {
-    Validator.ensureNotNull(dn);
-    this.name = dn;
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public GenericBindRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
-  {
-    Validator.ensureNotNull(dn);
-    this.name = DN.valueOf(dn);
+    Validator.ensureNotNull(name);
+    this.name = name;
     return this;
   }
 
diff --git a/sdk/src/org/opends/sdk/requests/GenericExtendedRequest.java b/sdk/src/org/opends/sdk/requests/GenericExtendedRequest.java
index e361b9c..46388d3 100644
--- a/sdk/src/org/opends/sdk/requests/GenericExtendedRequest.java
+++ b/sdk/src/org/opends/sdk/requests/GenericExtendedRequest.java
@@ -29,35 +29,40 @@
 
 
 
+import java.util.List;
+
 import org.opends.sdk.ByteString;
-import org.opends.sdk.ResultCode;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
-import org.opends.sdk.extensions.ExtendedOperation;
+import org.opends.sdk.controls.ControlDecoder;
+import org.opends.sdk.responses.ExtendedResultDecoder;
 import org.opends.sdk.responses.GenericExtendedResult;
 
 
 
 /**
- * A generic Extended request which should be used for unsupported
- * extended operations. Servers list the names of Extended requests they
- * recognize in the {@code supportedExtension} attribute in the root
- * DSE. Where the name is not recognized, the server returns
- * {@link ResultCode#PROTOCOL_ERROR} (the server may return this error
- * in other cases).
+ * A generic Extended request which should be used for unsupported extended
+ * operations. Servers list the names of Extended requests they recognize in the
+ * {@code supportedExtension} attribute in the root DSE. Where the name is not
+ * recognized, the server returns
+ * {@link org.opends.sdk.ResultCode#PROTOCOL_ERROR} (the server may return this
+ * error in other cases).
  */
 public interface GenericExtendedRequest extends
     ExtendedRequest<GenericExtendedResult>
 {
   /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * A decoder which can be used to decode generic extended operation requests.
+   */
+  public static final ExtendedRequestDecoder<GenericExtendedRequest,
+                                             GenericExtendedResult> DECODER =
+    new GenericExtendedRequestImpl.RequestDecoder();
+
+
+
+  /**
+   * {@inheritDoc}
    */
   GenericExtendedRequest addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -65,124 +70,78 @@
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * {@inheritDoc}
    */
-  GenericExtendedRequest clearControls()
-      throws UnsupportedOperationException;
-
-
-
-  /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control getControl(String oid) throws NullPointerException;
-
-
-
-  /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
-   */
-  Iterable<Control> getControls();
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  ExtendedOperation<GenericExtendedRequest, GenericExtendedResult> getExtendedOperation();
+  List<Control> getControls();
 
 
 
   /**
    * {@inheritDoc}
    */
-  String getRequestName();
+  String getOID();
 
 
 
   /**
    * {@inheritDoc}
    */
-  ByteString getRequestValue();
+  ExtendedResultDecoder<GenericExtendedResult> getResultDecoder();
 
 
 
   /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
+   * {@inheritDoc}
    */
-  boolean hasControls();
+  ByteString getValue();
 
 
 
   /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * {@inheritDoc}
    */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  boolean hasValue();
 
 
 
   /**
-   * Sets the dotted-decimal representation of the unique OID
-   * corresponding to this generic extended request.
-   * 
+   * Sets the numeric OID associated with this extended request.
+   *
    * @param oid
-   *          The dotted-decimal representation of the unique OID.
+   *          The numeric OID associated with this extended request.
    * @return This generic extended request.
    * @throws UnsupportedOperationException
-   *           If this generic extended request does not permit the
-   *           request name to be set.
+   *           If this generic extended request does not permit the request name
+   *           to be set.
    * @throws NullPointerException
    *           If {@code oid} was {@code null}.
    */
-  GenericExtendedRequest setRequestName(String oid)
+  GenericExtendedRequest setOID(String oid)
       throws UnsupportedOperationException, NullPointerException;
 
 
 
   /**
-   * Sets the content of this generic extended request in a form defined
-   * by the extended request.
-   * 
+   * Sets the value, if any, associated with this extended request. Its format
+   * is defined by the specification of this extended request.
+   *
    * @param bytes
-   *          The content of this generic extended request in a form
-   *          defined by the extended request, or {@code null} if there
-   *          is no content.
+   *          The value associated with this extended request, or {@code null}
+   *          if there is no value.
    * @return This generic extended request.
    * @throws UnsupportedOperationException
-   *           If this generic extended request does not permit the
-   *           request value to be set.
+   *           If this generic extended request does not permit the request
+   *           value to be set.
    */
-  GenericExtendedRequest setRequestValue(ByteString bytes)
+  GenericExtendedRequest setValue(ByteString bytes)
       throws UnsupportedOperationException;
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/GenericExtendedRequestImpl.java b/sdk/src/org/opends/sdk/requests/GenericExtendedRequestImpl.java
index f48fdc4..cb3321d 100644
--- a/sdk/src/org/opends/sdk/requests/GenericExtendedRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/GenericExtendedRequestImpl.java
@@ -31,11 +31,15 @@
 
 import org.opends.sdk.ByteString;
 import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.ResultCode;
-import org.opends.sdk.extensions.ExtendedOperation;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
 import org.opends.sdk.responses.GenericExtendedResult;
 import org.opends.sdk.responses.Responses;
 
+import com.sun.opends.sdk.util.StaticUtils;
 import com.sun.opends.sdk.util.Validator;
 
 
@@ -43,52 +47,81 @@
 /**
  * Generic extended request implementation.
  */
-final class GenericExtendedRequestImpl
-    extends
+final class GenericExtendedRequestImpl extends
     AbstractExtendedRequest<GenericExtendedRequest, GenericExtendedResult>
     implements GenericExtendedRequest
 {
-  /**
-   * Generic extended operation singleton.
-   */
-  private static final class Operation implements
-      ExtendedOperation<GenericExtendedRequest, GenericExtendedResult>
+
+  static final class RequestDecoder implements
+      ExtendedRequestDecoder<GenericExtendedRequest, GenericExtendedResult>
   {
-
-    public GenericExtendedRequest decodeRequest(String requestName,
-        ByteString requestValue) throws DecodeException
-    {
-      return Requests.newGenericExtendedRequest(requestName,
-          requestValue);
-    }
-
-
-
-    public GenericExtendedResult decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage)
-    {
-      return Responses.newGenericExtendedResult(resultCode)
-          .setMatchedDN(matchedDN).setDiagnosticMessage(
-              diagnosticMessage);
-    }
-
-
-
-    public GenericExtendedResult decodeResponse(ResultCode resultCode,
-        String matchedDN, String diagnosticMessage,
-        String responseName, ByteString responseValue)
+    public GenericExtendedRequest decodeExtendedRequest(
+        final ExtendedRequest<?> request, final DecodeOptions options)
         throws DecodeException
     {
-      return Responses.newGenericExtendedResult(resultCode)
-          .setMatchedDN(matchedDN).setDiagnosticMessage(
-              diagnosticMessage).setResponseName(responseName)
-          .setResponseValue(responseValue);
+      if (request instanceof GenericExtendedRequest)
+      {
+        return (GenericExtendedRequest) request;
+      }
+      else
+      {
+        final GenericExtendedRequest newRequest = new GenericExtendedRequestImpl(
+            request.getOID(), request.getValue());
+
+        for (final Control control : request.getControls())
+        {
+          newRequest.addControl(control);
+        }
+
+        return newRequest;
+      }
     }
   }
 
 
 
-  private static final Operation OPERATION = new Operation();
+  private static final class GenericExtendedResultDecoder implements
+      ExtendedResultDecoder<GenericExtendedResult>
+  {
+
+    public GenericExtendedResult adaptExtendedErrorResult(
+        final ResultCode resultCode, final String matchedDN,
+        final String diagnosticMessage)
+    {
+      return Responses.newGenericExtendedResult(resultCode).setMatchedDN(
+          matchedDN).setDiagnosticMessage(diagnosticMessage);
+    }
+
+
+
+    public GenericExtendedResult decodeExtendedResult(
+        final ExtendedResult result, final DecodeOptions options)
+        throws DecodeException
+    {
+      if (result instanceof GenericExtendedResult)
+      {
+        return (GenericExtendedResult) result;
+      }
+      else
+      {
+        final GenericExtendedResult newResult = Responses
+            .newGenericExtendedResult(result.getResultCode()).setMatchedDN(
+                result.getMatchedDN()).setDiagnosticMessage(
+                result.getDiagnosticMessage()).setOID(result.getOID())
+            .setValue(result.getValue());
+        for (final Control control : result.getControls())
+        {
+          newResult.addControl(control);
+        }
+        return newResult;
+      }
+    }
+  }
+
+
+
+  private static final GenericExtendedResultDecoder RESULT_DECODER =
+    new GenericExtendedResultDecoder();
 
   private ByteString requestValue = ByteString.empty();
 
@@ -97,21 +130,20 @@
 
 
   /**
-   * Creates a new generic extended request using the provided name and
-   * optional value.
-   * 
+   * Creates a new generic extended request using the provided name and optional
+   * value.
+   *
    * @param requestName
-   *          The dotted-decimal representation of the unique OID
-   *          corresponding to this extended request.
+   *          The dotted-decimal representation of the unique OID corresponding
+   *          to this extended request.
    * @param requestValue
-   *          The content of this generic extended request in a form
-   *          defined by the extended operation, or {@code null} if
-   *          there is no content.
+   *          The content of this generic extended request in a form defined by
+   *          the extended operation, or {@code null} if there is no content.
    * @throws NullPointerException
    *           If {@code requestName} was {@code null}.
    */
-  GenericExtendedRequestImpl(String requestName, ByteString requestValue)
-      throws NullPointerException
+  GenericExtendedRequestImpl(final String requestName,
+      final ByteString requestValue) throws NullPointerException
   {
     this.requestName = requestName;
     this.requestValue = requestValue;
@@ -122,17 +154,8 @@
   /**
    * {@inheritDoc}
    */
-  public ExtendedOperation<GenericExtendedRequest, GenericExtendedResult> getExtendedOperation()
-  {
-    return OPERATION;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public String getRequestName()
+  @Override
+  public String getOID()
   {
     return requestName;
   }
@@ -142,7 +165,19 @@
   /**
    * {@inheritDoc}
    */
-  public ByteString getRequestValue()
+  @Override
+  public ExtendedResultDecoder<GenericExtendedResult> getResultDecoder()
+  {
+    return RESULT_DECODER;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
   {
     return requestValue;
   }
@@ -152,7 +187,18 @@
   /**
    * {@inheritDoc}
    */
-  public GenericExtendedRequest setRequestName(String oid)
+  @Override
+  public boolean hasValue()
+  {
+    return requestValue != null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public GenericExtendedRequest setOID(final String oid)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(oid);
@@ -165,7 +211,7 @@
   /**
    * {@inheritDoc}
    */
-  public GenericExtendedRequest setRequestValue(ByteString bytes)
+  public GenericExtendedRequest setValue(final ByteString bytes)
       throws UnsupportedOperationException
   {
     this.requestValue = bytes;
@@ -182,9 +228,12 @@
   {
     final StringBuilder builder = new StringBuilder();
     builder.append("GenericExtendedRequest(requestName=");
-    builder.append(getRequestName());
-    builder.append(", requestValue=");
-    builder.append(getRequestValue());
+    builder.append(getOID());
+    if (hasValue())
+    {
+      builder.append(", requestValue=");
+      StaticUtils.toHexPlusAscii(getValue(), builder, 4);
+    }
     builder.append(", controls=");
     builder.append(getControls());
     builder.append(")");
diff --git a/sdk/src/org/opends/sdk/requests/ModifyDNRequest.java b/sdk/src/org/opends/sdk/requests/ModifyDNRequest.java
index 9cc3dc0..6b1a89b 100644
--- a/sdk/src/org/opends/sdk/requests/ModifyDNRequest.java
+++ b/sdk/src/org/opends/sdk/requests/ModifyDNRequest.java
@@ -29,20 +29,20 @@
 
 
 
-import org.opends.sdk.DN;
-import org.opends.sdk.LocalizedIllegalArgumentException;
-import org.opends.sdk.RDN;
+import java.util.List;
+
+import org.opends.sdk.*;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 import org.opends.sdk.ldif.ChangeRecord;
 import org.opends.sdk.ldif.ChangeRecordVisitor;
 
 
 
-
 /**
- * The Modify DN operation allows a client to change the Relative
- * Distinguished Name (RDN) of an entry in the Directory and/or to move
- * a subtree of entries to a new location in the Directory.
+ * The Modify DN operation allows a client to change the Relative Distinguished
+ * Name (RDN) of an entry in the Directory and/or to move a subtree of entries
+ * to a new location in the Directory.
  */
 public interface ModifyDNRequest extends Request, ChangeRecord
 {
@@ -54,15 +54,7 @@
 
 
   /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
   ModifyDNRequest addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -70,47 +62,25 @@
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * {@inheritDoc}
    */
-  ModifyDNRequest clearControls() throws UnsupportedOperationException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  List<Control> getControls();
 
 
 
   /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
-   */
-  Iterable<Control> getControls();
-
-
-
-  /**
-   * Returns the distinguished name of the entry to be renamed. This
-   * entry may or may not have subordinate entries. The server shall not
-   * dereference any aliases in locating the entry to be renamed.
-   * 
+   * Returns the distinguished name of the entry to be renamed. This entry may
+   * or may not have subordinate entries. The server shall not dereference any
+   * aliases in locating the entry to be renamed.
+   *
    * @return The distinguished name of the entry.
    */
   DN getName();
@@ -118,12 +88,12 @@
 
 
   /**
-   * Returns the new RDN of the entry to be renamed. The value of the
-   * old RDN is supplied when moving the entry to a new superior without
-   * changing its RDN. Attribute values of the new RDN not matching any
-   * attribute value of the entry are added to the entry, and an
-   * appropriate error is returned if this fails.
-   * 
+   * Returns the new RDN of the entry to be renamed. The value of the old RDN is
+   * supplied when moving the entry to a new superior without changing its RDN.
+   * Attribute values of the new RDN not matching any attribute value of the
+   * entry are added to the entry, and an appropriate error is returned if this
+   * fails.
+   *
    * @return The new RDN of the entry.
    */
   RDN getNewRDN();
@@ -131,71 +101,39 @@
 
 
   /**
-   * Returns the distinguished name of an existing entry that will
-   * become the immediate superior (parent) of the entry to be renamed.
-   * The server shall not dereference any aliases in locating the new
-   * superior entry.
-   * 
-   * @return The distinguished name of the new superior entry, or
-   *         {@code null} if the entry is to remain under the same
-   *         parent entry.
+   * Returns the distinguished name of an existing entry that will become the
+   * immediate superior (parent) of the entry to be renamed. The server shall
+   * not dereference any aliases in locating the new superior entry.
+   *
+   * @return The distinguished name of the new superior entry, or {@code null}
+   *         if the entry is to remain under the same parent entry.
    */
   DN getNewSuperior();
 
 
 
   /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Indicates whether the old RDN attribute values are to be retained
-   * as attributes of the entry or deleted from the entry.
-   * 
-   * @return {@code true} if the old RDN attribute values are to be
-   *         deleted from the entry, or {@code false} if they are to be
-   *         retained.
+   * Indicates whether the old RDN attribute values are to be retained as
+   * attributes of the entry or deleted from the entry.
+   *
+   * @return {@code true} if the old RDN attribute values are to be deleted from
+   *         the entry, or {@code false} if they are to be retained.
    */
   boolean isDeleteOldRDN();
 
 
 
   /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Specifies whether the old RDN attribute values are to be retained
-   * as attributes of the entry or deleted from the entry.
-   * 
+   * Specifies whether the old RDN attribute values are to be retained as
+   * attributes of the entry or deleted from the entry.
+   *
    * @param deleteOldRDN
-   *          {@code true} if the old RDN attribute values are to be
-   *          deleted from the entry, or {@code false} if they are to be
-   *          retained.
+   *          {@code true} if the old RDN attribute values are to be deleted
+   *          from the entry, or {@code false} if they are to be retained.
    * @return This modify DN request.
    * @throws UnsupportedOperationException
-   *           If this modify DN request does not permit the delete old
-   *           RDN parameter to be set.
+   *           If this modify DN request does not permit the delete old RDN
+   *           parameter to be set.
    */
   ModifyDNRequest setDeleteOldRDN(boolean deleteOldRDN)
       throws UnsupportedOperationException;
@@ -203,16 +141,16 @@
 
 
   /**
-   * Sets the distinguished name of the entry to be renamed. This entry
-   * may or may not have subordinate entries. The server shall not
-   * dereference any aliases in locating the entry to be renamed.
-   * 
+   * Sets the distinguished name of the entry to be renamed. This entry may or
+   * may not have subordinate entries. The server shall not dereference any
+   * aliases in locating the entry to be renamed.
+   *
    * @param dn
    *          The distinguished name of the entry to be renamed.
    * @return This modify DN request.
    * @throws UnsupportedOperationException
-   *           If this modify DN request does not permit the
-   *           distinguished name to be set.
+   *           If this modify DN request does not permit the distinguished name
+   *           to be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
@@ -222,114 +160,104 @@
 
 
   /**
-   * Sets the distinguished name of the entry to be renamed. This entry
-   * may or may not have subordinate entries. The server shall not
-   * dereference any aliases in locating the entry to be renamed.
-   * 
+   * Sets the distinguished name of the entry to be renamed. This entry may or
+   * may not have subordinate entries. The server shall not dereference any
+   * aliases in locating the entry to be renamed.
+   *
    * @param dn
    *          The distinguished name of the entry to be renamed.
    * @return This modify DN request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} could not be decoded using the default
-   *           schema.
+   *           If {@code dn} could not be decoded using the default schema.
    * @throws UnsupportedOperationException
-   *           If this modify DN request does not permit the
-   *           distinguished name to be set.
+   *           If this modify DN request does not permit the distinguished name
+   *           to be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  ModifyDNRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
+  ModifyDNRequest setName(String dn) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException;
 
 
 
   /**
-   * Sets the new RDN of the entry to be renamed. The value of the old
-   * RDN is supplied when moving the entry to a new superior without
-   * changing its RDN. Attribute values of the new RDN not matching any
-   * attribute value of the entry are added to the entry, and an
-   * appropriate error is returned if this fails.
-   * 
+   * Sets the new RDN of the entry to be renamed. The value of the old RDN is
+   * supplied when moving the entry to a new superior without changing its RDN.
+   * Attribute values of the new RDN not matching any attribute value of the
+   * entry are added to the entry, and an appropriate error is returned if this
+   * fails.
+   *
    * @param rdn
    *          The new RDN of the entry to be renamed.
    * @return This modify DN request.
    * @throws UnsupportedOperationException
-   *           If this modify DN request does not permit the new RDN to
-   *           be set.
+   *           If this modify DN request does not permit the new RDN to be set.
    * @throws NullPointerException
    *           If {@code rdn} was {@code null}.
    */
-  ModifyDNRequest setNewRDN(RDN rdn)
-      throws UnsupportedOperationException, NullPointerException;
+  ModifyDNRequest setNewRDN(RDN rdn) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Sets the new RDN of the entry to be renamed. The value of the old
-   * RDN is supplied when moving the entry to a new superior without
-   * changing its RDN. Attribute values of the new RDN not matching any
-   * attribute value of the entry are added to the entry, and an
-   * appropriate error is returned if this fails.
-   * 
+   * Sets the new RDN of the entry to be renamed. The value of the old RDN is
+   * supplied when moving the entry to a new superior without changing its RDN.
+   * Attribute values of the new RDN not matching any attribute value of the
+   * entry are added to the entry, and an appropriate error is returned if this
+   * fails.
+   *
    * @param rdn
    *          The new RDN of the entry to be renamed.
    * @return This modify DN request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code rdn} could not be decoded using the default
-   *           schema.
+   *           If {@code rdn} could not be decoded using the default schema.
    * @throws UnsupportedOperationException
-   *           If this modify DN request does not permit the new RDN to
-   *           be set.
+   *           If this modify DN request does not permit the new RDN to be set.
    * @throws NullPointerException
    *           If {@code rdn} was {@code null}.
    */
   ModifyDNRequest setNewRDN(String rdn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Sets the distinguished name of an existing entry that will become
-   * the immediate superior (parent) of the entry to be renamed. The
-   * server shall not dereference any aliases in locating the new
-   * superior entry.
-   * 
+   * Sets the distinguished name of an existing entry that will become the
+   * immediate superior (parent) of the entry to be renamed. The server shall
+   * not dereference any aliases in locating the new superior entry.
+   *
    * @param dn
-   *          The distinguished name of an existing entry that will
-   *          become the immediate superior (parent) of the entry to be
-   *          renamed, may be {@code null}.
+   *          The distinguished name of an existing entry that will become the
+   *          immediate superior (parent) of the entry to be renamed, may be
+   *          {@code null}.
    * @return This modify DN request.
    * @throws UnsupportedOperationException
-   *           If this modify DN request does not permit the new
-   *           superior to be set.
+   *           If this modify DN request does not permit the new superior to be
+   *           set.
    */
-  ModifyDNRequest setNewSuperior(DN dn)
-      throws UnsupportedOperationException;
+  ModifyDNRequest setNewSuperior(DN dn) throws UnsupportedOperationException;
 
 
 
   /**
-   * Sets the distinguished name of an existing entry that will become
-   * the immediate superior (parent) of the entry to be renamed. The
-   * server shall not dereference any aliases in locating the new
-   * superior entry.
-   * 
+   * Sets the distinguished name of an existing entry that will become the
+   * immediate superior (parent) of the entry to be renamed. The server shall
+   * not dereference any aliases in locating the new superior entry.
+   *
    * @param dn
-   *          The distinguished name of an existing entry that will
-   *          become the immediate superior (parent) of the entry to be
-   *          renamed, may be {@code null}.
+   *          The distinguished name of an existing entry that will become the
+   *          immediate superior (parent) of the entry to be renamed, may be
+   *          {@code null}.
    * @return This modify DN request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} could not be decoded using the default
-   *           schema.
+   *           If {@code dn} could not be decoded using the default schema.
    * @throws UnsupportedOperationException
-   *           If this modify DN request does not permit the new
-   *           superior to be set.
+   *           If this modify DN request does not permit the new superior to be
+   *           set.
    */
   ModifyDNRequest setNewSuperior(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException;
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException;
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/ModifyDNRequestImpl.java b/sdk/src/org/opends/sdk/requests/ModifyDNRequestImpl.java
index 92d42a6..4d6ed55 100644
--- a/sdk/src/org/opends/sdk/requests/ModifyDNRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/ModifyDNRequestImpl.java
@@ -41,8 +41,8 @@
 /**
  * Modify DN request implementation.
  */
-final class ModifyDNRequestImpl extends
-    AbstractRequestImpl<ModifyDNRequest> implements ModifyDNRequest
+final class ModifyDNRequestImpl extends AbstractRequestImpl<ModifyDNRequest>
+    implements ModifyDNRequest
 {
   private DN name;
 
@@ -55,8 +55,8 @@
 
 
   /**
-   * Creates a new modify DN request using the provided distinguished
-   * name and new RDN.
+   * Creates a new modify DN request using the provided distinguished name and
+   * new RDN.
    *
    * @param name
    *          The distinguished name of the entry to be renamed.
@@ -65,7 +65,8 @@
    * @throws NullPointerException
    *           If {@code name} or {@code newRDN} was {@code null}.
    */
-  ModifyDNRequestImpl(DN name, RDN newRDN) throws NullPointerException
+  ModifyDNRequestImpl(final DN name, final RDN newRDN)
+      throws NullPointerException
   {
     this.name = name;
     this.newRDN = newRDN;
@@ -76,7 +77,7 @@
   /**
    * {@inheritDoc}
    */
-  public <R, P> R accept(ChangeRecordVisitor<R, P> v, P p)
+  public <R, P> R accept(final ChangeRecordVisitor<R, P> v, final P p)
   {
     return v.visitChangeRecord(p, this);
   }
@@ -126,7 +127,7 @@
   /**
    * {@inheritDoc}
    */
-  public ModifyDNRequestImpl setDeleteOldRDN(boolean deleteOldRDN)
+  public ModifyDNRequestImpl setDeleteOldRDN(final boolean deleteOldRDN)
       throws UnsupportedOperationException
   {
     this.deleteOldRDN = deleteOldRDN;
@@ -138,7 +139,7 @@
   /**
    * {@inheritDoc}
    */
-  public ModifyDNRequest setName(DN dn)
+  public ModifyDNRequest setName(final DN dn)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(dn);
@@ -151,9 +152,9 @@
   /**
    * {@inheritDoc}
    */
-  public ModifyDNRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
+  public ModifyDNRequest setName(final String dn)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
   {
     Validator.ensureNotNull(dn);
     this.name = DN.valueOf(dn);
@@ -165,7 +166,7 @@
   /**
    * {@inheritDoc}
    */
-  public ModifyDNRequest setNewRDN(RDN rdn)
+  public ModifyDNRequest setNewRDN(final RDN rdn)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(rdn);
@@ -178,9 +179,9 @@
   /**
    * {@inheritDoc}
    */
-  public ModifyDNRequest setNewRDN(String rdn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
+  public ModifyDNRequest setNewRDN(final String rdn)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
   {
     Validator.ensureNotNull(rdn);
     this.newRDN = RDN.valueOf(rdn);
@@ -192,7 +193,7 @@
   /**
    * {@inheritDoc}
    */
-  public ModifyDNRequest setNewSuperior(DN dn)
+  public ModifyDNRequest setNewSuperior(final DN dn)
       throws UnsupportedOperationException
   {
     this.newSuperior = dn;
@@ -204,9 +205,8 @@
   /**
    * {@inheritDoc}
    */
-  public ModifyDNRequest setNewSuperior(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException
+  public ModifyDNRequest setNewSuperior(final String dn)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException
   {
     this.newSuperior = (dn != null) ? DN.valueOf(dn) : null;
     return this;
@@ -237,6 +237,7 @@
 
 
 
+  @Override
   ModifyDNRequest getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/requests/ModifyRequest.java b/sdk/src/org/opends/sdk/requests/ModifyRequest.java
index 8c7fd04..e5e719d 100644
--- a/sdk/src/org/opends/sdk/requests/ModifyRequest.java
+++ b/sdk/src/org/opends/sdk/requests/ModifyRequest.java
@@ -29,17 +29,19 @@
 
 
 
+import java.util.List;
+
 import org.opends.sdk.*;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 import org.opends.sdk.ldif.ChangeRecord;
 import org.opends.sdk.ldif.ChangeRecordVisitor;
 
 
 
-
 /**
- * The Modify operation allows a client to request that a modification
- * of an entry be performed on its behalf by a server.
+ * The Modify operation allows a client to request that a modification of an
+ * entry be performed on its behalf by a server.
  */
 public interface ModifyRequest extends Request, ChangeRecord
 {
@@ -51,65 +53,7 @@
 
 
   /**
-   * Appends the provided change to the list of changes included with
-   * this modify request.
-   * 
-   * @param change
-   *          The change to be performed.
-   * @return This modify request.
-   * @throws UnsupportedOperationException
-   *           If this modify request does not permit changes to be
-   *           added.
-   * @throws NullPointerException
-   *           If {@code change} was {@code null}.
-   */
-  ModifyRequest addChange(Change change)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Appends the provided change to the list of changes included with
-   * this modify request.
-   * <p>
-   * If the attribute value is not an instance of {@code ByteString}
-   * then it will be converted using the
-   * {@link ByteString#valueOf(Object)} method.
-   * 
-   * @param type
-   *          The type of change to be performed.
-   * @param attributeDescription
-   *          The name of the attribute to be modified.
-   * @param values
-   *          The attribute values to be modified.
-   * @return This modify request.
-   * @throws LocalizedIllegalArgumentException
-   *           If {@code attributeDescription} could not be decoded
-   *           using the default schema.
-   * @throws UnsupportedOperationException
-   *           If this modify request does not permit changes to be
-   *           added.
-   * @throws NullPointerException
-   *           If {@code type}, {@code attributeDescription}, or {@code
-   *           value} was {@code null}.
-   */
-  ModifyRequest addChange(ModificationType type,
-      String attributeDescription, Object... values)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
   ModifyRequest addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -117,79 +61,83 @@
 
 
   /**
-   * Removes all the changes included with this modify request.
-   * 
+   * Appends the provided modification to the list of modifications included
+   * with this modify request.
+   *
+   * @param modification
+   *          The modification to be performed.
    * @return This modify request.
    * @throws UnsupportedOperationException
-   *           If this modify request does not permit changes to be
-   *           removed.
-   */
-  ModifyRequest clearChanges() throws UnsupportedOperationException;
-
-
-
-  /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   */
-  ModifyRequest clearControls() throws UnsupportedOperationException;
-
-
-
-  /**
-   * Returns the number of changes included with this modify request.
-   * 
-   * @return The number of changes.
-   */
-  int getChangeCount();
-
-
-
-  /**
-   * Returns an {@code Iterable} containing the changes included with
-   * this modify request. The returned {@code Iterable} may be used to
-   * remove changes if permitted by this modify request.
-   * 
-   * @return An {@code Iterable} containing the changes.
-   */
-  Iterable<Change> getChanges();
-
-
-
-  /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
+   *           If this modify request does not permit modifications to be added.
    * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   *           If {@code modification} was {@code null}.
    */
-  Control getControl(String oid) throws NullPointerException;
+  ModifyRequest addModification(Modification modification)
+      throws UnsupportedOperationException, NullPointerException;
 
 
 
   /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
+   * Appends the provided modification to the list of modifications included
+   * with this modify request.
+   * <p>
+   * If the attribute value is not an instance of {@code ByteString} then it
+   * will be converted using the {@link ByteString#valueOf(Object)} method.
+   *
+   * @param type
+   *          The type of modification to be performed.
+   * @param attributeDescription
+   *          The name of the attribute to be modified.
+   * @param values
+   *          The attribute values to be modified.
+   * @return This modify request.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code attributeDescription} could not be decoded using the
+   *           default schema.
+   * @throws UnsupportedOperationException
+   *           If this modify request does not permit modifications to be added.
+   * @throws NullPointerException
+   *           If {@code type}, {@code attributeDescription}, or {@code value}
+   *           was {@code null}.
    */
-  Iterable<Control> getControls();
+  ModifyRequest addModification(ModificationType type,
+      String attributeDescription, Object... values)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Returns the distinguished name of the entry to be modified. The
-   * server shall not perform any alias dereferencing in determining the
-   * object to be modified.
-   * 
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * Returns a {@code List} containing the modifications included with this
+   * modify request. The returned {@code List} may be modified if permitted by
+   * this modify request.
+   *
+   * @return A {@code List} containing the modifications.
+   */
+  List<Modification> getModifications();
+
+
+
+  /**
+   * Returns the distinguished name of the entry to be modified. The server
+   * shall not perform any alias dereferencing in determining the object to be
+   * modified.
+   *
    * @return The distinguished name of the entry to be modified.
    */
   DN getName();
@@ -197,54 +145,16 @@
 
 
   /**
-   * Indicates whether or not this modify request has any changes.
-   * 
-   * @return {@code true} if this modify request has any changes,
-   *         otherwise {@code false}.
-   */
-  boolean hasChanges();
-
-
-
-  /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Sets the distinguished name of the entry to be modified. The server
-   * shall not perform any alias dereferencing in determining the object
-   * to be modified.
-   * 
+   * Sets the distinguished name of the entry to be modified. The server shall
+   * not perform any alias dereferencing in determining the object to be
+   * modified.
+   *
    * @param dn
    *          The the distinguished name of the entry to be modified.
    * @return This modify request.
    * @throws UnsupportedOperationException
-   *           If this modify request does not permit the distinguished
-   *           name to be set.
+   *           If this modify request does not permit the distinguished name to
+   *           be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
@@ -254,24 +164,22 @@
 
 
   /**
-   * Sets the distinguished name of the entry to be modified. The server
-   * shall not perform any alias dereferencing in determining the object
-   * to be modified.
-   * 
+   * Sets the distinguished name of the entry to be modified. The server shall
+   * not perform any alias dereferencing in determining the object to be
+   * modified.
+   *
    * @param dn
    *          The the distinguished name of the entry to be modified.
    * @return This modify request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} could not be decoded using the default
-   *           schema.
+   *           If {@code dn} could not be decoded using the default schema.
    * @throws UnsupportedOperationException
-   *           If this modify request does not permit the distinguished
-   *           name to be set.
+   *           If this modify request does not permit the distinguished name to
+   *           be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  ModifyRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
+  ModifyRequest setName(String dn) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException;
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/ModifyRequestImpl.java b/sdk/src/org/opends/sdk/requests/ModifyRequestImpl.java
index 0c9d68a..d7fe851 100644
--- a/sdk/src/org/opends/sdk/requests/ModifyRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/ModifyRequestImpl.java
@@ -42,10 +42,10 @@
 /**
  * Modify request implementation.
  */
-final class ModifyRequestImpl extends
-    AbstractRequestImpl<ModifyRequest> implements ModifyRequest
+final class ModifyRequestImpl extends AbstractRequestImpl<ModifyRequest>
+    implements ModifyRequest
 {
-  private final List<Change> changes = new LinkedList<Change>();
+  private final List<Modification> changes = new LinkedList<Modification>();
 
   private DN name;
 
@@ -59,7 +59,7 @@
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  ModifyRequestImpl(DN name) throws NullPointerException
+  ModifyRequestImpl(final DN name) throws NullPointerException
   {
     this.name = name;
   }
@@ -69,17 +69,29 @@
   /**
    * {@inheritDoc}
    */
-  public <R, P> R accept(ChangeRecordVisitor<R, P> v, P p)
+  public <R, P> R accept(final ChangeRecordVisitor<R, P> v, final P p)
   {
     return v.visitChangeRecord(p, this);
   }
 
 
 
+  public ModifyRequest addChange(final ModificationType type,
+      final String attributeDescription, final Object firstValue,
+      final Object... remainingValues)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
+  {
+    // TODO Auto-generated method stub
+    return null;
+  }
+
+
+
   /**
    * {@inheritDoc}
    */
-  public ModifyRequest addChange(Change change)
+  public ModifyRequest addModification(final Modification change)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(change);
@@ -92,57 +104,23 @@
   /**
    * {@inheritDoc}
    */
-  public ModifyRequest addChange(ModificationType type,
-      String attributeDescription, Object... values)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
+  public ModifyRequest addModification(final ModificationType type,
+      final String attributeDescription, final Object... values)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
   {
     Validator.ensureNotNull(type, attributeDescription, values);
-    changes.add(new Change(type, new LinkedAttribute(
+    changes.add(new Modification(type, new LinkedAttribute(
         attributeDescription, values)));
     return this;
   }
 
 
 
-  public ModifyRequest addChange(ModificationType type,
-      String attributeDescription, Object firstValue,
-      Object... remainingValues)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
-  {
-    // TODO Auto-generated method stub
-    return null;
-  }
-
-
-
   /**
    * {@inheritDoc}
    */
-  public ModifyRequest clearChanges()
-      throws UnsupportedOperationException
-  {
-    changes.clear();
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public int getChangeCount()
-  {
-    return changes.size();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Iterable<Change> getChanges()
+  public List<Modification> getModifications()
   {
     return changes;
   }
@@ -162,17 +140,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean hasChanges()
-  {
-    return !changes.isEmpty();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public ModifyRequest setName(DN dn)
+  public ModifyRequest setName(final DN dn)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(dn);
@@ -185,9 +153,9 @@
   /**
    * {@inheritDoc}
    */
-  public ModifyRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
+  public ModifyRequest setName(final String dn)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
   {
     Validator.ensureNotNull(dn);
     this.name = DN.valueOf(dn);
@@ -206,7 +174,7 @@
     builder.append("ModifyRequest(dn=");
     builder.append(getName());
     builder.append(", changes=");
-    builder.append(getChanges());
+    builder.append(getModifications());
     builder.append(", controls=");
     builder.append(getControls());
     builder.append(")");
@@ -215,6 +183,7 @@
 
 
 
+  @Override
   ModifyRequest getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequest.java b/sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequest.java
new file mode 100644
index 0000000..5812d0a
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequest.java
@@ -0,0 +1,274 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+import org.opends.sdk.responses.PasswordModifyExtendedResult;
+
+
+
+/**
+ * The password modify extended request as defined in RFC 3062. This operation
+ * allows directory clients to update user passwords. The user may or may not be
+ * associated with a directory entry. The user may or may not be represented as
+ * an LDAP DN. The user's password may or may not be stored in the directory. In
+ * addition, it includes support for requiring the user's current password as
+ * well as for generating a new password if none was provided.
+ *
+ * @see PasswordModifyExtendedResult
+ * @see <a href="http://tools.ietf.org/html/rfc3909">RFC 3062 - LDAP Password
+ *      Modify Extended Operation </a>
+ */
+public interface PasswordModifyExtendedRequest extends
+    ExtendedRequest<PasswordModifyExtendedResult>
+{
+
+  /**
+   * The OID for the password modify extended operation request.
+   */
+  public static final String OID = "1.3.6.1.4.1.4203.1.11.1";
+
+  /**
+   * A decoder which can be used to decode password modify extended operation
+   * requests.
+   */
+  public static final ExtendedRequestDecoder<PasswordModifyExtendedRequest,
+                                             PasswordModifyExtendedResult>
+    DECODER = new PasswordModifyExtendedRequestImpl.RequestDecoder();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  PasswordModifyExtendedRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * Returns the desired password for the user, or {@code null} if a new
+   * password should be generated.
+   *
+   * @return The desired password for the user, or {@code null} if a new
+   *         password should be generated.
+   */
+  ByteString getNewPassword();
+
+
+
+  /**
+   * Returns the desired password for the user decoded as a UTF-8 string, or
+   * {@code null} if a new password should be generated.
+   *
+   * @return The desired password for the user decoded as a UTF-8 string, or
+   *         {@code null} if a new password should be generated.
+   */
+  String getNewPasswordAsString();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getOID();
+
+
+
+  /**
+   * Returns the current password for the user, if known.
+   *
+   * @return The current password for the user, or {@code null} if the password
+   *         is not known.
+   */
+  ByteString getOldPassword();
+
+
+
+  /**
+   * Returns the current password for the user, if known, decoded as a UTF-8
+   * string.
+   *
+   * @return The current password for the user decoded as a UTF-8 string, or
+   *         {@code null} if the password is not known.
+   */
+  String getOldPasswordAsString();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ExtendedResultDecoder<PasswordModifyExtendedResult> getResultDecoder();
+
+
+
+  /**
+   * Returns the identity of the user whose password is to be modified, or
+   * {@code null} if the request should be applied to the user currently
+   * associated with the session. The returned identity may or may not be a
+   * distinguished name.
+   *
+   * @return The identity of the user whose password is to be modified, or
+   *         {@code null} if the request should be applied to the user currently
+   *         associated with the session.
+   */
+  ByteString getUserIdentity();
+
+
+
+  /**
+   * Returns the identity of the user whose password is to be modified decoded
+   * as a UTF-8 string, or {@code null} if the request should be applied to the
+   * user currently associated with the session. The returned identity may or
+   * may not be a distinguished name.
+   *
+   * @return The identity of the user whose password is to be modified decoded
+   *         as a UTF-8 string, or {@code null} if the request should be applied
+   *         to the user currently associated with the session.
+   */
+  String getUserIdentityAsString();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ByteString getValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  boolean hasValue();
+
+
+
+  /**
+   * Sets the desired password for the user.
+   *
+   * @param newPassword
+   *          The desired password for the user, or {@code null} if a new
+   *          password should be generated.
+   * @return This password modify request.
+   */
+  PasswordModifyExtendedRequest setNewPassword(ByteString newPassword);
+
+
+
+  /**
+   * Sets the desired password for the user. The password will be converted to a
+   * UTF-8 octet string.
+   *
+   * @param newPassword
+   *          The desired password for the user, or {@code null} if a new
+   *          password should be generated.
+   * @return This password modify request.
+   */
+  PasswordModifyExtendedRequest setNewPassword(String newPassword);
+
+
+
+  /**
+   * Sets the current password for the user.
+   *
+   * @param oldPassword
+   *          The current password for the user, or {@code null} if the password
+   *          is not known.
+   * @return This password modify request.
+   */
+  PasswordModifyExtendedRequest setOldPassword(ByteString oldPassword);
+
+
+
+  /**
+   * Sets the current password for the user. The password will be converted to a
+   * UTF-8 octet string.
+   *
+   * @param oldPassword
+   *          The current password for the user, or {@code null} if the password
+   *          is not known.
+   * @return This password modify request.
+   */
+  PasswordModifyExtendedRequest setOldPassword(String oldPassword);
+
+
+
+  /**
+   * Sets the identity of the user whose password is to be modified. The
+   * identity may or may not be a distinguished name.
+   *
+   * @param userIdentity
+   *          The identity of the user whose password is to be modified, or
+   *          {@code null} if the request should be applied to the user
+   *          currently associated with the session.
+   * @return This password modify request.
+   */
+  PasswordModifyExtendedRequest setUserIdentity(ByteString userIdentity);
+
+
+
+  /**
+   * Sets the identity of the user whose password is to be modified. The
+   * identity may or may not be a distinguished name. The identity will be
+   * converted to a UTF-8 octet string.
+   *
+   * @param userIdentity
+   *          The identity of the user whose password is to be modified, or
+   *          {@code null} if the request should be applied to the user
+   *          currently associated with the session.
+   * @return This password modify request.
+   */
+  PasswordModifyExtendedRequest setUserIdentity(String userIdentity);
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequestImpl.java b/sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequestImpl.java
new file mode 100644
index 0000000..a32a7b6
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequestImpl.java
@@ -0,0 +1,437 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST;
+import static com.sun.opends.sdk.util.StaticUtils.getExceptionMessage;
+
+import java.io.IOException;
+
+import org.opends.sdk.*;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+import org.opends.sdk.responses.PasswordModifyExtendedResult;
+import org.opends.sdk.responses.Responses;
+
+
+
+/**
+ * Password modify extended request implementation.
+ */
+final class PasswordModifyExtendedRequestImpl
+    extends
+    AbstractExtendedRequest<PasswordModifyExtendedRequest, PasswordModifyExtendedResult>
+    implements PasswordModifyExtendedRequest
+{
+  static final class RequestDecoder
+      implements
+      ExtendedRequestDecoder<PasswordModifyExtendedRequest, PasswordModifyExtendedResult>
+  {
+    public PasswordModifyExtendedRequest decodeExtendedRequest(
+        final ExtendedRequest<?> request, final DecodeOptions options)
+        throws DecodeException
+    {
+      final PasswordModifyExtendedRequest newRequest = new PasswordModifyExtendedRequestImpl();
+      if (request.getValue() != null)
+      {
+        try
+        {
+          final ASN1Reader reader = ASN1.getReader(request.getValue());
+          reader.readStartSequence();
+          if (reader.hasNextElement()
+              && (reader.peekType() == TYPE_PASSWORD_MODIFY_USER_ID))
+          {
+            newRequest.setUserIdentity(reader.readOctetStringAsString());
+          }
+          if (reader.hasNextElement()
+              && (reader.peekType() == TYPE_PASSWORD_MODIFY_OLD_PASSWORD))
+          {
+            newRequest.setOldPassword(reader.readOctetString());
+          }
+          if (reader.hasNextElement()
+              && (reader.peekType() == TYPE_PASSWORD_MODIFY_NEW_PASSWORD))
+          {
+            newRequest.setNewPassword(reader.readOctetString());
+          }
+          reader.readEndSequence();
+        }
+        catch (final IOException e)
+        {
+          final LocalizableMessage message = ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST
+              .get(getExceptionMessage(e));
+          throw DecodeException.error(message, e);
+        }
+      }
+
+      for (final Control control : request.getControls())
+      {
+        newRequest.addControl(control);
+      }
+
+      return newRequest;
+    }
+  }
+
+
+
+  private static final class ResultDecoder implements
+      ExtendedResultDecoder<PasswordModifyExtendedResult>
+  {
+    public PasswordModifyExtendedResult adaptExtendedErrorResult(
+        final ResultCode resultCode, final String matchedDN,
+        final String diagnosticMessage)
+    {
+      return Responses.newPasswordModifyExtendedResult(resultCode)
+          .setMatchedDN(matchedDN).setDiagnosticMessage(diagnosticMessage);
+    }
+
+
+
+    public PasswordModifyExtendedResult decodeExtendedResult(
+        final ExtendedResult result, final DecodeOptions options)
+        throws DecodeException
+    {
+      if (result instanceof PasswordModifyExtendedResult)
+      {
+        return (PasswordModifyExtendedResult) result;
+      }
+      else
+      {
+        final ResultCode resultCode = result.getResultCode();
+
+        final PasswordModifyExtendedResult newResult = Responses
+            .newPasswordModifyExtendedResult(resultCode).setMatchedDN(
+                result.getMatchedDN()).setDiagnosticMessage(
+                result.getDiagnosticMessage());
+
+        // TODO: Should we check to make sure OID is null?
+        final ByteString responseValue = result.getValue();
+        if (resultCode == ResultCode.SUCCESS && responseValue != null)
+        {
+          try
+          {
+            final ASN1Reader asn1Reader = ASN1.getReader(responseValue);
+            asn1Reader.readStartSequence();
+            if (asn1Reader.peekType() == TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD)
+            {
+              newResult.setGeneratedPassword(asn1Reader.readOctetString());
+            }
+            asn1Reader.readEndSequence();
+          }
+          catch (final IOException e)
+          {
+            final LocalizableMessage message = ERR_EXTOP_PASSMOD_CANNOT_DECODE_REQUEST
+                .get(getExceptionMessage(e));
+            throw DecodeException.error(message, e);
+          }
+        }
+
+        for (final Control control : result.getControls())
+        {
+          newResult.addControl(control);
+        }
+
+        return newResult;
+      }
+    }
+  }
+
+
+
+  /**
+   * The ASN.1 element type that will be used to encode the userIdentity
+   * component in a password modify extended request.
+   */
+  private static final byte TYPE_PASSWORD_MODIFY_USER_ID = (byte) 0x80;
+
+  /**
+   * The ASN.1 element type that will be used to encode the oldPasswd component
+   * in a password modify extended request.
+   */
+  private static final byte TYPE_PASSWORD_MODIFY_OLD_PASSWORD = (byte) 0x81;
+
+  /**
+   * The ASN.1 element type that will be used to encode the newPasswd component
+   * in a password modify extended request.
+   */
+  private static final byte TYPE_PASSWORD_MODIFY_NEW_PASSWORD = (byte) 0x82;
+
+  /**
+   * The ASN.1 element type that will be used to encode the genPasswd component
+   * in a password modify extended response.
+   */
+  private static final byte TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD = (byte) 0x80;
+
+  private ByteString userIdentity = null;
+
+  private ByteString oldPassword = null;
+
+  private ByteString newPassword = null;
+
+  private static final ExtendedResultDecoder<PasswordModifyExtendedResult>
+    RESULT_DECODER = new ResultDecoder();
+
+
+
+  // Instantiation via factory.
+  PasswordModifyExtendedRequestImpl()
+  {
+
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getNewPassword()
+  {
+    return newPassword;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getNewPasswordAsString()
+  {
+    return newPassword != null ? newPassword.toString() : null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getOldPassword()
+  {
+    return oldPassword;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getOldPasswordAsString()
+  {
+    return oldPassword != null ? oldPassword.toString() : null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ExtendedResultDecoder<PasswordModifyExtendedResult> getResultDecoder()
+  {
+    return RESULT_DECODER;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getUserIdentity()
+  {
+    return userIdentity;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getUserIdentityAsString()
+  {
+    return userIdentity != null ? userIdentity.toString() : null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    final ByteStringBuilder buffer = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(buffer);
+
+    try
+    {
+      writer.writeStartSequence();
+      if (userIdentity != null)
+      {
+        writer.writeOctetString(TYPE_PASSWORD_MODIFY_USER_ID, userIdentity);
+      }
+      if (oldPassword != null)
+      {
+        writer.writeOctetString(TYPE_PASSWORD_MODIFY_OLD_PASSWORD, oldPassword);
+      }
+      if (newPassword != null)
+      {
+        writer.writeOctetString(TYPE_PASSWORD_MODIFY_NEW_PASSWORD, newPassword);
+      }
+      writer.writeEndSequence();
+    }
+    catch (final IOException ioe)
+    {
+      // This should never happen unless there is a bug somewhere.
+      throw new RuntimeException(ioe);
+    }
+
+    return buffer.toByteString();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return true;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PasswordModifyExtendedRequest setNewPassword(
+      final ByteString newPassword)
+  {
+    this.newPassword = newPassword;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PasswordModifyExtendedRequest setNewPassword(final String newPassword)
+  {
+    this.newPassword = (newPassword != null) ? ByteString.valueOf(newPassword)
+        : null;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PasswordModifyExtendedRequest setOldPassword(
+      final ByteString oldPassword)
+  {
+    this.oldPassword = oldPassword;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PasswordModifyExtendedRequest setOldPassword(final String oldPassword)
+  {
+    this.oldPassword = (oldPassword != null) ? ByteString.valueOf(oldPassword)
+        : null;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PasswordModifyExtendedRequest setUserIdentity(
+      final ByteString userIdentity)
+  {
+    this.userIdentity = userIdentity;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PasswordModifyExtendedRequest setUserIdentity(final String userIdentity)
+  {
+    this.userIdentity = (userIdentity != null) ? ByteString
+        .valueOf(userIdentity) : null;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PasswordModifyExtendedRequest(requestName=");
+    builder.append(getOID());
+    builder.append(", userIdentity=");
+    builder.append(userIdentity);
+    builder.append(", oldPassword=");
+    builder.append(oldPassword);
+    builder.append(", newPassword=");
+    builder.append(newPassword);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/requests/PlainSASLBindRequest.java b/sdk/src/org/opends/sdk/requests/PlainSASLBindRequest.java
new file mode 100644
index 0000000..67aa6f8
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/PlainSASLBindRequest.java
@@ -0,0 +1,222 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.*;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+
+
+/**
+ * The Plain SASL bind request as defined in RFC 4616. This SASL mechanism
+ * allows a client to authenticate to the server with an authentication ID and
+ * password. This mechanism does not provide a security layer.
+ * <p>
+ * The authentication and optional authorization identity is specified using an
+ * authorization ID, or {@code authzId}, as defined in RFC 4513 section 5.2.1.8.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4616">RFC 4616 - The PLAIN Simple
+ *      Authentication and Security Layer (SASL) Mechanism </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513 -
+ *      SASL Authorization Identities (authzId) </a>
+ */
+public interface PlainSASLBindRequest extends SASLBindRequest
+{
+
+  /**
+   * The name of the SASL mechanism based on PLAIN authentication.
+   */
+  public static final String SASL_MECHANISM_NAME = "PLAIN";
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  PlainSASLBindRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  BindClient createBindClient(String serverName) throws ErrorResultException;
+
+
+
+  /**
+   * Returns the authentication ID of the user. The authentication ID usually
+   * has the form "dn:" immediately followed by the distinguished name of the
+   * user, or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @return The authentication ID of the user.
+   */
+  String getAuthenticationID();
+
+
+
+  /**
+   * Returns the authentication mechanism identifier for this SASL bind request
+   * as defined by the LDAP protocol, which is always {@code 0xA3}.
+   *
+   * @return The authentication mechanism identifier.
+   */
+  byte getAuthenticationType();
+
+
+
+  /**
+   * Returns the optional authorization ID of the user which represents an
+   * alternate authorization identity which should be used for subsequent
+   * operations performed on the connection. The authorization ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @return The authorization ID of the user, which may be {@code null}.
+   */
+  String getAuthorizationID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * Returns the name of the Directory object that the client wishes to bind as,
+   * which is always the empty string for SASL authentication.
+   *
+   * @return The name of the Directory object that the client wishes to bind as.
+   */
+  String getName();
+
+
+
+  /**
+   * Returns the password of the user that the client wishes to bind as.
+   *
+   * @return The password of the user that the client wishes to bind as.
+   */
+  ByteString getPassword();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getSASLMechanism();
+
+
+
+  /**
+   * Sets the authentication ID of the user. The authentication ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @param authenticationID
+   *          The authentication ID of the user.
+   * @return This bind request.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authenticationID} was non-empty and did not contain a
+   *           valid authorization ID type.
+   * @throws NullPointerException
+   *           If {@code authenticationID} was {@code null}.
+   */
+  PlainSASLBindRequest setAuthenticationID(String authenticationID)
+      throws LocalizedIllegalArgumentException, NullPointerException;
+
+
+
+  /**
+   * Sets the optional authorization ID of the user which represents an
+   * alternate authorization identity which should be used for subsequent
+   * operations performed on the connection. The authorization ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @param authorizationID
+   *          The authorization ID of the user, which may be {@code null}.
+   * @return This bind request.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authorizationID} was non-empty and did not contain a
+   *           valid authorization ID type.
+   */
+  PlainSASLBindRequest setAuthorizationID(String authorizationID)
+      throws LocalizedIllegalArgumentException;
+
+
+
+  /**
+   * Sets the password of the user that the client wishes to bind as.
+   *
+   * @param password
+   *          The password of the user that the client wishes to bind as, which
+   *          may be empty.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the password to be set.
+   * @throws NullPointerException
+   *           If {@code password} was {@code null}.
+   */
+  PlainSASLBindRequest setPassword(ByteString password)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * Sets the password of the user that the client wishes to bind as. The
+   * password will be converted to a UTF-8 octet string.
+   *
+   * @param password
+   *          The password of the user that the client wishes to bind as.
+   * @return This bind request.
+   * @throws UnsupportedOperationException
+   *           If this bind request does not permit the password to be set.
+   * @throws NullPointerException
+   *           If {@code password} was {@code null}.
+   */
+  PlainSASLBindRequest setPassword(String password)
+      throws UnsupportedOperationException, NullPointerException;
+}
diff --git a/sdk/src/org/opends/sdk/requests/PlainSASLBindRequestImpl.java b/sdk/src/org/opends/sdk/requests/PlainSASLBindRequestImpl.java
new file mode 100644
index 0000000..0be59bb
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/PlainSASLBindRequestImpl.java
@@ -0,0 +1,254 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslClient;
+import javax.security.sasl.SaslException;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.ErrorResultException;
+import org.opends.sdk.ResultCode;
+import org.opends.sdk.responses.BindResult;
+import org.opends.sdk.responses.Responses;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * Plain SASL bind request implementation.
+ */
+final class PlainSASLBindRequestImpl extends
+    AbstractSASLBindRequest<PlainSASLBindRequest> implements
+    PlainSASLBindRequest
+{
+  private final static class Client extends SASLBindClientImpl
+  {
+    private final SaslClient saslClient;
+    private final String authenticationID;
+    private final ByteString password;
+
+
+
+    private Client(final PlainSASLBindRequestImpl initialBindRequest,
+        final String serverName) throws ErrorResultException
+    {
+      super(initialBindRequest);
+
+      this.authenticationID = initialBindRequest.getAuthenticationID();
+      this.password = initialBindRequest.getPassword();
+
+      try
+      {
+        saslClient = Sasl.createSaslClient(
+            new String[] { SASL_MECHANISM_NAME }, initialBindRequest
+                .getAuthorizationID(), SASL_DEFAULT_PROTOCOL, serverName, null,
+            this);
+
+        if (saslClient.hasInitialResponse())
+        {
+          setNextSASLCredentials(saslClient.evaluateChallenge(new byte[0]));
+        }
+        else
+        {
+          setNextSASLCredentials((ByteString) null);
+        }
+      }
+      catch (final SaslException e)
+      {
+        throw ErrorResultException.wrap(Responses.newResult(
+            ResultCode.CLIENT_SIDE_LOCAL_ERROR).setCause(e));
+      }
+    }
+
+
+
+    @Override
+    public void dispose()
+    {
+      try
+      {
+        saslClient.dispose();
+      }
+      catch (final SaslException ignored)
+      {
+        // Ignore the SASL exception.
+      }
+    }
+
+
+
+    @Override
+    public boolean evaluateResult(final BindResult result)
+    {
+      return saslClient.isComplete();
+    }
+
+
+
+    @Override
+    void handle(final NameCallback callback)
+        throws UnsupportedCallbackException
+    {
+      callback.setName(authenticationID);
+    }
+
+
+
+    @Override
+    void handle(final PasswordCallback callback)
+        throws UnsupportedCallbackException
+    {
+      callback.setPassword(password.toString().toCharArray());
+    }
+  }
+
+
+
+  private String authenticationID;
+  private String authorizationID;
+
+  private ByteString password;
+
+
+
+  PlainSASLBindRequestImpl(final String authenticationID,
+      final ByteString password)
+  {
+    Validator.ensureNotNull(authenticationID, password);
+    this.authenticationID = authenticationID;
+    this.password = password;
+  }
+
+
+
+  public BindClient createBindClient(final String serverName)
+      throws ErrorResultException
+  {
+    return new Client(this, serverName);
+  }
+
+
+
+  public String getAuthenticationID()
+  {
+    return authenticationID;
+  }
+
+
+
+  public String getAuthorizationID()
+  {
+    return authorizationID;
+  }
+
+
+
+  public ByteString getPassword()
+  {
+    return password;
+  }
+
+
+
+  public String getSASLMechanism()
+  {
+    return SASL_MECHANISM_NAME;
+  }
+
+
+
+  public PlainSASLBindRequest setAuthenticationID(final String authenticationID)
+  {
+    Validator.ensureNotNull(authenticationID);
+    this.authenticationID = authenticationID;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PlainSASLBindRequest setAuthorizationID(final String authorizationID)
+  {
+    this.authorizationID = authorizationID;
+    return this;
+  }
+
+
+
+  public PlainSASLBindRequest setPassword(final ByteString password)
+  {
+    Validator.ensureNotNull(password);
+    this.password = password;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PlainSASLBindRequest setPassword(final String password)
+      throws NullPointerException
+  {
+    Validator.ensureNotNull(password);
+    this.password = ByteString.valueOf(password);
+    return this;
+  }
+
+
+
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PlainSASLBindRequest(bindDN=");
+    builder.append(getName());
+    builder.append(", authentication=SASL");
+    builder.append(", saslMechanism=");
+    builder.append(getSASLMechanism());
+    builder.append(", authenticationID=");
+    builder.append(authenticationID);
+    builder.append(", authorizationID=");
+    builder.append(authorizationID);
+    builder.append(", password=");
+    builder.append(password);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/requests/Request.java b/sdk/src/org/opends/sdk/requests/Request.java
index ed7c60a..741fe77 100644
--- a/sdk/src/org/opends/sdk/requests/Request.java
+++ b/sdk/src/org/opends/sdk/requests/Request.java
@@ -29,13 +29,18 @@
 
 
 
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * The base class of all Requests provides methods for querying and
- * manipulating the set of Controls included with a Request.
+ * The base class of all Requests provides methods for querying and manipulating
+ * the set of Controls included with a Request.
  * <p>
  * TODO: added complete description including sub-types.
  */
@@ -44,7 +49,7 @@
 
   /**
    * Adds the provided control to this request.
-   * 
+   *
    * @param control
    *          The control to be added to this request.
    * @return This request.
@@ -53,72 +58,42 @@
    * @throws NullPointerException
    *           If {@code control} was {@code null}.
    */
-  Request addControl(Control control)
-      throws UnsupportedOperationException, NullPointerException;
+  Request addControl(Control control) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   */
-  Request clearControls() throws UnsupportedOperationException;
-
-
-
-  /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
+   * Decodes and returns the first control in this request having an OID
+   * corresponding to the provided control decoder.
+   *
+   * @param <C>
+   *          The type of control to be decoded and returned.
+   * @param decoder
+   *          The control decoder.
+   * @param options
+   *          The set of decode options which should be used when decoding the
+   *          control.
+   * @return The decoded control, or {@code null} if the control is not included
    *         with this request.
+   * @throws DecodeException
+   *           If the control could not be decoded because it was malformed in
+   *           some way (e.g. the control value was missing, or its content
+   *           could not be decoded).
    * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   *           If {@code decoder} or {@code options} was {@code null}.
    */
-  Control getControl(String oid) throws NullPointerException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws DecodeException, NullPointerException;
 
 
 
   /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
+   * Returns a {@code List} containing the controls included with this request.
+   * The returned {@code List} may be modified if permitted by this request.
+   *
+   * @return A {@code List} containing the controls.
    */
-  Iterable<Control> getControls();
-
-
-
-  /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  List<Control> getControls();
 
 }
diff --git a/sdk/src/org/opends/sdk/requests/Requests.java b/sdk/src/org/opends/sdk/requests/Requests.java
index 66f9705..027b1eb 100644
--- a/sdk/src/org/opends/sdk/requests/Requests.java
+++ b/sdk/src/org/opends/sdk/requests/Requests.java
@@ -29,7 +29,10 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_READ_LDIF_RECORD_CHANGE_RECORD_WRONG_TYPE;
+
+import javax.net.ssl.SSLContext;
+import javax.security.auth.Subject;
 
 import org.opends.sdk.*;
 import org.opends.sdk.ldif.ChangeRecord;
@@ -40,8 +43,7 @@
 
 
 /**
- * This class contains various methods for creating and manipulating
- * requests.
+ * This class contains various methods for creating and manipulating requests.
  * <p>
  * TODO: search request from LDAP URL.
  * <p>
@@ -61,7 +63,7 @@
    *          The message ID of the request to be abandoned.
    * @return The new abandon request.
    */
-  public static AbandonRequest newAbandonRequest(int messageID)
+  public static AbandonRequest newAbandonRequest(final int messageID)
   {
     return new AbandonRequestImpl(messageID);
   }
@@ -77,21 +79,20 @@
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public static AddRequest newAddRequest(DN name)
+  public static AddRequest newAddRequest(final DN name)
       throws NullPointerException
   {
-    final Entry entry = new SortedEntry().setName(name);
+    final Entry entry = new LinkedHashMapEntry().setName(name);
     return new AddRequestImpl(entry);
   }
 
 
 
   /**
-   * Creates a new add request backed by the provided entry.
-   * Modifications made to {@code entry} will be reflected in the
-   * returned add request. The returned add request supports updates to
-   * its list of controls, as well as updates to the name and attributes
-   * if the underlying entry allows.
+   * Creates a new add request backed by the provided entry. Modifications made
+   * to {@code entry} will be reflected in the returned add request. The
+   * returned add request supports updates to its list of controls, as well as
+   * updates to the name and attributes if the underlying entry allows.
    *
    * @param entry
    *          The entry to be added.
@@ -99,7 +100,7 @@
    * @throws NullPointerException
    *           If {@code entry} was {@code null} .
    */
-  public static AddRequest newAddRequest(Entry entry)
+  public static AddRequest newAddRequest(final Entry entry)
       throws NullPointerException
   {
     Validator.ensureNotNull(entry);
@@ -109,46 +110,45 @@
 
 
   /**
-   * Creates a new add request using the provided distinguished name
-   * decoded using the default schema.
+   * Creates a new add request using the provided distinguished name decoded
+   * using the default schema.
    *
    * @param name
    *          The distinguished name of the entry to be added.
    * @return The new add request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
+   *           If {@code name} could not be decoded using the default schema.
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public static AddRequest newAddRequest(String name)
+  public static AddRequest newAddRequest(final String name)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
-    final Entry entry = new SortedEntry().setName(name);
+    final Entry entry = new LinkedHashMapEntry().setName(name);
     return new AddRequestImpl(entry);
   }
 
 
 
   /**
-   * Creates a new add request using the provided lines of LDIF decoded
-   * using the default schema.
+   * Creates a new add request using the provided lines of LDIF decoded using
+   * the default schema.
    *
    * @param ldifLines
-   *          Lines of LDIF containing an LDIF add change record or an
-   *          LDIF entry record.
+   *          Lines of LDIF containing an LDIF add change record or an LDIF
+   *          entry record.
    * @return The new add request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code ldifLines} was empty, or contained invalid
-   *           LDIF, or could not be decoded using the default schema.
+   *           If {@code ldifLines} was empty, or contained invalid LDIF, or
+   *           could not be decoded using the default schema.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null} .
    */
-  public static AddRequest newAddRequest(String... ldifLines)
+  public static AddRequest newAddRequest(final String... ldifLines)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     // LDIF change record reader is tolerant to missing change types.
-    ChangeRecord record = LDIFChangeRecordReader
+    final ChangeRecord record = LDIFChangeRecordReader
         .valueOfLDIFChangeRecord(ldifLines);
 
     if (record instanceof AddRequest)
@@ -158,7 +158,7 @@
     else
     {
       // Wrong change type.
-      LocalizableMessage message = WARN_READ_LDIF_RECORD_CHANGE_RECORD_WRONG_TYPE
+      final LocalizableMessage message = WARN_READ_LDIF_RECORD_CHANGE_RECORD_WRONG_TYPE
           .get("add");
       throw new LocalizedIllegalArgumentException(message);
     }
@@ -167,21 +167,53 @@
 
 
   /**
-   * Creates a new change record (an add, delete, modify, or modify DN
-   * request) using the provided lines of LDIF decoded using the default
-   * schema.
+   * Creates a new anonymous SASL bind request having the provided trace string.
+   *
+   * @param traceString
+   *          The trace information, which has no semantic value, and can be
+   *          used by administrators in order to identify the user.
+   * @return The new anonymous SASL bind request.
+   * @throws NullPointerException
+   *           If {@code traceString} was {@code null}.
+   */
+  public static AnonymousSASLBindRequest newAnonymousSASLBindRequest(
+      final String traceString) throws NullPointerException
+  {
+    return new AnonymousSASLBindRequestImpl(traceString);
+  }
+
+
+
+  /**
+   * Creates a new cancel extended request using the provided message ID.
+   *
+   * @param messageID
+   *          The message ID of the request to be abandoned.
+   * @return The new cancel extended request.
+   */
+  public static CancelExtendedRequest newCancelExtendedRequest(
+      final int messageID)
+  {
+    return new CancelExtendedRequestImpl(messageID);
+  }
+
+
+
+  /**
+   * Creates a new change record (an add, delete, modify, or modify DN request)
+   * using the provided lines of LDIF decoded using the default schema.
    *
    * @param ldifLines
-   *          Lines of LDIF containing an LDIF change record or an LDIF
-   *          entry record.
+   *          Lines of LDIF containing an LDIF change record or an LDIF entry
+   *          record.
    * @return The new change record.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code ldifLines} was empty, or contained invalid
-   *           LDIF, or could not be decoded using the default schema.
+   *           If {@code ldifLines} was empty, or contained invalid LDIF, or
+   *           could not be decoded using the default schema.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null} .
    */
-  public static ChangeRecord newChangeRecord(String... ldifLines)
+  public static ChangeRecord newChangeRecord(final String... ldifLines)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     // LDIF change record reader is tolerant to missing change types.
@@ -191,8 +223,8 @@
 
 
   /**
-   * Creates a new compare request using the provided distinguished
-   * name, attribute name, and assertion value.
+   * Creates a new compare request using the provided distinguished name,
+   * attribute name, and assertion value.
    *
    * @param name
    *          The distinguished name of the entry to be compared.
@@ -205,25 +237,22 @@
    *           If {@code name}, {@code attributeDescription}, or {@code
    *           assertionValue} was {@code null}.
    */
-  public static CompareRequest newCompareRequest(DN name,
-      AttributeDescription attributeDescription,
-      ByteString assertionValue) throws NullPointerException
+  public static CompareRequest newCompareRequest(final DN name,
+      final AttributeDescription attributeDescription,
+      final ByteString assertionValue) throws NullPointerException
   {
     Validator.ensureNotNull(name, attributeDescription, assertionValue);
-    return new CompareRequestImpl(name, attributeDescription,
-        assertionValue);
+    return new CompareRequestImpl(name, attributeDescription, assertionValue);
   }
 
 
 
   /**
-   * Creates a new compare request using the provided distinguished
-   * name, attribute name, and assertion value decoded using the default
-   * schema.
+   * Creates a new compare request using the provided distinguished name,
+   * attribute name, and assertion value decoded using the default schema.
    * <p>
-   * If the assertion value is not an instance of {@code ByteString}
-   * then it will be converted using the
-   * {@link ByteString#valueOf(Object)} method.
+   * If the assertion value is not an instance of {@code ByteString} then it
+   * will be converted using the {@link ByteString#valueOf(Object)} method.
    *
    * @param name
    *          The distinguished name of the entry to be compared.
@@ -233,20 +262,44 @@
    *          The assertion value to be compared.
    * @return The new compare request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} or {@code attributeDescription} could not
-   *           be decoded using the default schema.
+   *           If {@code name} or {@code attributeDescription} could not be
+   *           decoded using the default schema.
    * @throws NullPointerException
    *           If {@code name}, {@code attributeDescription}, or {@code
    *           assertionValue} was {@code null}.
    */
-  public static CompareRequest newCompareRequest(String name,
-      String attributeDescription, Object assertionValue)
+  public static CompareRequest newCompareRequest(final String name,
+      final String attributeDescription, final Object assertionValue)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(name, attributeDescription, assertionValue);
-    return new CompareRequestImpl(DN.valueOf(name),
-        AttributeDescription.valueOf(attributeDescription), ByteString
-            .valueOf(assertionValue));
+    return new CompareRequestImpl(DN.valueOf(name), AttributeDescription
+        .valueOf(attributeDescription), ByteString.valueOf(assertionValue));
+  }
+
+
+
+  /**
+   * Creates a new CRAM-MD5 SASL bind request having the provided authentication
+   * ID and password.
+   *
+   * @param authenticationID
+   *          The authentication ID of the user. The authentication ID usually
+   *          has the form "dn:" immediately followed by the distinguished name
+   *          of the user, or "u:" followed by a user ID string, but other forms
+   *          are permitted.
+   * @param password
+   *          The password of the user that the client wishes to bind as. The
+   *          password will be converted to a UTF-8 octet string.
+   * @return The new CRAM-MD5 SASL bind request.
+   * @throws NullPointerException
+   *           If {@code authenticationID} or {@code password} was {@code null}.
+   */
+  public static CRAMMD5SASLBindRequest newCRAMMD5SASLBindRequest(
+      final String authenticationID, final ByteString password)
+      throws NullPointerException
+  {
+    return new CRAMMD5SASLBindRequestImpl(authenticationID, password);
   }
 
 
@@ -260,7 +313,7 @@
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public static DeleteRequest newDeleteRequest(DN name)
+  public static DeleteRequest newDeleteRequest(final DN name)
       throws NullPointerException
   {
     Validator.ensureNotNull(name);
@@ -270,19 +323,18 @@
 
 
   /**
-   * Creates a new delete request using the provided distinguished name
-   * decoded using the default schema.
+   * Creates a new delete request using the provided distinguished name decoded
+   * using the default schema.
    *
    * @param name
    *          The distinguished name of the entry to be deleted.
    * @return The new delete request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
+   *           If {@code name} could not be decoded using the default schema.
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public static DeleteRequest newDeleteRequest(String name)
+  public static DeleteRequest newDeleteRequest(final String name)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(name);
@@ -292,50 +344,90 @@
 
 
   /**
-   * Creates a new generic bind request using an empty distinguished
-   * name, authentication type, and authentication information.
+   * Creates a new DIGEST-MD5 SASL bind request having the provided
+   * authentication ID and password, but no realm or authorization ID.
+   *
+   * @param authenticationID
+   *          The authentication ID of the user. The authentication ID usually
+   *          has the form "dn:" immediately followed by the distinguished name
+   *          of the user, or "u:" followed by a user ID string, but other forms
+   *          are permitted.
+   * @param password
+   *          The password of the user that the client wishes to bind as. The
+   *          password will be converted to a UTF-8 octet string.
+   * @return The new DIGEST-MD5 SASL bind request.
+   * @throws NullPointerException
+   *           If {@code authenticationID} or {@code password} was {@code null}.
+   */
+  public static DigestMD5SASLBindRequest newDigestMD5SASLBindRequest(
+      final String authenticationID, final ByteString password)
+      throws NullPointerException
+  {
+    return new DigestMD5SASLBindRequestImpl(authenticationID, password);
+  }
+
+
+
+  /**
+   * Creates a new External SASL bind request with no authorization ID.
+   *
+   * @return The new External SASL bind request.
+   */
+  public static ExternalSASLBindRequest newExternalSASLBindRequest()
+  {
+    return new ExternalSASLBindRequestImpl();
+  }
+
+
+
+  /**
+   * Creates a new generic bind request using an empty distinguished name,
+   * authentication type, and authentication information.
    *
    * @param authenticationType
-   *          The authentication mechanism identifier for this generic
-   *          bind request.
+   *          The authentication mechanism identifier for this generic bind
+   *          request.
    * @param authenticationValue
-   *          The authentication information for this generic bind
-   *          request in a form defined by the authentication mechanism.
+   *          The authentication information for this generic bind request in a
+   *          form defined by the authentication mechanism.
    * @return The new generic bind request.
    * @throws NullPointerException
    *           If {@code authenticationValue} was {@code null}.
    */
   public static GenericBindRequest newGenericBindRequest(
-      byte authenticationType, ByteString authenticationValue)
+      final byte authenticationType, final ByteString authenticationValue)
       throws NullPointerException
   {
     Validator.ensureNotNull(authenticationValue);
-    return new GenericBindRequestImpl(DN.rootDN(), authenticationType,
+    return new GenericBindRequestImpl("", authenticationType,
         authenticationValue);
   }
 
 
 
   /**
-   * Creates a new generic bind request using the provided distinguished
-   * name, authentication type, and authentication information.
+   * Creates a new generic bind request using the provided name, authentication
+   * type, and authentication information.
+   * <p>
+   * The LDAP protocol defines the Bind name to be a distinguished name, however
+   * some LDAP implementations have relaxed this constraint and allow other
+   * identities to be used, such as the user's email address.
    *
    * @param name
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as (may be empty).
+   *          The name of the Directory object that the client wishes to bind as
+   *          (may be empty).
    * @param authenticationType
-   *          The authentication mechanism identifier for this generic
-   *          bind request.
+   *          The authentication mechanism identifier for this generic bind
+   *          request.
    * @param authenticationValue
-   *          The authentication information for this generic bind
-   *          request in a form defined by the authentication mechanism.
+   *          The authentication information for this generic bind request in a
+   *          form defined by the authentication mechanism.
    * @return The new generic bind request.
    * @throws NullPointerException
-   *           If {@code name} or {@code authenticationValue} was
-   *           {@code null}.
+   *           If {@code name} or {@code authenticationValue} was {@code null}.
    */
-  public static GenericBindRequest newGenericBindRequest(DN name,
-      byte authenticationType, ByteString authenticationValue)
+  public static GenericBindRequest newGenericBindRequest(final String name,
+      final byte authenticationType, final ByteString authenticationValue)
       throws NullPointerException
   {
     Validator.ensureNotNull(name, authenticationValue);
@@ -346,50 +438,18 @@
 
 
   /**
-   * Creates a new generic bind request using the provided distinguished
-   * name, authentication type, and authentication information.
-   *
-   * @param name
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as (may be empty).
-   * @param authenticationType
-   *          The authentication mechanism identifier for this generic
-   *          bind request.
-   * @param authenticationValue
-   *          The authentication information for this generic bind
-   *          request in a form defined by the authentication mechanism.
-   * @return The new generic bind request.
-   * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
-   * @throws NullPointerException
-   *           If {@code name} or {@code authenticationValue} was
-   *           {@code null}.
-   */
-  public static GenericBindRequest newGenericBindRequest(String name,
-      byte authenticationType, ByteString authenticationValue)
-      throws LocalizedIllegalArgumentException, NullPointerException
-  {
-    Validator.ensureNotNull(name, authenticationValue);
-    return new GenericBindRequestImpl(DN.valueOf(name),
-        authenticationType, authenticationValue);
-  }
-
-
-
-  /**
-   * Creates a new generic extended request using the provided name and
-   * no value.
+   * Creates a new generic extended request using the provided name and no
+   * value.
    *
    * @param requestName
-   *          The dotted-decimal representation of the unique OID
-   *          corresponding to this extended request.
+   *          The dotted-decimal representation of the unique OID corresponding
+   *          to this extended request.
    * @return The new generic extended request.
    * @throws NullPointerException
    *           If {@code requestName} was {@code null}.
    */
   public static GenericExtendedRequest newGenericExtendedRequest(
-      String requestName) throws NullPointerException
+      final String requestName) throws NullPointerException
   {
     Validator.ensureNotNull(requestName);
     return new GenericExtendedRequestImpl(requestName, null);
@@ -398,22 +458,21 @@
 
 
   /**
-   * Creates a new generic extended request using the provided name and
-   * optional value.
+   * Creates a new generic extended request using the provided name and optional
+   * value.
    *
    * @param requestName
-   *          The dotted-decimal representation of the unique OID
-   *          corresponding to this extended request.
+   *          The dotted-decimal representation of the unique OID corresponding
+   *          to this extended request.
    * @param requestValue
-   *          The content of this generic extended request in a form
-   *          defined by the extended operation, or {@code null} if
-   *          there is no content.
+   *          The content of this generic extended request in a form defined by
+   *          the extended operation, or {@code null} if there is no content.
    * @return The new generic extended request.
    * @throws NullPointerException
    *           If {@code requestName} was {@code null}.
    */
   public static GenericExtendedRequest newGenericExtendedRequest(
-      String requestName, ByteString requestValue)
+      final String requestName, final ByteString requestValue)
       throws NullPointerException
   {
     Validator.ensureNotNull(requestName);
@@ -423,8 +482,51 @@
 
 
   /**
-   * Creates a new modify DN request using the provided distinguished
-   * name and new RDN.
+   * Creates a new GSSAPI SASL bind request having the provided authentication
+   * ID and password, but no realm, KDC address, or authorization ID.
+   *
+   * @param authenticationID
+   *          The authentication ID of the user. The authentication ID usually
+   *          has the form "dn:" immediately followed by the distinguished name
+   *          of the user, or "u:" followed by a user ID string, but other forms
+   *          are permitted.
+   * @param password
+   *          The password of the user that the client wishes to bind as. The
+   *          password will be converted to a UTF-8 octet string.
+   * @return The new GSSAPI SASL bind request.
+   * @throws NullPointerException
+   *           If {@code authenticationID} or {@code password} was {@code null}.
+   */
+  public static GSSAPISASLBindRequest newGSSAPISASLBindRequest(
+      final String authenticationID, final ByteString password)
+      throws NullPointerException
+  {
+    return new GSSAPISASLBindRequestImpl(authenticationID, password);
+  }
+
+
+
+  /**
+   * Creates a new GSSAPI SASL bind request having the provided subject, but no
+   * authorization ID.
+   *
+   * @param subject
+   *          The Kerberos subject of the user to be authenticated.
+   * @return The new GSSAPI SASL bind request.
+   * @throws NullPointerException
+   *           If {@code subject} was {@code null}.
+   */
+  public static GSSAPISASLBindRequest newGSSAPISASLBindRequest(
+      final Subject subject) throws NullPointerException
+  {
+    return new GSSAPISASLBindRequestImpl(subject);
+  }
+
+
+
+  /**
+   * Creates a new modify DN request using the provided distinguished name and
+   * new RDN.
    *
    * @param name
    *          The distinguished name of the entry to be renamed.
@@ -434,8 +536,8 @@
    * @throws NullPointerException
    *           If {@code name} or {@code newRDN} was {@code null}.
    */
-  public static ModifyDNRequest newModifyDNRequest(DN name, RDN newRDN)
-      throws NullPointerException
+  public static ModifyDNRequest newModifyDNRequest(final DN name,
+      final RDN newRDN) throws NullPointerException
   {
     Validator.ensureNotNull(name, newRDN);
     return new ModifyDNRequestImpl(name, newRDN);
@@ -444,8 +546,8 @@
 
 
   /**
-   * Creates a new modify DN request using the provided distinguished
-   * name and new RDN decoded using the default schema.
+   * Creates a new modify DN request using the provided distinguished name and
+   * new RDN decoded using the default schema.
    *
    * @param name
    *          The distinguished name of the entry to be renamed.
@@ -453,18 +555,17 @@
    *          The new RDN of the entry.
    * @return The new modify DN request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} or {@code newRDN} could not be decoded
-   *           using the default schema.
+   *           If {@code name} or {@code newRDN} could not be decoded using the
+   *           default schema.
    * @throws NullPointerException
    *           If {@code name} or {@code newRDN} was {@code null}.
    */
-  public static ModifyDNRequest newModifyDNRequest(String name,
-      String newRDN) throws LocalizedIllegalArgumentException,
+  public static ModifyDNRequest newModifyDNRequest(final String name,
+      final String newRDN) throws LocalizedIllegalArgumentException,
       NullPointerException
   {
     Validator.ensureNotNull(name, newRDN);
-    return new ModifyDNRequestImpl(DN.valueOf(name), RDN
-        .valueOf(newRDN));
+    return new ModifyDNRequestImpl(DN.valueOf(name), RDN.valueOf(newRDN));
   }
 
 
@@ -478,7 +579,7 @@
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public static ModifyRequest newModifyRequest(DN name)
+  public static ModifyRequest newModifyRequest(final DN name)
       throws NullPointerException
   {
     Validator.ensureNotNull(name);
@@ -488,19 +589,18 @@
 
 
   /**
-   * Creates a new modify request using the provided distinguished name
-   * decoded using the default schema.
+   * Creates a new modify request using the provided distinguished name decoded
+   * using the default schema.
    *
    * @param name
    *          The distinguished name of the entry to be modified.
    * @return The new modify request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
+   *           If {@code name} could not be decoded using the default schema.
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public static ModifyRequest newModifyRequest(String name)
+  public static ModifyRequest newModifyRequest(final String name)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(name);
@@ -510,24 +610,23 @@
 
 
   /**
-   * Creates a new modify request using the provided lines of LDIF
-   * decoded using the default schema.
+   * Creates a new modify request using the provided lines of LDIF decoded using
+   * the default schema.
    *
    * @param ldifLines
-   *          Lines of LDIF containing a single LDIF modify change
-   *          record.
+   *          Lines of LDIF containing a single LDIF modify change record.
    * @return The new modify request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code ldifLines} was empty, or contained invalid
-   *           LDIF, or could not be decoded using the default schema.
+   *           If {@code ldifLines} was empty, or contained invalid LDIF, or
+   *           could not be decoded using the default schema.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null} .
    */
-  public static ModifyRequest newModifyRequest(String... ldifLines)
+  public static ModifyRequest newModifyRequest(final String... ldifLines)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     // LDIF change record reader is tolerant to missing change types.
-    ChangeRecord record = LDIFChangeRecordReader
+    final ChangeRecord record = LDIFChangeRecordReader
         .valueOfLDIFChangeRecord(ldifLines);
 
     if (record instanceof ModifyRequest)
@@ -537,7 +636,7 @@
     else
     {
       // Wrong change type.
-      LocalizableMessage message = WARN_READ_LDIF_RECORD_CHANGE_RECORD_WRONG_TYPE
+      final LocalizableMessage message = WARN_READ_LDIF_RECORD_CHANGE_RECORD_WRONG_TYPE
           .get("modify");
       throw new LocalizedIllegalArgumentException(message);
     }
@@ -546,67 +645,113 @@
 
 
   /**
-   * Creates a new search request using the provided distinguished name,
-   * scope, and filter, decoded using the default schema.
+   * Creates a new password modify extended request, with no user identity, old
+   * password, or new password.
    *
-   * @param name
-   *          The distinguished name of the base entry relative to which
-   *          the search is to be performed.
-   * @param scope
-   *          The scope of the search.
-   * @param filter
-   *          The filter that defines the conditions that must be
-   *          fulfilled in order for an entry to be returned.
-   * @param attributeDescriptions
-   *          The names of the attributes to be included with each
-   *          entry.
-   * @return The new search request.
-   * @throws NullPointerException
-   *           If the {@code name}, {@code scope}, or {@code filter}
-   *           were {@code null}.
+   * @return The new password modify extended request.
    */
-  public static SearchRequest newSearchRequest(DN name,
-      SearchScope scope, Filter filter, String... attributeDescriptions)
-      throws NullPointerException
+  public static PasswordModifyExtendedRequest newPasswordModifyExtendedRequest()
   {
-    Validator.ensureNotNull(name, scope, filter);
-    return new SearchRequestImpl(name, scope, filter)
-        .addAttribute(attributeDescriptions);
+    return new PasswordModifyExtendedRequestImpl();
   }
 
 
 
   /**
-   * Creates a new search request using the provided distinguished name,
-   * scope, and filter, decoded using the default schema.
+   * Creates a new Plain SASL bind request having the provided authentication ID
+   * and password, but no authorization ID.
+   *
+   * @param authenticationID
+   *          The authentication ID of the user. The authentication ID usually
+   *          has the form "dn:" immediately followed by the distinguished name
+   *          of the user, or "u:" followed by a user ID string, but other forms
+   *          are permitted.
+   * @param password
+   *          The password of the user that the client wishes to bind as. The
+   *          password will be converted to a UTF-8 octet string.
+   * @return The new Plain SASL bind request.
+   * @throws NullPointerException
+   *           If {@code authenticationID} or {@code password} was {@code null}.
+   */
+  public static PlainSASLBindRequest newPlainSASLBindRequest(
+      final String authenticationID, final ByteString password)
+      throws NullPointerException
+  {
+    return new PlainSASLBindRequestImpl(authenticationID, password);
+  }
+
+
+
+  /**
+   * Creates a new search request using the provided distinguished name, scope,
+   * and filter, decoded using the default schema.
    *
    * @param name
-   *          The distinguished name of the base entry relative to which
-   *          the search is to be performed.
+   *          The distinguished name of the base entry relative to which the
+   *          search is to be performed.
    * @param scope
    *          The scope of the search.
    * @param filter
-   *          The filter that defines the conditions that must be
-   *          fulfilled in order for an entry to be returned.
+   *          The filter that defines the conditions that must be fulfilled in
+   *          order for an entry to be returned.
    * @param attributeDescriptions
-   *          The names of the attributes to be included with each
-   *          entry.
+   *          The names of the attributes to be included with each entry.
+   * @return The new search request.
+   * @throws NullPointerException
+   *           If the {@code name}, {@code scope}, or {@code filter} were
+   *           {@code null}.
+   */
+  public static SearchRequest newSearchRequest(final DN name,
+      final SearchScope scope, final Filter filter,
+      final String... attributeDescriptions) throws NullPointerException
+  {
+    Validator.ensureNotNull(name, scope, filter);
+    final SearchRequest request = new SearchRequestImpl(name, scope, filter);
+    for (final String attributeDescription : attributeDescriptions)
+    {
+      request.addAttribute(attributeDescription);
+    }
+    return request;
+  }
+
+
+
+  /**
+   * Creates a new search request using the provided distinguished name, scope,
+   * and filter, decoded using the default schema.
+   *
+   * @param name
+   *          The distinguished name of the base entry relative to which the
+   *          search is to be performed.
+   * @param scope
+   *          The scope of the search.
+   * @param filter
+   *          The filter that defines the conditions that must be fulfilled in
+   *          order for an entry to be returned.
+   * @param attributeDescriptions
+   *          The names of the attributes to be included with each entry.
    * @return The new search request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema, or if {@code filter} is not a valid LDAP string
-   *           representation of a filter.
+   *           If {@code name} could not be decoded using the default schema, or
+   *           if {@code filter} is not a valid LDAP string representation of a
+   *           filter.
    * @throws NullPointerException
-   *           If the {@code name}, {@code scope}, or {@code filter}
-   *           were {@code null}.
+   *           If the {@code name}, {@code scope}, or {@code filter} were
+   *           {@code null}.
    */
-  public static SearchRequest newSearchRequest(String name,
-      SearchScope scope, String filter, String... attributeDescriptions)
+  public static SearchRequest newSearchRequest(final String name,
+      final SearchScope scope, final String filter,
+      final String... attributeDescriptions)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(name, scope, filter);
-    return new SearchRequestImpl(DN.valueOf(name), scope, Filter
-        .valueOf(filter)).addAttribute(attributeDescriptions);
+    final SearchRequest request = new SearchRequestImpl(DN.valueOf(name),
+        scope, Filter.valueOf(filter));
+    for (final String attributeDescription : attributeDescriptions)
+    {
+      request.addAttribute(attributeDescription);
+    }
+    return request;
   }
 
 
@@ -619,61 +764,54 @@
    */
   public static SimpleBindRequest newSimpleBindRequest()
   {
-    return new SimpleBindRequestImpl(DN.rootDN(), ByteString.empty());
+    return new SimpleBindRequestImpl("", ByteString.empty());
   }
 
 
 
   /**
-   * Creates a new simple bind request having the provided name and
-   * password suitable for name/password authentication.
+   * Creates a new simple bind request having the provided name and password
+   * suitable for name/password authentication. The name will be decoded using
+   * the default schema.
+   * <p>
+   * The LDAP protocol defines the Bind name to be a distinguished name, however
+   * some LDAP implementations have relaxed this constraint and allow other
+   * identities to be used, such as the user's email address.
    *
    * @param name
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as, which may be empty.
+   *          The name of the Directory object that the client wishes to bind
+   *          as, which may be empty.
    * @param password
-   *          The password of the Directory object that the client
-   *          wishes to bind as, which may be empty indicating that an
-   *          unauthenticated bind is to be performed.
+   *          The password of the Directory object that the client wishes to
+   *          bind as, which may be empty indicating that an unauthenticated
+   *          bind is to be performed.
    * @return The new simple bind request.
    * @throws NullPointerException
    *           If {@code name} or {@code password} was {@code null}.
    */
-  public static SimpleBindRequest newSimpleBindRequest(DN name,
-      ByteString password) throws NullPointerException
+  public static SimpleBindRequest newSimpleBindRequest(final String name,
+      final String password) throws NullPointerException
   {
     Validator.ensureNotNull(name, password);
-    return new SimpleBindRequestImpl(name, password);
+    return new SimpleBindRequestImpl(name, ByteString.valueOf(password));
   }
 
 
 
   /**
-   * Creates a new simple bind request having the provided name and
-   * password suitable for name/password authentication. The name will
-   * be decoded using the default schema.
+   * Creates a new start TLS extended request which will use the provided SSL
+   * context.
    *
-   * @param name
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as, which may be empty..
-   * @param password
-   *          The password of the Directory object that the client
-   *          wishes to bind as, which may be empty indicating that an
-   *          unauthenticated bind is to be performed.
-   * @return The new simple bind request.
-   * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
+   * @param sslContext
+   *          The SSLContext that should be used when installing the TLS layer.
+   * @return The new start TLS extended request.
    * @throws NullPointerException
-   *           If {@code name} or {@code password} was {@code null}.
+   *           If {@code sslContext} was {@code null}.
    */
-  public static SimpleBindRequest newSimpleBindRequest(String name,
-      String password) throws LocalizedIllegalArgumentException,
-      NullPointerException
+  public static StartTLSExtendedRequest newStartTLSExtendedRequest(
+      final SSLContext sslContext) throws NullPointerException
   {
-    Validator.ensureNotNull(name, password);
-    return new SimpleBindRequestImpl(DN.valueOf(name), ByteString
-        .valueOf(password));
+    return new StartTLSExtendedRequestImpl(sslContext);
   }
 
 
@@ -690,6 +828,18 @@
 
 
 
+  /**
+   * Creates a new Who Am I extended request.
+   *
+   * @return The new Who Am I extended request.
+   */
+  public static WhoAmIExtendedRequest newWhoAmIExtendedRequest()
+  {
+    return new WhoAmIExtendedRequestImpl();
+  }
+
+
+
   private Requests()
   {
     // Prevent instantiation.
diff --git a/sdk/src/org/opends/sdk/requests/SASLBindClientImpl.java b/sdk/src/org/opends/sdk/requests/SASLBindClientImpl.java
new file mode 100644
index 0000000..d45f631
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/SASLBindClientImpl.java
@@ -0,0 +1,275 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.INFO_SASL_UNSUPPORTED_CALLBACK;
+
+import java.io.IOException;
+
+import javax.security.auth.callback.*;
+import javax.security.sasl.AuthorizeCallback;
+import javax.security.sasl.RealmCallback;
+import javax.security.sasl.RealmChoiceCallback;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.ByteStringBuilder;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Writer;
+
+
+
+/**
+ * SASL bind client implementation.
+ */
+class SASLBindClientImpl extends BindClientImpl implements CallbackHandler
+{
+  /**
+   * The name of the default protocol used.
+   */
+  static final String SASL_DEFAULT_PROTOCOL = "ldap";
+
+  private final String saslMechanism;
+
+
+
+  /**
+   * Creates a new abstract SASL bind client. The next bind request will be a
+   * copy of the provided initial bind request which should be updated in
+   * subsequent bind requests forming part of this authentication.
+   *
+   * @param initialBindRequest
+   *          The initial bind request.
+   */
+  SASLBindClientImpl(final SASLBindRequest initialBindRequest)
+  {
+    super(initialBindRequest);
+    this.saslMechanism = initialBindRequest.getSASLMechanism();
+  }
+
+
+
+  public final void handle(final Callback[] callbacks) throws IOException,
+      UnsupportedCallbackException
+  {
+    for (final Callback callback : callbacks)
+    {
+      if (callback instanceof NameCallback)
+      {
+        handle((NameCallback) callback);
+      }
+      else if (callback instanceof PasswordCallback)
+      {
+        handle((PasswordCallback) callback);
+      }
+      else if (callback instanceof AuthorizeCallback)
+      {
+        handle((AuthorizeCallback) callback);
+      }
+      else if (callback instanceof RealmCallback)
+      {
+        handle((RealmCallback) callback);
+      }
+      else if (callback instanceof RealmChoiceCallback)
+      {
+        handle((RealmChoiceCallback) callback);
+      }
+      else if (callback instanceof ChoiceCallback)
+      {
+        handle((ChoiceCallback) callback);
+      }
+      else if (callback instanceof ConfirmationCallback)
+      {
+        handle((ConfirmationCallback) callback);
+      }
+      else if (callback instanceof LanguageCallback)
+      {
+        handle((LanguageCallback) callback);
+      }
+      else if (callback instanceof TextInputCallback)
+      {
+        handle((TextInputCallback) callback);
+      }
+      else if (callback instanceof TextOutputCallback)
+      {
+        handle((TextOutputCallback) callback);
+      }
+      else
+      {
+        final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+            .get(saslMechanism, String.valueOf(callback));
+        throw new UnsupportedCallbackException(callback, message.toString());
+      }
+    }
+  }
+
+
+
+  void handle(final AuthorizeCallback callback)
+      throws UnsupportedCallbackException
+  {
+    final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+        .get(saslMechanism, String.valueOf(callback));
+    throw new UnsupportedCallbackException(callback, message.toString());
+  }
+
+
+
+  void handle(final ChoiceCallback callback)
+      throws UnsupportedCallbackException
+  {
+    final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+        .get(saslMechanism, String.valueOf(callback));
+    throw new UnsupportedCallbackException(callback, message.toString());
+  }
+
+
+
+  void handle(final ConfirmationCallback callback)
+      throws UnsupportedCallbackException
+  {
+    final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+        .get(saslMechanism, String.valueOf(callback));
+    throw new UnsupportedCallbackException(callback, message.toString());
+  }
+
+
+
+  void handle(final LanguageCallback callback)
+      throws UnsupportedCallbackException
+  {
+    final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+        .get(saslMechanism, String.valueOf(callback));
+    throw new UnsupportedCallbackException(callback, message.toString());
+  }
+
+
+
+  void handle(final NameCallback callback) throws UnsupportedCallbackException
+  {
+    final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+        .get(saslMechanism, String.valueOf(callback));
+    throw new UnsupportedCallbackException(callback, message.toString());
+  }
+
+
+
+  void handle(final PasswordCallback callback)
+      throws UnsupportedCallbackException
+  {
+    final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+        .get(saslMechanism, String.valueOf(callback));
+    throw new UnsupportedCallbackException(callback, message.toString());
+  }
+
+
+
+  void handle(final RealmCallback callback) throws UnsupportedCallbackException
+  {
+    final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+        .get(saslMechanism, String.valueOf(callback));
+    throw new UnsupportedCallbackException(callback, message.toString());
+  }
+
+
+
+  void handle(final RealmChoiceCallback callback)
+      throws UnsupportedCallbackException
+  {
+    final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+        .get(saslMechanism, String.valueOf(callback));
+    throw new UnsupportedCallbackException(callback, message.toString());
+  }
+
+
+
+  void handle(final TextInputCallback callback)
+      throws UnsupportedCallbackException
+  {
+    final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+        .get(saslMechanism, String.valueOf(callback));
+    throw new UnsupportedCallbackException(callback, message.toString());
+  }
+
+
+
+  void handle(final TextOutputCallback callback)
+      throws UnsupportedCallbackException
+  {
+    final org.opends.sdk.LocalizableMessage message = INFO_SASL_UNSUPPORTED_CALLBACK
+        .get(saslMechanism, String.valueOf(callback));
+    throw new UnsupportedCallbackException(callback, message.toString());
+  }
+
+
+
+  /**
+   * Sets the SASL credentials to be used in the next bind request.
+   *
+   * @param saslCredentials
+   *          The SASL credentials to be used in the next bind request.
+   * @return A reference to this SASL bind client.
+   */
+  final BindClient setNextSASLCredentials(final byte[] saslCredentials)
+  {
+    final ByteString value = (saslCredentials != null) ? ByteString
+        .wrap(saslCredentials) : null;
+    return setNextSASLCredentials(value);
+  }
+
+
+
+  /**
+   * Sets the SASL credentials to be used in the next bind request.
+   *
+   * @param saslCredentials
+   *          The SASL credentials to be used in the next bind request.
+   * @return A reference to this SASL bind client.
+   */
+  final BindClient setNextSASLCredentials(final ByteString saslCredentials)
+  {
+    final ByteStringBuilder builder = new ByteStringBuilder();
+    final ASN1Writer writer = ASN1.getWriter(builder);
+
+    try
+    {
+      writer.writeOctetString(saslMechanism);
+      if (saslCredentials != null)
+      {
+        writer.writeOctetString(saslCredentials);
+      }
+    }
+    catch (final IOException ioe)
+    {
+      throw new RuntimeException("Error encoding SaslCredentials");
+    }
+
+    return setNextAuthenticationValue(builder.toByteString());
+  }
+}
diff --git a/sdk/src/org/opends/sdk/requests/SASLBindRequest.java b/sdk/src/org/opends/sdk/requests/SASLBindRequest.java
new file mode 100644
index 0000000..2851c73
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/SASLBindRequest.java
@@ -0,0 +1,108 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.ErrorResultException;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+
+
+/**
+ * The SASL authentication method of the Bind operation allows clients to
+ * authenticate using one of the SASL authentication methods defined in RFC
+ * 4513.
+ * <p>
+ * <TODO>finish doc.
+ */
+public interface SASLBindRequest extends BindRequest
+{
+  /**
+   * {@inheritDoc}
+   */
+  SASLBindRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  BindClient createBindClient(String serverName) throws ErrorResultException;
+
+
+
+  /**
+   * Returns the authentication mechanism identifier for this SASL bind request
+   * as defined by the LDAP protocol, which is always {@code 0xA3}.
+   *
+   * @return The authentication mechanism identifier.
+   */
+  byte getAuthenticationType();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * Returns the name of the Directory object that the client wishes to bind as,
+   * which is always the empty string for SASL authentication.
+   *
+   * @return The name of the Directory object that the client wishes to bind as.
+   */
+  String getName();
+
+
+
+  /**
+   * Returns the SASL mechanism for this SASL bind request.
+   *
+   * @return The SASL mechanism for this bind request.
+   */
+  String getSASLMechanism();
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/SearchRequest.java b/sdk/src/org/opends/sdk/requests/SearchRequest.java
index d46618a..38e00dc 100644
--- a/sdk/src/org/opends/sdk/requests/SearchRequest.java
+++ b/sdk/src/org/opends/sdk/requests/SearchRequest.java
@@ -29,57 +29,34 @@
 
 
 
-import java.util.Collection;
+import java.util.List;
 
 import org.opends.sdk.*;
 import org.opends.sdk.controls.Control;
-
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * The Search operation is used to request a server to return, subject
- * to access controls and other restrictions, a set of entries matching
- * a complex search criterion. This can be used to read attributes from
- * a single entry, from entries immediately subordinate to a particular
- * entry, or from a whole subtree of entries.
+ * The Search operation is used to request a server to return, subject to access
+ * controls and other restrictions, a set of entries matching a complex search
+ * criterion. This can be used to read attributes from a single entry, from
+ * entries immediately subordinate to a particular entry, or from a whole
+ * subtree of entries.
  */
 public interface SearchRequest extends Request
 {
   /**
-   * Adds the provided attribute names to the list of attributes to be
-   * included with each entry that matches the search criteria.
-   * Attributes that are sub-types of listed attributes are implicitly
-   * included.
-   * 
-   * @param attributeDescriptions
-   *          The names of the attributes to be included with each
-   *          entry.
-   * @return This search request.
-   * @throws UnsupportedOperationException
-   *           If this search request does not permit attribute names to
-   *           be added.
-   * @throws NullPointerException
-   *           If {@code attributeDescriptions} was {@code null}, or if
-   *           it contained a {@code null} element.
-   */
-  SearchRequest addAttribute(Collection<String> attributeDescriptions)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Adds the provided attribute name to the list of attributes to be
-   * included with each entry that matches the search criteria.
-   * Attributes that are sub-types of listed attributes are implicitly
-   * included.
-   * 
+   * Adds the provided attribute name to the list of attributes to be included
+   * with each entry that matches the search criteria. Attributes that are
+   * sub-types of listed attributes are implicitly included.
+   *
    * @param attributeDescription
    *          The name of the attribute to be included with each entry.
    * @return This search request.
    * @throws UnsupportedOperationException
-   *           If this search request does not permit attribute names to
-   *           be added.
+   *           If this search request does not permit attribute names to be
+   *           added.
    * @throws NullPointerException
    *           If {@code attributeDescription} was {@code null}.
    */
@@ -89,37 +66,7 @@
 
 
   /**
-   * Adds the provided attribute names to the list of attributes to be
-   * included with each entry that matches the search criteria.
-   * Attributes that are sub-types of listed attributes are implicitly
-   * included.
-   * 
-   * @param attributeDescriptions
-   *          The names of the attributes to be included with each
-   *          entry.
-   * @return This search request.
-   * @throws UnsupportedOperationException
-   *           If this search request does not permit attribute names to
-   *           be added.
-   * @throws NullPointerException
-   *           If {@code attributeDescriptions} was {@code null}, or if
-   *           it contained a {@code null} element.
-   */
-  SearchRequest addAttribute(String... attributeDescriptions)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
   SearchRequest addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -127,73 +74,36 @@
 
 
   /**
-   * Clears the list of attributes to be included with each entry that
-   * matches the search criteria. Attributes that are sub-types of
-   * listed attributes are implicitly included.
-   * 
-   * @return This search request.
-   * @throws UnsupportedOperationException
-   *           If this search request does not permit attributes to be
-   *           removed.
+   * Returns a {@code List} containing the list of attributes to be included
+   * with each entry that matches the search criteria. Attributes that are
+   * sub-types of listed attributes are implicitly included. The returned
+   * {@code List} may be modified if permitted by this search request.
+   *
+   * @return A {@code List} containing the list of attributes.
    */
-  SearchRequest clearAttributes() throws UnsupportedOperationException;
+  List<String> getAttributes();
 
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * {@inheritDoc}
    */
-  SearchRequest clearControls() throws UnsupportedOperationException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns an {@code Iterable} containing the list of attributes to be
-   * included with each entry that matches the search criteria.
-   * Attributes that are sub-types of listed attributes are implicitly
-   * included. The returned {@code Iterable} may be used to remove
-   * attribute names if permitted by this search request.
-   * 
-   * @return An {@code Iterable} containing the list of attributes.
+   * {@inheritDoc}
    */
-  Iterable<String> getAttributes();
-
-
-
-  /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control getControl(String oid) throws NullPointerException;
-
-
-
-  /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
-   */
-  Iterable<Control> getControls();
+  List<Control> getControls();
 
 
 
   /**
    * Returns an indication as to whether or not alias entries are to be
    * dereferenced during the search.
-   * 
+   *
    * @return The alias dereferencing policy.
    */
   DereferenceAliasesPolicy getDereferenceAliasesPolicy();
@@ -201,9 +111,9 @@
 
 
   /**
-   * Returns the filter that defines the conditions that must be
-   * fulfilled in order for an entry to be returned.
-   * 
+   * Returns the filter that defines the conditions that must be fulfilled in
+   * order for an entry to be returned.
+   *
    * @return The search filter.
    */
   Filter getFilter();
@@ -211,9 +121,9 @@
 
 
   /**
-   * Returns the distinguished name of the base entry relative to which
-   * the search is to be performed.
-   * 
+   * Returns the distinguished name of the base entry relative to which the
+   * search is to be performed.
+   *
    * @return The distinguished name of the base entry.
    */
   DN getName();
@@ -222,7 +132,7 @@
 
   /**
    * Returns the scope of the search.
-   * 
+   *
    * @return The search scope.
    */
   SearchScope getScope();
@@ -230,183 +140,114 @@
 
 
   /**
-   * Returns the size limit that should be used in order to restrict the
-   * maximum number of entries returned by the search.
+   * Returns the size limit that should be used in order to restrict the maximum
+   * number of entries returned by the search.
    * <p>
    * A value of zero (the default) in this field indicates that no
-   * client-requested size limit restrictions are in effect. Servers may
-   * also enforce a maximum number of entries to return.
-   * 
-   * @return The size limit that should be used in order to restrict the
-   *         maximum number of entries returned by the search.
+   * client-requested size limit restrictions are in effect. Servers may also
+   * enforce a maximum number of entries to return.
+   *
+   * @return The size limit that should be used in order to restrict the maximum
+   *         number of entries returned by the search.
    */
   int getSizeLimit();
 
 
 
   /**
-   * Returns the time limit that should be used in order to restrict the
-   * maximum time (in seconds) allowed for the search.
+   * Returns the time limit that should be used in order to restrict the maximum
+   * time (in seconds) allowed for the search.
    * <p>
    * A value of zero (the default) in this field indicates that no
-   * client-requested time limit restrictions are in effect for the
-   * search. Servers may also enforce a maximum time limit for the
-   * search.
-   * 
-   * @return The time limit that should be used in order to restrict the
-   *         maximum time (in seconds) allowed for the search.
+   * client-requested time limit restrictions are in effect for the search.
+   * Servers may also enforce a maximum time limit for the search.
+   *
+   * @return The time limit that should be used in order to restrict the maximum
+   *         time (in seconds) allowed for the search.
    */
   int getTimeLimit();
 
 
 
   /**
-   * Indicates whether or not this search request has a list of
-   * attributes to be included with each entry that matches the search
-   * criteria.
-   * 
-   * @return {@code true} if this search request has a list of
-   *         attributes to be included with each entry, otherwise
-   *         {@code false}.
-   */
-  boolean hasAttributes();
-
-
-
-  /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Indicates whether search results are to contain both attribute
-   * descriptions and values, or just attribute descriptions.
-   * 
-   * @return {@code true} if only attribute descriptions (and not
-   *         values) are to be returned, or {@code false} (the default)
-   *         if both attribute descriptions and values are to be
-   *         returned.
+   * Indicates whether search results are to contain both attribute descriptions
+   * and values, or just attribute descriptions.
+   *
+   * @return {@code true} if only attribute descriptions (and not values) are to
+   *         be returned, or {@code false} (the default) if both attribute
+   *         descriptions and values are to be returned.
    */
   boolean isTypesOnly();
 
 
 
   /**
-   * Removes the provided attribute name from the list of attributes to
-   * be included with each entry that matches the search criteria.
-   * Attributes that are sub-types of listed attributes are implicitly
-   * included.
-   * 
-   * @param attributeDescription
-   *          The name of the attribute to be removed.
-   * @return {@code true} if the attribute name was found in the list of
-   *         attributes.
-   * @throws UnsupportedOperationException
-   *           If this search request does not permit attribute names to
-   *           be removed.
-   * @throws NullPointerException
-   *           If {@code attributeDescription} was {@code null}.
-   */
-  boolean removeAttribute(String attributeDescription)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
    * Sets the alias dereferencing policy to be used during the search.
-   * 
+   *
    * @param policy
-   *          The alias dereferencing policy to be used during the
-   *          search.
+   *          The alias dereferencing policy to be used during the search.
    * @return This search request.
    * @throws UnsupportedOperationException
-   *           If this search request does not permit the alias
-   *           dereferencing policy to be set.
+   *           If this search request does not permit the alias dereferencing
+   *           policy to be set.
    * @throws NullPointerException
    *           If {@code policy} was {@code null}.
    */
-  SearchRequest setDereferenceAliasesPolicy(
-      DereferenceAliasesPolicy policy)
+  SearchRequest setDereferenceAliasesPolicy(DereferenceAliasesPolicy policy)
       throws UnsupportedOperationException, NullPointerException;
 
 
 
   /**
-   * Sets the filter that defines the conditions that must be fulfilled
-   * in order for an entry to be returned.
-   * 
+   * Sets the filter that defines the conditions that must be fulfilled in order
+   * for an entry to be returned.
+   *
    * @param filter
-   *          The filter that defines the conditions that must be
-   *          fulfilled in order for an entry to be returned.
+   *          The filter that defines the conditions that must be fulfilled in
+   *          order for an entry to be returned.
    * @return This search request.
    * @throws UnsupportedOperationException
-   *           If this search request does not permit the filter to be
-   *           set.
+   *           If this search request does not permit the filter to be set.
    * @throws NullPointerException
    *           If {@code filter} was {@code null}.
    */
-  SearchRequest setFilter(Filter filter)
-      throws UnsupportedOperationException, NullPointerException;
+  SearchRequest setFilter(Filter filter) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Sets the filter that defines the conditions that must be fulfilled
-   * in order for an entry to be returned.
-   * 
+   * Sets the filter that defines the conditions that must be fulfilled in order
+   * for an entry to be returned.
+   *
    * @param filter
-   *          The filter that defines the conditions that must be
-   *          fulfilled in order for an entry to be returned.
+   *          The filter that defines the conditions that must be fulfilled in
+   *          order for an entry to be returned.
    * @return This search request.
    * @throws UnsupportedOperationException
-   *           If this search request does not permit the filter to be
-   *           set.
+   *           If this search request does not permit the filter to be set.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code filter} is not a valid LDAP string
-   *           representation of a filter.
+   *           If {@code filter} is not a valid LDAP string representation of a
+   *           filter.
    * @throws NullPointerException
    *           If {@code filter} was {@code null}.
    */
-  SearchRequest setFilter(String filter)
-      throws UnsupportedOperationException,
+  SearchRequest setFilter(String filter) throws UnsupportedOperationException,
       LocalizedIllegalArgumentException, NullPointerException;
 
 
 
   /**
-   * Sets the distinguished name of the base entry relative to which the
-   * search is to be performed.
-   * 
+   * Sets the distinguished name of the base entry relative to which the search
+   * is to be performed.
+   *
    * @param dn
-   *          The distinguished name of the base entry relative to which
-   *          the search is to be performed.
+   *          The distinguished name of the base entry relative to which the
+   *          search is to be performed.
    * @return This search request.
    * @throws UnsupportedOperationException
-   *           If this search request does not permit the distinguished
-   *           name to be set.
+   *           If this search request does not permit the distinguished name to
+   *           be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
@@ -416,37 +257,34 @@
 
 
   /**
-   * Sets the distinguished name of the base entry relative to which the
-   * search is to be performed.
-   * 
+   * Sets the distinguished name of the base entry relative to which the search
+   * is to be performed.
+   *
    * @param dn
-   *          The distinguished name of the base entry relative to which
-   *          the search is to be performed.
+   *          The distinguished name of the base entry relative to which the
+   *          search is to be performed.
    * @return This search request.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} could not be decoded using the default
-   *           schema.
+   *           If {@code dn} could not be decoded using the default schema.
    * @throws UnsupportedOperationException
-   *           If this search request does not permit the distinguished
-   *           name to be set.
+   *           If this search request does not permit the distinguished name to
+   *           be set.
    * @throws NullPointerException
    *           If {@code dn} was {@code null}.
    */
-  SearchRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
+  SearchRequest setName(String dn) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException;
 
 
 
   /**
    * Sets the scope of the search.
-   * 
+   *
    * @param scope
    *          The scope of the search.
    * @return This search request.
    * @throws UnsupportedOperationException
-   *           If this search request does not permit the scope to be
-   *           set.
+   *           If this search request does not permit the scope to be set.
    * @throws NullPointerException
    *           If {@code scope} was {@code null}.
    */
@@ -456,67 +294,61 @@
 
 
   /**
-   * Sets the size limit that should be used in order to restrict the
-   * maximum number of entries returned by the search.
+   * Sets the size limit that should be used in order to restrict the maximum
+   * number of entries returned by the search.
    * <p>
    * A value of zero (the default) in this field indicates that no
-   * client-requested size limit restrictions are in effect. Servers may
-   * also enforce a maximum number of entries to return.
-   * 
+   * client-requested size limit restrictions are in effect. Servers may also
+   * enforce a maximum number of entries to return.
+   *
    * @param limit
-   *          The size limit that should be used in order to restrict
-   *          the maximum number of entries returned by the search.
+   *          The size limit that should be used in order to restrict the
+   *          maximum number of entries returned by the search.
    * @return This search request.
    * @throws UnsupportedOperationException
-   *           If this search request does not permit the size limit to
-   *           be set.
+   *           If this search request does not permit the size limit to be set.
    * @throws LocalizedIllegalArgumentException
    *           If {@code limit} was negative.
    */
-  SearchRequest setSizeLimit(int limit)
-      throws UnsupportedOperationException,
+  SearchRequest setSizeLimit(int limit) throws UnsupportedOperationException,
       LocalizedIllegalArgumentException;
 
 
 
   /**
-   * Sets the time limit that should be used in order to restrict the
-   * maximum time (in seconds) allowed for the search.
+   * Sets the time limit that should be used in order to restrict the maximum
+   * time (in seconds) allowed for the search.
    * <p>
    * A value of zero (the default) in this field indicates that no
-   * client-requested time limit restrictions are in effect for the
-   * search. Servers may also enforce a maximum time limit for the
-   * search.
-   * 
+   * client-requested time limit restrictions are in effect for the search.
+   * Servers may also enforce a maximum time limit for the search.
+   *
    * @param limit
-   *          The time limit that should be used in order to restrict
-   *          the maximum time (in seconds) allowed for the search.
+   *          The time limit that should be used in order to restrict the
+   *          maximum time (in seconds) allowed for the search.
    * @return This search request.
    * @throws UnsupportedOperationException
-   *           If this search request does not permit the time limit to
-   *           be set.
+   *           If this search request does not permit the time limit to be set.
    * @throws LocalizedIllegalArgumentException
    *           If {@code limit} was negative.
    */
-  SearchRequest setTimeLimit(int limit)
-      throws UnsupportedOperationException,
+  SearchRequest setTimeLimit(int limit) throws UnsupportedOperationException,
       LocalizedIllegalArgumentException;
 
 
 
   /**
-   * Specifies whether search results are to contain both attribute
-   * descriptions and values, or just attribute descriptions.
-   * 
+   * Specifies whether search results are to contain both attribute descriptions
+   * and values, or just attribute descriptions.
+   *
    * @param typesOnly
-   *          {@code true} if only attribute descriptions (and not
-   *          values) are to be returned, or {@code false} (the default)
-   *          if both attribute descriptions and values are to be
-   *          returned.
+   *          {@code true} if only attribute descriptions (and not values) are
+   *          to be returned, or {@code false} (the default) if both attribute
+   *          descriptions and values are to be returned.
    * @return This search request.
    * @throws UnsupportedOperationException
-   *           If this search request does not permit the types-only
-   *           parameter to be set.
+   *           If this search request does not permit the types-only parameter
+   *           to be set.
    */
   SearchRequest setTypesOnly(boolean typesOnly)
       throws UnsupportedOperationException;
diff --git a/sdk/src/org/opends/sdk/requests/SearchRequestImpl.java b/sdk/src/org/opends/sdk/requests/SearchRequestImpl.java
index 1199fd5..2337021 100644
--- a/sdk/src/org/opends/sdk/requests/SearchRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/SearchRequestImpl.java
@@ -29,7 +29,6 @@
 
 
 
-import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -42,8 +41,8 @@
 /**
  * Search request implementation.
  */
-final class SearchRequestImpl extends
-    AbstractRequestImpl<SearchRequest> implements SearchRequest
+final class SearchRequestImpl extends AbstractRequestImpl<SearchRequest>
+    implements SearchRequest
 {
 
   private final List<String> attributes = new LinkedList<String>();
@@ -65,25 +64,24 @@
 
 
   /**
-   * Creates a new search request using the provided distinguished name,
-   * scope, and filter, decoded using the default schema.
+   * Creates a new search request using the provided distinguished name, scope,
+   * and filter, decoded using the default schema.
    *
    * @param name
-   *          The distinguished name of the base entry relative to which
-   *          the search is to be performed.
+   *          The distinguished name of the base entry relative to which the
+   *          search is to be performed.
    * @param scope
    *          The scope of the search.
    * @param filter
-   *          The filter that defines the conditions that must be
-   *          fulfilled in order for an entry to be returned.
+   *          The filter that defines the conditions that must be fulfilled in
+   *          order for an entry to be returned.
    * @param attributeDescriptions
-   *          The names of the attributes to be included with each
-   *          entry.
+   *          The names of the attributes to be included with each entry.
    * @throws NullPointerException
-   *           If the {@code name}, {@code scope}, or {@code filter}
-   *           were {@code null}.
+   *           If the {@code name}, {@code scope}, or {@code filter} were
+   *           {@code null}.
    */
-  SearchRequestImpl(DN name, SearchScope scope, Filter filter)
+  SearchRequestImpl(final DN name, final SearchScope scope, final Filter filter)
       throws NullPointerException
   {
     this.name = name;
@@ -96,26 +94,10 @@
   /**
    * {@inheritDoc}
    */
-  public SearchRequest addAttribute(
-      Collection<String> attributeDescriptions)
-      throws NullPointerException
-  {
-    Validator.ensureNotNull(attributeDescriptions);
-
-    attributes.addAll(attributeDescriptions);
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public SearchRequest addAttribute(String attributeDescription)
+  public SearchRequest addAttribute(final String attributeDescription)
       throws NullPointerException
   {
     Validator.ensureNotNull(attributeDescription);
-
     attributes.add(attributeDescription);
     return this;
   }
@@ -125,35 +107,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchRequest addAttribute(String... attributeDescriptions)
-      throws NullPointerException
-  {
-    Validator.ensureNotNull((Object) attributeDescriptions);
-
-    for (final String attributeDescription : attributeDescriptions)
-    {
-      attributes.add(attributeDescription);
-    }
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public SearchRequest clearAttributes()
-  {
-    attributes.clear();
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Iterable<String> getAttributes()
+  public List<String> getAttributes()
   {
     return attributes;
   }
@@ -223,16 +177,6 @@
   /**
    * {@inheritDoc}
    */
-  public boolean hasAttributes()
-  {
-    return !attributes.isEmpty();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
   public boolean isTypesOnly()
   {
     return typesOnly;
@@ -243,21 +187,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean removeAttribute(String attributeDescription)
-      throws NullPointerException
-  {
-    Validator.ensureNotNull(attributeDescription);
-
-    return attributes.remove(attributeDescription);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
   public SearchRequest setDereferenceAliasesPolicy(
-      DereferenceAliasesPolicy policy) throws NullPointerException
+      final DereferenceAliasesPolicy policy) throws NullPointerException
   {
     Validator.ensureNotNull(policy);
 
@@ -270,7 +201,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchRequest setFilter(Filter filter)
+  public SearchRequest setFilter(final Filter filter)
       throws NullPointerException
   {
     Validator.ensureNotNull(filter);
@@ -284,7 +215,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchRequest setFilter(String filter)
+  public SearchRequest setFilter(final String filter)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     this.filter = Filter.valueOf(filter);
@@ -296,7 +227,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchRequest setName(DN dn) throws NullPointerException
+  public SearchRequest setName(final DN dn) throws NullPointerException
   {
     Validator.ensureNotNull(dn);
 
@@ -309,7 +240,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchRequest setName(String dn)
+  public SearchRequest setName(final String dn)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(dn);
@@ -323,7 +254,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchRequest setScope(SearchScope scope)
+  public SearchRequest setScope(final SearchScope scope)
       throws NullPointerException
   {
     Validator.ensureNotNull(scope);
@@ -337,7 +268,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchRequest setSizeLimit(int limit)
+  public SearchRequest setSizeLimit(final int limit)
       throws LocalizedIllegalArgumentException
   {
     // FIXME: I18N error message.
@@ -352,7 +283,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchRequest setTimeLimit(int limit)
+  public SearchRequest setTimeLimit(final int limit)
       throws LocalizedIllegalArgumentException
   {
     // FIXME: I18N error message.
@@ -367,7 +298,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchRequest setTypesOnly(boolean typesOnly)
+  public SearchRequest setTypesOnly(final boolean typesOnly)
   {
     this.typesOnly = typesOnly;
     return this;
@@ -406,6 +337,7 @@
 
 
 
+  @Override
   SearchRequest getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/requests/SimpleBindRequest.java b/sdk/src/org/opends/sdk/requests/SimpleBindRequest.java
index 47b4072..7109836 100644
--- a/sdk/src/org/opends/sdk/requests/SimpleBindRequest.java
+++ b/sdk/src/org/opends/sdk/requests/SimpleBindRequest.java
@@ -29,11 +29,14 @@
 
 
 
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-import org.opends.sdk.LocalizedIllegalArgumentException;
-import org.opends.sdk.controls.Control;
+import java.util.List;
 
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.ErrorResultException;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
@@ -41,26 +44,18 @@
  * The simple authentication method of the Bind Operation provides three
  * authentication mechanisms:
  * <ul>
- * <li>An anonymous authentication mechanism, in which both the name
- * (the bind DN) and password are zero length.
- * <li>An unauthenticated authentication mechanism using credentials
- * consisting of a name (the bind DN) and a zero length password.
- * <li>A name/password authentication mechanism using credentials
- * consisting of a name (the bind DN) and a password.
+ * <li>An anonymous authentication mechanism, in which both the name and
+ * password are zero length.
+ * <li>An unauthenticated authentication mechanism using credentials consisting
+ * of a name and a zero length password.
+ * <li>A name/password authentication mechanism using credentials consisting of
+ * a name and a password.
  * </ul>
  */
 public interface SimpleBindRequest extends BindRequest
 {
   /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
   SimpleBindRequest addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -68,163 +63,105 @@
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * {@inheritDoc}
    */
-  SimpleBindRequest clearControls()
-      throws UnsupportedOperationException;
+  BindClient createBindClient(String serverName) throws ErrorResultException;
 
 
 
   /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * Returns the authentication mechanism identifier for this simple bind
+   * request as defined by the LDAP protocol, which is always {@code 0x80}.
+   *
+   * @return The authentication mechanism identifier.
    */
-  Control getControl(String oid) throws NullPointerException;
-
-
-
-  /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
-   */
-  Iterable<Control> getControls();
+  byte getAuthenticationType();
 
 
 
   /**
    * {@inheritDoc}
    */
-  DN getName();
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns the password of the Directory object that the client wishes
-   * to bind as. The password may be empty (but never {@code null}) when
-   * used for of anonymous or unauthenticated binds.
-   * 
-   * @return The password of the Directory object that the client wishes
-   *         to bind as.
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getName();
+
+
+
+  /**
+   * Returns the password of the Directory object that the client wishes to bind
+   * as. The password may be empty (but never {@code null}) when used for of
+   * anonymous or unauthenticated binds.
+   *
+   * @return The password of the Directory object that the client wishes to bind
+   *         as.
    */
   ByteString getPassword();
 
 
 
   /**
-   * Returns the password of the Directory object that the client wishes
-   * to bind as decoded as a UTF-8 string. The password may be empty
-   * (but never {@code null}) when used for of anonymous or
-   * unauthenticated binds.
-   * 
-   * @return The password of the Directory object that the client wishes
-   *         to bind as decoded as a UTF-8 string.
+   * Returns the password of the Directory object that the client wishes to bind
+   * as decoded as a UTF-8 string. The password may be empty (but never {@code
+   * null}) when used for of anonymous or unauthenticated binds.
+   *
+   * @return The password of the Directory object that the client wishes to bind
+   *         as decoded as a UTF-8 string.
    */
   String getPasswordAsString();
 
 
 
   /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Sets the distinguished name of the Directory object that the client
-   * wishes to bind as. The distinguished name may be empty (but never
-   * {@code null} when used for of anonymous binds, or when using SASL
-   * authentication. The server shall not dereference any aliases in
-   * locating the named object.
-   * 
-   * @param dn
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as.
+   * Sets the name of the Directory object that the client wishes to bind as.
+   * The name may be empty (but never {@code null} when used for of anonymous
+   * binds, or when using SASL authentication. The server shall not dereference
+   * any aliases in locating the named object.
+   * <p>
+   * The LDAP protocol defines the Bind name to be a distinguished name, however
+   * some LDAP implementations have relaxed this constraint and allow other
+   * identities to be used, such as the user's email address.
+   *
+   * @param name
+   *          The name of the Directory object that the client wishes to bind
+   *          as.
    * @return This bind request.
    * @throws UnsupportedOperationException
-   *           If this bind request does not permit the distinguished
-   *           name to be set.
+   *           If this bind request does not permit the distinguished name to be
+   *           set.
    * @throws NullPointerException
-   *           If {@code dn} was {@code null}.
+   *           If {@code name} was {@code null}.
    */
-  SimpleBindRequest setName(DN dn)
-      throws UnsupportedOperationException, NullPointerException;
+  SimpleBindRequest setName(String name) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Sets the distinguished name of the Directory object that the client
-   * wishes to bind as. The distinguished name may be empty (but never
-   * {@code null} when used for of anonymous binds, or when using SASL
-   * authentication. The server shall not dereference any aliases in
-   * locating the named object.
-   * 
-   * @param dn
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as.
-   * @return This bind request.
-   * @throws LocalizedIllegalArgumentException
-   *           If {@code dn} could not be decoded using the default
-   *           schema.
-   * @throws UnsupportedOperationException
-   *           If this bind request does not permit the distinguished
-   *           name to be set.
-   * @throws NullPointerException
-   *           If {@code dn} was {@code null}.
-   */
-  SimpleBindRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Sets the password of the Directory object that the client wishes to
-   * bind as. The password may be empty (but never {@code null}) when
-   * used for of anonymous or unauthenticated binds.
-   * 
+   * Sets the password of the Directory object that the client wishes to bind
+   * as. The password may be empty (but never {@code null}) when used for of
+   * anonymous or unauthenticated binds.
+   *
    * @param password
-   *          The password of the Directory object that the client
-   *          wishes to bind as, which may be empty.
+   *          The password of the Directory object that the client wishes to
+   *          bind as, which may be empty.
    * @return This simple bind request.
    * @throws UnsupportedOperationException
-   *           If this simple bind request does not permit the password
-   *           to be set.
+   *           If this simple bind request does not permit the password to be
+   *           set.
    * @throws NullPointerException
    *           If {@code password} was {@code null}.
    */
@@ -234,18 +171,18 @@
 
 
   /**
-   * Sets the password of the Directory object that the client wishes to
-   * bind as. The password will be converted to a UTF-8 octet string.
-   * The password may be empty (but never {@code null}) when used for of
-   * anonymous or unauthenticated binds.
-   * 
+   * Sets the password of the Directory object that the client wishes to bind
+   * as. The password will be converted to a UTF-8 octet string. The password
+   * may be empty (but never {@code null}) when used for of anonymous or
+   * unauthenticated binds.
+   *
    * @param password
-   *          The password of the Directory object that the client
-   *          wishes to bind as, which may be empty.
+   *          The password of the Directory object that the client wishes to
+   *          bind as, which may be empty.
    * @return This simple bind request.
    * @throws UnsupportedOperationException
-   *           If this simple bind request does not permit the password
-   *           to be set.
+   *           If this simple bind request does not permit the password to be
+   *           set.
    * @throws NullPointerException
    *           If {@code password} was {@code null}.
    */
diff --git a/sdk/src/org/opends/sdk/requests/SimpleBindRequestImpl.java b/sdk/src/org/opends/sdk/requests/SimpleBindRequestImpl.java
index 6b5aa32..e717430 100644
--- a/sdk/src/org/opends/sdk/requests/SimpleBindRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/SimpleBindRequestImpl.java
@@ -29,9 +29,10 @@
 
 
 
+import static com.sun.opends.sdk.ldap.LDAPConstants.TYPE_AUTHENTICATION_SIMPLE;
+
 import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-import org.opends.sdk.LocalizedIllegalArgumentException;
+import org.opends.sdk.ErrorResultException;
 
 import com.sun.opends.sdk.util.Validator;
 
@@ -45,25 +46,25 @@
 {
   private ByteString password = ByteString.empty();
 
-  private DN name = DN.rootDN();
+  private String name = "".intern();
 
 
 
   /**
-   * Creates a new simple bind request having the provided name and
-   * password suitable for name/password authentication.
-   * 
+   * Creates a new simple bind request having the provided name and password
+   * suitable for name/password authentication.
+   *
    * @param name
-   *          The distinguished name of the Directory object that the
-   *          client wishes to bind as, which may be empty.
+   *          The name of the Directory object that the client wishes to bind
+   *          as, which may be empty.
    * @param password
-   *          The password of the Directory object that the client
-   *          wishes to bind as, which may be empty indicating that an
-   *          unauthenticated bind is to be performed.
+   *          The password of the Directory object that the client wishes to
+   *          bind as, which may be empty indicating that an unauthenticated
+   *          bind is to be performed.
    * @throws NullPointerException
    *           If {@code name} or {@code password} was {@code null}.
    */
-  SimpleBindRequestImpl(DN name, ByteString password)
+  SimpleBindRequestImpl(final String name, final ByteString password)
       throws NullPointerException
   {
     this.name = name;
@@ -72,10 +73,26 @@
 
 
 
+  public BindClient createBindClient(final String serverName)
+      throws ErrorResultException
+  {
+    return new BindClientImpl(this).setNextAuthenticationValue(password);
+  }
+
+
+
+  public byte getAuthenticationType()
+  {
+    return TYPE_AUTHENTICATION_SIMPLE;
+  }
+
+
+
   /**
    * {@inheritDoc}
    */
-  public DN getName()
+  @Override
+  public String getName()
   {
     return name;
   }
@@ -105,11 +122,11 @@
   /**
    * {@inheritDoc}
    */
-  public SimpleBindRequest setName(DN dn)
+  public SimpleBindRequest setName(final String name)
       throws UnsupportedOperationException, NullPointerException
   {
-    Validator.ensureNotNull(dn);
-    this.name = dn;
+    Validator.ensureNotNull(name);
+    this.name = name;
     return this;
   }
 
@@ -118,21 +135,7 @@
   /**
    * {@inheritDoc}
    */
-  public SimpleBindRequest setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
-  {
-    Validator.ensureNotNull(dn);
-    this.name = DN.valueOf(dn);
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public SimpleBindRequest setPassword(ByteString password)
+  public SimpleBindRequest setPassword(final ByteString password)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(password);
@@ -145,7 +148,7 @@
   /**
    * {@inheritDoc}
    */
-  public SimpleBindRequest setPassword(String password)
+  public SimpleBindRequest setPassword(final String password)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(password);
diff --git a/sdk/src/org/opends/sdk/requests/StartTLSExtendedRequest.java b/sdk/src/org/opends/sdk/requests/StartTLSExtendedRequest.java
new file mode 100644
index 0000000..33d8249
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/StartTLSExtendedRequest.java
@@ -0,0 +1,141 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import javax.net.ssl.SSLContext;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+
+
+
+/**
+ * The start TLS extended request as defined in RFC 4511. The Start Transport
+ * Layer Security (StartTLS) operation's purpose is to initiate installation of
+ * a TLS layer.
+ *
+ * @see <a href="http://tools.ietf.org/html/rfc4511">RFC 4511 - Lightweight
+ *      Directory Access Protocol (LDAP): The Protocol </a>
+ */
+public interface StartTLSExtendedRequest extends
+    ExtendedRequest<ExtendedResult>
+{
+
+  /**
+   * The OID for the start TLS extended operation request.
+   */
+  public static final String OID = "1.3.6.1.4.1.1466.20037";
+
+  /**
+   * A decoder which can be used to decode start TLS extended operation
+   * requests.
+   */
+  public static final ExtendedRequestDecoder<StartTLSExtendedRequest,
+                                             ExtendedResult> DECODER =
+    new StartTLSExtendedRequestImpl.RequestDecoder();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  StartTLSExtendedRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getOID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ExtendedResultDecoder<ExtendedResult> getResultDecoder();
+
+
+
+  /**
+   * Returns the SSLContext that should be used when installing the TLS layer.
+   *
+   * @return The SSLContext that should be used when installing the TLS layer.
+   */
+  SSLContext getSSLContext();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ByteString getValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  boolean hasValue();
+
+
+
+  /**
+   * Sets the SSLContext that should be used when installing the TLS layer.
+   *
+   * @param sslContext
+   *          The SSLContext that should be used when installing the TLS layer.
+   * @return This startTLS request.
+   */
+  StartTLSExtendedRequest setSSLContext(SSLContext sslContext);
+}
diff --git a/sdk/src/org/opends/sdk/requests/StartTLSExtendedRequestImpl.java b/sdk/src/org/opends/sdk/requests/StartTLSExtendedRequestImpl.java
new file mode 100644
index 0000000..49dd4f6
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/StartTLSExtendedRequestImpl.java
@@ -0,0 +1,203 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import javax.net.ssl.SSLContext;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.ResultCode;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+import org.opends.sdk.responses.GenericExtendedResult;
+import org.opends.sdk.responses.Responses;
+
+import com.sun.opends.sdk.util.Validator;
+
+
+
+/**
+ * Start TLS extended request implementation.
+ */
+final class StartTLSExtendedRequestImpl extends
+    AbstractExtendedRequest<StartTLSExtendedRequest, ExtendedResult> implements
+    StartTLSExtendedRequest
+{
+  static final class RequestDecoder implements
+      ExtendedRequestDecoder<StartTLSExtendedRequest, ExtendedResult>
+  {
+
+    public StartTLSExtendedRequest decodeExtendedRequest(
+        final ExtendedRequest<?> request, final DecodeOptions options)
+        throws DecodeException
+    {
+      // TODO: Check the OID and that the value is not present.
+      final StartTLSExtendedRequest newRequest = new StartTLSExtendedRequestImpl();
+      for (final Control control : request.getControls())
+      {
+        newRequest.addControl(control);
+      }
+      return newRequest;
+    }
+  }
+
+
+
+  private static final class ResultDecoder implements
+      ExtendedResultDecoder<ExtendedResult>
+  {
+    public GenericExtendedResult adaptExtendedErrorResult(
+        final ResultCode resultCode, final String matchedDN,
+        final String diagnosticMessage)
+    {
+      return Responses.newGenericExtendedResult(resultCode).setMatchedDN(
+          matchedDN).setDiagnosticMessage(diagnosticMessage);
+    }
+
+
+
+    public ExtendedResult decodeExtendedResult(final ExtendedResult result,
+        final DecodeOptions options) throws DecodeException
+    {
+      // TODO: Should we check oid is NOT null and matches but
+      // value is null?
+      return result;
+    }
+  }
+
+
+
+  private SSLContext sslContext;
+
+  // No need to expose this.
+  private static final ExtendedResultDecoder<ExtendedResult> RESULT_DECODER = new ResultDecoder();
+
+
+
+  StartTLSExtendedRequestImpl(final SSLContext sslContext)
+  {
+    Validator.ensureNotNull(sslContext);
+    this.sslContext = sslContext;
+  }
+
+
+
+  // Prevent instantiation.
+  private StartTLSExtendedRequestImpl()
+  {
+    // Nothing to do.
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ExtendedResultDecoder<ExtendedResult> getResultDecoder()
+  {
+    return RESULT_DECODER;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public SSLContext getSSLContext()
+  {
+    return sslContext;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public StartTLSExtendedRequest setSSLContext(final SSLContext sslContext)
+  {
+    Validator.ensureNotNull(sslContext);
+    this.sslContext = sslContext;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("StartTLSExtendedRequest(requestName=");
+    builder.append(getOID());
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/requests/UnbindRequest.java b/sdk/src/org/opends/sdk/requests/UnbindRequest.java
index 2fc1739..861e260 100644
--- a/sdk/src/org/opends/sdk/requests/UnbindRequest.java
+++ b/sdk/src/org/opends/sdk/requests/UnbindRequest.java
@@ -29,7 +29,12 @@
 
 
 
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
@@ -39,15 +44,7 @@
 public interface UnbindRequest extends Request
 {
   /**
-   * Adds the provided control to this request.
-   * 
-   * @param control
-   *          The control to be added to this request.
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be added.
-   * @throws NullPointerException
-   *           If {@code control} was {@code null}.
+   * {@inheritDoc}
    */
   UnbindRequest addControl(Control control)
       throws UnsupportedOperationException, NullPointerException;
@@ -55,65 +52,15 @@
 
 
   /**
-   * Removes all the controls included with this request.
-   * 
-   * @return This request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
+   * {@inheritDoc}
    */
-  UnbindRequest clearControls() throws UnsupportedOperationException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
-   *         with this request.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
-
-
-
-  /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this request. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this request.
-   * 
-   * @return An {@code Iterable} containing the controls.
-   */
-  Iterable<Control> getControls();
-
-
-
-  /**
-   * Indicates whether or not this request has any controls.
-   * 
-   * @return {@code true} if this request has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Removes the first control contained in this request having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this request.
-   * @throws UnsupportedOperationException
-   *           If this request does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  List<Control> getControls();
 }
diff --git a/sdk/src/org/opends/sdk/requests/UnbindRequestImpl.java b/sdk/src/org/opends/sdk/requests/UnbindRequestImpl.java
index 72a5485..87c8eef 100644
--- a/sdk/src/org/opends/sdk/requests/UnbindRequestImpl.java
+++ b/sdk/src/org/opends/sdk/requests/UnbindRequestImpl.java
@@ -27,11 +27,13 @@
 
 package org.opends.sdk.requests;
 
+
+
 /**
  * Unbind request implementation.
  */
-final class UnbindRequestImpl extends
-    AbstractRequestImpl<UnbindRequest> implements UnbindRequest
+final class UnbindRequestImpl extends AbstractRequestImpl<UnbindRequest>
+    implements UnbindRequest
 {
 
   /**
@@ -59,6 +61,7 @@
 
 
 
+  @Override
   UnbindRequest getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequest.java b/sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequest.java
new file mode 100644
index 0000000..f03262c
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequest.java
@@ -0,0 +1,133 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+import org.opends.sdk.responses.WhoAmIExtendedResult;
+
+
+
+/**
+ *The who am I extended request as defined in RFC 4532. This operation allows
+ * clients to obtain the primary authorization identity, in its primary form,
+ * that the server has associated with the user or application entity.
+ * <p>
+ * This operation may preferable to the Authorization Identity Controls
+ * mechanism defined in RFC 3829, which uses Bind request and response controls
+ * to request and return the authorization identity. Bind controls are not
+ * protected by security layers established by the Bind operation that includes
+ * them. While it is possible to establish security layers using StartTLS prior
+ * to the Bind operation, it is often desirable to use security layers
+ * established by the Bind operation. An extended operation sent after a Bind
+ * operation is protected by the security layers established by the Bind
+ * operation.
+ *
+ * @see WhoAmIExtendedResult
+ * @see org.opends.sdk.controls.AuthorizationIdentityRequestControl
+ * @see <a href="http://tools.ietf.org/html/rfc4532">RFC 4532 - Lightweight
+ *      Directory Access Protocol (LDAP) "Who am I?" Operation </a>
+ * @see <a href="http://tools.ietf.org/html/rfc3829">RFC 3829 - Lightweight
+ *      Directory Access Protocol (LDAP) Authorization Identity Request and
+ *      Response Controls </a>
+ */
+public interface WhoAmIExtendedRequest extends
+    ExtendedRequest<WhoAmIExtendedResult>
+{
+
+  /**
+   * The OID for the who am I extended operation request.
+   */
+  public static final String OID = "1.3.6.1.4.1.4203.1.11.3";
+
+  /**
+   * A decoder which can be used to decode who am I extended operation requests.
+   */
+  public static final ExtendedRequestDecoder<WhoAmIExtendedRequest,
+                                             WhoAmIExtendedResult> DECODER =
+    new WhoAmIExtendedRequestImpl.RequestDecoder();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  WhoAmIExtendedRequest addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getOID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ExtendedResultDecoder<WhoAmIExtendedResult> getResultDecoder();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ByteString getValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  boolean hasValue();
+}
diff --git a/sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequestImpl.java b/sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequestImpl.java
new file mode 100644
index 0000000..bc91781
--- /dev/null
+++ b/sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequestImpl.java
@@ -0,0 +1,194 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.*;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.responses.ExtendedResult;
+import org.opends.sdk.responses.ExtendedResultDecoder;
+import org.opends.sdk.responses.Responses;
+import org.opends.sdk.responses.WhoAmIExtendedResult;
+
+
+
+/**
+ * Who Am I extended request implementation.
+ */
+final class WhoAmIExtendedRequestImpl extends
+    AbstractExtendedRequest<WhoAmIExtendedRequest, WhoAmIExtendedResult>
+    implements WhoAmIExtendedRequest
+{
+
+  static final class RequestDecoder implements
+      ExtendedRequestDecoder<WhoAmIExtendedRequest, WhoAmIExtendedResult>
+  {
+
+    public WhoAmIExtendedRequest decodeExtendedRequest(
+        final ExtendedRequest<?> request, final DecodeOptions options)
+        throws DecodeException
+    {
+      // TODO: Check the OID and that the value is not present.
+      final WhoAmIExtendedRequest newRequest = new WhoAmIExtendedRequestImpl();
+      for (final Control control : request.getControls())
+      {
+        newRequest.addControl(control);
+      }
+      return newRequest;
+    }
+  }
+
+
+
+  private static final class ResultDecoder implements
+      ExtendedResultDecoder<WhoAmIExtendedResult>
+  {
+    public WhoAmIExtendedResult adaptExtendedErrorResult(
+        final ResultCode resultCode, final String matchedDN,
+        final String diagnosticMessage)
+    {
+      return Responses.newWhoAmIExtendedResult(resultCode).setMatchedDN(
+          matchedDN).setDiagnosticMessage(diagnosticMessage);
+    }
+
+
+
+    public WhoAmIExtendedResult decodeExtendedResult(
+        final ExtendedResult result, final DecodeOptions options)
+        throws DecodeException
+    {
+      if (result instanceof WhoAmIExtendedResult)
+      {
+        return (WhoAmIExtendedResult) result;
+      }
+      else
+      {
+        final WhoAmIExtendedResult newResult = Responses
+            .newWhoAmIExtendedResult(result.getResultCode()).setMatchedDN(
+                result.getMatchedDN()).setDiagnosticMessage(
+                result.getDiagnosticMessage());
+
+        final ByteString responseValue = result.getValue();
+        if (responseValue != null)
+        {
+          try
+          {
+            newResult.setAuthorizationID(responseValue.toString());
+          }
+          catch (final LocalizedIllegalArgumentException e)
+          {
+            throw DecodeException.error(e.getMessageObject());
+          }
+        }
+
+        for (final Control control : result.getControls())
+        {
+          newResult.addControl(control);
+        }
+
+        return newResult;
+      }
+    }
+  }
+
+
+
+  // No need to expose this.
+  private static final ExtendedResultDecoder<WhoAmIExtendedResult>
+    RESULT_DECODER = new ResultDecoder();
+
+
+
+  // Prevent instantiation.
+  WhoAmIExtendedRequestImpl()
+  {
+    // Nothing to do.
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    return OID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ExtendedResultDecoder<WhoAmIExtendedResult> getResultDecoder()
+  {
+    return RESULT_DECODER;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return false;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("WhoAmIExtendedRequest(requestName=");
+    builder.append(getOID());
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/requests/package-info.java b/sdk/src/org/opends/sdk/requests/package-info.java
index 0e84921..cf35739 100755
--- a/sdk/src/org/opends/sdk/requests/package-info.java
+++ b/sdk/src/org/opends/sdk/requests/package-info.java
@@ -29,3 +29,6 @@
  * Classes and interfaces for core LDAP requests.
  */
 package org.opends.sdk.requests;
+
+
+
diff --git a/sdk/src/org/opends/sdk/responses/AbstractExtendedResult.java b/sdk/src/org/opends/sdk/responses/AbstractExtendedResult.java
index dde1dd1..339ac92 100644
--- a/sdk/src/org/opends/sdk/responses/AbstractExtendedResult.java
+++ b/sdk/src/org/opends/sdk/responses/AbstractExtendedResult.java
@@ -32,28 +32,30 @@
 import org.opends.sdk.ByteString;
 import org.opends.sdk.ResultCode;
 
+import com.sun.opends.sdk.util.StaticUtils;
+
 
 
 /**
- * An abstract Extended result which can be used as the basis for
- * implementing new Extended operations.
- * 
+ * An abstract Extended result which can be used as the basis for implementing
+ * new Extended operations.
+ *
  * @param <S>
  *          The type of Extended result.
  */
-public abstract class AbstractExtendedResult<S extends ExtendedResult>
-    extends AbstractResultImpl<S> implements ExtendedResult
+public abstract class AbstractExtendedResult<S extends ExtendedResult> extends
+    AbstractResultImpl<S> implements ExtendedResult
 {
 
   /**
    * Creates a new extended result using the provided result code.
-   * 
+   *
    * @param resultCode
    *          The result code.
    * @throws NullPointerException
    *           If {@code resultCode} was {@code null}.
    */
-  protected AbstractExtendedResult(ResultCode resultCode)
+  protected AbstractExtendedResult(final ResultCode resultCode)
       throws NullPointerException
   {
     super(resultCode);
@@ -64,20 +66,28 @@
   /**
    * {@inheritDoc}
    */
-  public abstract String getResponseName();
+  public abstract String getOID();
 
 
 
   /**
    * {@inheritDoc}
    */
-  public abstract ByteString getResponseValue();
+  public abstract ByteString getValue();
 
 
 
   /**
    * {@inheritDoc}
    */
+  public abstract boolean hasValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
   public String toString()
   {
     final StringBuilder builder = new StringBuilder();
@@ -90,10 +100,12 @@
     builder.append(", referrals=");
     builder.append(getReferralURIs());
     builder.append(", responseName=");
-    builder.append(getResponseName() == null ? "" : getResponseName());
-    builder.append(", responseValue=");
-    final ByteString value = getResponseValue();
-    builder.append(value == null ? ByteString.empty() : value);
+    builder.append(getOID() == null ? "" : getOID());
+    if (hasValue())
+    {
+      builder.append(", responseValue=");
+      StaticUtils.toHexPlusAscii(getValue(), builder, 4);
+    }
     builder.append(", controls=");
     builder.append(getControls());
     builder.append(")");
@@ -105,6 +117,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   @SuppressWarnings("unchecked")
   final S getThis()
   {
diff --git a/sdk/src/org/opends/sdk/responses/AbstractIntermediateResponse.java b/sdk/src/org/opends/sdk/responses/AbstractIntermediateResponse.java
index ff15a22..fc6333a 100644
--- a/sdk/src/org/opends/sdk/responses/AbstractIntermediateResponse.java
+++ b/sdk/src/org/opends/sdk/responses/AbstractIntermediateResponse.java
@@ -31,12 +31,14 @@
 
 import org.opends.sdk.ByteString;
 
+import com.sun.opends.sdk.util.StaticUtils;
+
 
 
 /**
  * An abstract Intermediate response which can be used as the basis for
  * implementing new Intermediate responses.
- * 
+ *
  * @param <S>
  *          The type of Intermediate response.
  */
@@ -57,28 +59,38 @@
   /**
    * {@inheritDoc}
    */
-  public abstract String getResponseName();
+  public abstract String getOID();
 
 
 
   /**
    * {@inheritDoc}
    */
-  public abstract ByteString getResponseValue();
+  public abstract ByteString getValue();
 
 
 
   /**
    * {@inheritDoc}
    */
+  public abstract boolean hasValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
   public String toString()
   {
     final StringBuilder builder = new StringBuilder();
     builder.append("IntermediateResponse(responseName=");
-    builder.append(getResponseName() == null ? "" : getResponseName());
-    builder.append(", responseValue=");
-    final ByteString value = getResponseValue();
-    builder.append(value == null ? ByteString.empty() : value);
+    builder.append(getOID() == null ? "" : getOID());
+    if (hasValue())
+    {
+      builder.append(", responseValue=");
+      StaticUtils.toHexPlusAscii(getValue(), builder, 4);
+    }
     builder.append(", controls=");
     builder.append(getControls());
     builder.append(")");
@@ -90,6 +102,7 @@
   /**
    * {@inheritDoc}
    */
+  @Override
   @SuppressWarnings("unchecked")
   final S getThis()
   {
diff --git a/sdk/src/org/opends/sdk/responses/AbstractResponseImpl.java b/sdk/src/org/opends/sdk/responses/AbstractResponseImpl.java
index 669cddd..2e8ee49 100644
--- a/sdk/src/org/opends/sdk/responses/AbstractResponseImpl.java
+++ b/sdk/src/org/opends/sdk/responses/AbstractResponseImpl.java
@@ -29,11 +29,13 @@
 
 
 
-import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 import com.sun.opends.sdk.util.Validator;
 
@@ -41,12 +43,11 @@
 
 /**
  * Modifiable response implementation.
- * 
+ *
  * @param <S>
  *          The type of response.
  */
-abstract class AbstractResponseImpl<S extends Response> implements
-    Response
+abstract class AbstractResponseImpl<S extends Response> implements Response
 {
   private final List<Control> controls = new LinkedList<Control>();
 
@@ -65,8 +66,7 @@
   /**
    * {@inheritDoc}
    */
-  public final S addControl(Control control)
-      throws NullPointerException
+  public final S addControl(final Control control) throws NullPointerException
   {
     Validator.ensureNotNull(control);
     controls.add(control);
@@ -78,20 +78,11 @@
   /**
    * {@inheritDoc}
    */
-  public final S clearControls()
+  public final <C extends Control> C getControl(
+      final ControlDecoder<C> decoder, final DecodeOptions options)
+      throws NullPointerException, DecodeException
   {
-    controls.clear();
-    return getThis();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final Control getControl(String oid)
-  {
-    Validator.ensureNotNull(oid);
+    Validator.ensureNotNull(decoder, options);
 
     // Avoid creating an iterator if possible.
     if (controls.isEmpty())
@@ -101,9 +92,9 @@
 
     for (final Control control : controls)
     {
-      if (control.getOID().equals(oid))
+      if (control.getOID().equals(decoder.getOID()))
       {
-        return control;
+        return decoder.decodeControl(control, options);
       }
     }
 
@@ -115,53 +106,14 @@
   /**
    * {@inheritDoc}
    */
-  public final Iterable<Control> getControls()
+  public final List<Control> getControls()
   {
     return controls;
   }
 
 
 
-  /**
-   * {@inheritDoc}
-   */
-  public final boolean hasControls()
-  {
-    return !controls.isEmpty();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final Control removeControl(String oid)
-      throws NullPointerException
-  {
-    Validator.ensureNotNull(oid);
-
-    // Avoid creating an iterator if possible.
-    if (controls.isEmpty())
-    {
-      return null;
-    }
-
-    final Iterator<Control> iterator = controls.iterator();
-    while (iterator.hasNext())
-    {
-      final Control control = iterator.next();
-      if (control.getOID().equals(oid))
-      {
-        iterator.remove();
-        return control;
-      }
-    }
-
-    return null;
-  }
-
-
-
+  @Override
   public abstract String toString();
 
 
diff --git a/sdk/src/org/opends/sdk/responses/AbstractResultImpl.java b/sdk/src/org/opends/sdk/responses/AbstractResultImpl.java
index b47259b..8cdc53a 100644
--- a/sdk/src/org/opends/sdk/responses/AbstractResultImpl.java
+++ b/sdk/src/org/opends/sdk/responses/AbstractResultImpl.java
@@ -40,7 +40,7 @@
 
 /**
  * Modifiable result implementation.
- * 
+ *
  * @param <S>
  *          The type of result.
  */
@@ -61,15 +61,15 @@
 
 
   /**
-   * Creates a new modifiable result implementation using the provided
-   * result code.
-   * 
+   * Creates a new modifiable result implementation using the provided result
+   * code.
+   *
    * @param resultCode
    *          The result code.
    * @throws NullPointerException
    *           If {@code resultCode} was {@code null}.
    */
-  AbstractResultImpl(ResultCode resultCode) throws NullPointerException
+  AbstractResultImpl(final ResultCode resultCode) throws NullPointerException
   {
     this.resultCode = resultCode;
   }
@@ -79,7 +79,7 @@
   /**
    * {@inheritDoc}
    */
-  public final S addReferralURI(String uri) throws NullPointerException
+  public final S addReferralURI(final String uri) throws NullPointerException
   {
     Validator.ensureNotNull(uri);
 
@@ -92,17 +92,6 @@
   /**
    * {@inheritDoc}
    */
-  public final S clearReferralURIs()
-  {
-    referralURIs.clear();
-    return getThis();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
   public final Throwable getCause()
   {
     return cause;
@@ -133,7 +122,7 @@
   /**
    * {@inheritDoc}
    */
-  public final Iterable<String> getReferralURIs()
+  public final List<String> getReferralURIs()
   {
     return referralURIs;
   }
@@ -153,16 +142,6 @@
   /**
    * {@inheritDoc}
    */
-  public final boolean hasReferralURIs()
-  {
-    return !referralURIs.isEmpty();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
   public final boolean isReferral()
   {
     final ResultCode code = getResultCode();
@@ -185,7 +164,7 @@
   /**
    * {@inheritDoc}
    */
-  public final S setCause(Throwable cause)
+  public final S setCause(final Throwable cause)
   {
     this.cause = cause;
     return getThis();
@@ -196,7 +175,7 @@
   /**
    * {@inheritDoc}
    */
-  public final S setDiagnosticMessage(String message)
+  public final S setDiagnosticMessage(final String message)
   {
     if (message == null)
     {
@@ -215,7 +194,7 @@
   /**
    * {@inheritDoc}
    */
-  public final S setMatchedDN(String dn)
+  public final S setMatchedDN(final String dn)
   {
     if (dn == null)
     {
@@ -234,7 +213,7 @@
   /**
    * {@inheritDoc}
    */
-  public final S setResultCode(ResultCode resultCode)
+  public final S setResultCode(final ResultCode resultCode)
       throws NullPointerException
   {
     Validator.ensureNotNull(resultCode);
diff --git a/sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResponseImpl.java b/sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResponseImpl.java
index a39c9cc..f2f0abd 100644
--- a/sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResponseImpl.java
+++ b/sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResponseImpl.java
@@ -29,20 +29,24 @@
 
 
 
-import org.opends.sdk.controls.Control;
+import java.util.Collections;
+import java.util.List;
 
-import com.sun.opends.sdk.util.Iterables;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
  * Unmodifiable response implementation.
- * 
+ *
  * @param <S>
  *          The type of response.
  */
-abstract class AbstractUnmodifiableResponseImpl<S extends Response>
-    implements Response
+abstract class AbstractUnmodifiableResponseImpl<S extends Response> implements
+    Response
 {
 
   private final S impl;
@@ -51,12 +55,11 @@
 
   /**
    * Creates a new unmodifiable response implementation.
-   * 
+   *
    * @param impl
-   *          The underlying response implementation to be made
-   *          unmodifiable.
+   *          The underlying response implementation to be made unmodifiable.
    */
-  AbstractUnmodifiableResponseImpl(S impl)
+  AbstractUnmodifiableResponseImpl(final S impl)
   {
     this.impl = impl;
   }
@@ -66,7 +69,7 @@
   /**
    * {@inheritDoc}
    */
-  public final S addControl(Control control)
+  public final S addControl(final Control control)
       throws UnsupportedOperationException, NullPointerException
   {
     throw new UnsupportedOperationException();
@@ -77,21 +80,12 @@
   /**
    * {@inheritDoc}
    */
-  public final S clearControls() throws UnsupportedOperationException
-  {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final Control getControl(String oid)
-      throws NullPointerException
+  public final <C extends Control> C getControl(
+      final ControlDecoder<C> decoder, final DecodeOptions options)
+      throws NullPointerException, DecodeException
   {
     // FIXME: ensure that controls are immutable.
-    return impl.getControl(oid);
+    return impl.getControl(decoder, options);
   }
 
 
@@ -99,10 +93,10 @@
   /**
    * {@inheritDoc}
    */
-  public final Iterable<Control> getControls()
+  public final List<Control> getControls()
   {
     // FIXME: ensure that controls are immutable.
-    return Iterables.unmodifiable(impl.getControls());
+    return Collections.unmodifiableList(impl.getControls());
   }
 
 
@@ -110,27 +104,7 @@
   /**
    * {@inheritDoc}
    */
-  public final boolean hasControls()
-  {
-    return impl.hasControls();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public final Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException
-  {
-    throw new UnsupportedOperationException();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
+  @Override
   public final String toString()
   {
     return impl.toString();
diff --git a/sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResultImpl.java b/sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResultImpl.java
index 5873fd4..fa64f00 100644
--- a/sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResultImpl.java
+++ b/sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResultImpl.java
@@ -29,13 +29,16 @@
 
 
 
+import java.util.Collections;
+import java.util.List;
+
 import org.opends.sdk.ResultCode;
 
 
 
 /**
  * Unmodifiable result implementation.
- * 
+ *
  * @param <S>
  *          The type of result.
  */
@@ -49,12 +52,11 @@
 
   /**
    * Creates a new unmodifiable result implementation.
-   * 
+   *
    * @param impl
-   *          The underlying result implementation to be made
-   *          unmodifiable.
+   *          The underlying result implementation to be made unmodifiable.
    */
-  AbstractUnmodifiableResultImpl(S impl)
+  AbstractUnmodifiableResultImpl(final S impl)
   {
     super(impl);
     this.impl = impl;
@@ -62,7 +64,7 @@
 
 
 
-  public final S addReferralURI(String uri)
+  public final S addReferralURI(final String uri)
       throws UnsupportedOperationException, NullPointerException
   {
     throw new UnsupportedOperationException();
@@ -70,14 +72,6 @@
 
 
 
-  public final S clearReferralURIs()
-      throws UnsupportedOperationException
-  {
-    throw new UnsupportedOperationException();
-  }
-
-
-
   public final Throwable getCause()
   {
     return impl.getCause();
@@ -99,9 +93,9 @@
 
 
 
-  public final Iterable<String> getReferralURIs()
+  public final List<String> getReferralURIs()
   {
-    return impl.getReferralURIs();
+    return Collections.unmodifiableList(impl.getReferralURIs());
   }
 
 
@@ -113,13 +107,6 @@
 
 
 
-  public final boolean hasReferralURIs()
-  {
-    return impl.hasReferralURIs();
-  }
-
-
-
   public final boolean isReferral()
   {
     return impl.isReferral();
@@ -134,7 +121,7 @@
 
 
 
-  public final S setCause(Throwable cause)
+  public final S setCause(final Throwable cause)
       throws UnsupportedOperationException
   {
     throw new UnsupportedOperationException();
@@ -142,7 +129,7 @@
 
 
 
-  public final S setDiagnosticMessage(String message)
+  public final S setDiagnosticMessage(final String message)
       throws UnsupportedOperationException
   {
     throw new UnsupportedOperationException();
@@ -150,7 +137,7 @@
 
 
 
-  public final S setMatchedDN(String dn)
+  public final S setMatchedDN(final String dn)
       throws UnsupportedOperationException
   {
     throw new UnsupportedOperationException();
@@ -158,7 +145,7 @@
 
 
 
-  public final S setResultCode(ResultCode resultCode)
+  public final S setResultCode(final ResultCode resultCode)
       throws UnsupportedOperationException, NullPointerException
   {
     throw new UnsupportedOperationException();
diff --git a/sdk/src/org/opends/sdk/responses/BindResult.java b/sdk/src/org/opends/sdk/responses/BindResult.java
index 4555962..e8222d1 100644
--- a/sdk/src/org/opends/sdk/responses/BindResult.java
+++ b/sdk/src/org/opends/sdk/responses/BindResult.java
@@ -29,9 +29,14 @@
 
 
 
+import java.util.List;
+
 import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.ResultCode;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
@@ -39,49 +44,43 @@
  * A Bind result indicates the status of the client's request for
  * authentication.
  * <p>
- * A successful Bind operation is indicated by a Bind result with a
- * result code set to {@link ResultCode#SUCCESS} and can be determined
- * by invoking the {@link #isSuccess} method.
+ * A successful Bind operation is indicated by a Bind result with a result code
+ * set to {@link ResultCode#SUCCESS} and can be determined by invoking the
+ * {@link #isSuccess} method.
  * <p>
- * The server SASL credentials field is used as part of a SASL-defined
- * bind mechanism to allow the client to authenticate the server to
- * which it is communicating, or to perform "challenge-response"
- * authentication. If the client bound using a form of simple
- * authentication, or the SASL mechanism does not require the server to
- * return information to the client, then this field shall not be
- * included in the Bind result.
+ * The server SASL credentials field is used as part of a SASL-defined bind
+ * mechanism to allow the client to authenticate the server to which it is
+ * communicating, or to perform "challenge-response" authentication. If the
+ * client bound using a form of simple authentication, or the SASL mechanism
+ * does not require the server to return information to the client, then this
+ * field shall not be included in the Bind result.
  * <p>
- * If the server requires the client to send a new SASL Bind request in
- * order to continue the authentication process then the result code is
- * set to {@link ResultCode#SASL_BIND_IN_PROGRESS} and can be determined
- * by invoking the {@link #isSASLBindInProgress} method.
+ * If the server requires the client to send a new SASL Bind request in order to
+ * continue the authentication process then the result code is set to
+ * {@link ResultCode#SASL_BIND_IN_PROGRESS} and can be determined by invoking
+ * the {@link #isSASLBindInProgress} method.
  */
 public interface BindResult extends Result
 {
   /**
    * {@inheritDoc}
    */
-  BindResult addControl(Control control)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  BindResult addReferralURI(String uri)
-      throws UnsupportedOperationException, NullPointerException;
+  BindResult addControl(Control control) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  BindResult clearControls() throws UnsupportedOperationException;
+  BindResult addReferralURI(String uri) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
-  BindResult clearReferralURIs() throws UnsupportedOperationException;
-
-
-
+  /**
+   * {@inheritDoc}
+   */
   Throwable getCause();
 
 
@@ -89,39 +88,51 @@
   /**
    * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  Iterable<Control> getControls();
+  List<Control> getControls();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   String getDiagnosticMessage();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   String getMatchedDN();
 
 
 
-  Iterable<String> getReferralURIs();
+  /**
+   * {@inheritDoc}
+   */
+  List<String> getReferralURIs();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   ResultCode getResultCode();
 
 
 
   /**
-   * Returns the server SASL credentials associated with this bind
-   * result.
-   * 
-   * @return The server SASL credentials, or {@code null} indicating
-   *         that none was provided.
+   * Returns the server SASL credentials associated with this bind result.
+   *
+   * @return The server SASL credentials, or {@code null} indicating that none
+   *         was provided.
    */
   ByteString getServerSASLCredentials();
 
@@ -130,34 +141,29 @@
   /**
    * {@inheritDoc}
    */
-  boolean hasControls();
-
-
-
-  boolean hasReferralURIs();
-
-
-
   boolean isReferral();
 
 
 
   /**
-   * Indicates whether or not the server requires the client to send a
-   * new SASL Bind request with the same SASL mechanism in order to
-   * continue the authentication process. This typically occurs during
-   * multi-stage (challenge response) authentication.
+   * Indicates whether or not the server requires the client to send a new SASL
+   * Bind request with the same SASL mechanism in order to continue the
+   * authentication process. This typically occurs during multi-stage (challenge
+   * response) authentication.
    * <p>
-   * Specifically, this method returns {@code true} if the result code
-   * is equal to {@link ResultCode#SASL_BIND_IN_PROGRESS}.
-   * 
-   * @return {@code true} if the server requires the client to send a
-   *         new SASL Bind request, otherwise {@code false}.
+   * Specifically, this method returns {@code true} if the result code is equal
+   * to {@link ResultCode#SASL_BIND_IN_PROGRESS}.
+   *
+   * @return {@code true} if the server requires the client to send a new SASL
+   *         Bind request, otherwise {@code false}.
    */
   boolean isSASLBindInProgress();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   boolean isSuccess();
 
 
@@ -165,26 +171,28 @@
   /**
    * {@inheritDoc}
    */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  BindResult setCause(Throwable cause) throws UnsupportedOperationException;
 
 
 
-  BindResult setCause(Throwable cause)
-      throws UnsupportedOperationException;
-
-
-
+  /**
+   * {@inheritDoc}
+   */
   BindResult setDiagnosticMessage(String message)
       throws UnsupportedOperationException;
 
 
 
-  BindResult setMatchedDN(String dn)
-      throws UnsupportedOperationException;
+  /**
+   * {@inheritDoc}
+   */
+  BindResult setMatchedDN(String dn) throws UnsupportedOperationException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   BindResult setResultCode(ResultCode resultCode)
       throws UnsupportedOperationException, NullPointerException;
 
@@ -192,15 +200,14 @@
 
   /**
    * Sets the server SASL credentials associated with this bind result.
-   * 
+   *
    * @param credentials
-   *          The server SASL credentials associated with this bind
-   *          result, which may be {@code null} indicating that none was
-   *          provided.
+   *          The server SASL credentials associated with this bind result,
+   *          which may be {@code null} indicating that none was provided.
    * @return This bind result.
    * @throws UnsupportedOperationException
-   *           If this bind result does not permit the server SASL
-   *           credentials to be set.
+   *           If this bind result does not permit the server SASL credentials
+   *           to be set.
    */
   BindResult setServerSASLCredentials(ByteString credentials)
       throws UnsupportedOperationException;
diff --git a/sdk/src/org/opends/sdk/responses/BindResultImpl.java b/sdk/src/org/opends/sdk/responses/BindResultImpl.java
index 26110bf..3a1fa84 100644
--- a/sdk/src/org/opends/sdk/responses/BindResultImpl.java
+++ b/sdk/src/org/opends/sdk/responses/BindResultImpl.java
@@ -37,8 +37,8 @@
 /**
  * Bind result implementation.
  */
-final class BindResultImpl extends AbstractResultImpl<BindResult>
-    implements BindResult
+final class BindResultImpl extends AbstractResultImpl<BindResult> implements
+    BindResult
 {
   private ByteString credentials = null;
 
@@ -46,13 +46,13 @@
 
   /**
    * Creates a new bind result using the provided result code.
-   * 
+   *
    * @param resultCode
    *          The result code.
    * @throws NullPointerException
    *           If {@code resultCode} was {@code null}.
    */
-  BindResultImpl(ResultCode resultCode) throws NullPointerException
+  BindResultImpl(final ResultCode resultCode) throws NullPointerException
   {
     super(resultCode);
   }
@@ -83,7 +83,7 @@
   /**
    * {@inheritDoc}
    */
-  public BindResult setServerSASLCredentials(ByteString credentials)
+  public BindResult setServerSASLCredentials(final ByteString credentials)
       throws UnsupportedOperationException
   {
     this.credentials = credentials;
@@ -108,8 +108,8 @@
     builder.append(", referrals=");
     builder.append(getReferralURIs());
     builder.append(", serverSASLCreds=");
-    builder.append(getServerSASLCredentials() == null ? ByteString
-        .empty() : getServerSASLCredentials());
+    builder.append(getServerSASLCredentials() == null ? ByteString.empty()
+        : getServerSASLCredentials());
     builder.append(", controls=");
     builder.append(getControls());
     builder.append(")");
@@ -118,6 +118,7 @@
 
 
 
+  @Override
   BindResult getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/responses/CompareResult.java b/sdk/src/org/opends/sdk/responses/CompareResult.java
index bf6fe63..92ec492 100644
--- a/sdk/src/org/opends/sdk/responses/CompareResult.java
+++ b/sdk/src/org/opends/sdk/responses/CompareResult.java
@@ -15,32 +15,36 @@
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at
  * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * compare the following below this CDDL HEADER, with the fields enclosed
+ * add the following below this CDDL HEADER, with the fields enclosed
  * by brackets "[]" replaced with your own identifying information:
  *      Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 package org.opends.sdk.responses;
 
 
 
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.ResultCode;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
  * An Compare result indicates the final status of an Compare operation.
  * <p>
- * If the attribute value assertion in the Compare request matched a
- * value of the attribute or sub-type according to the attribute's
- * equality matching rule then the result code is set to
- * {@link ResultCode#COMPARE_TRUE} and can be determined by invoking the
- * {@link #matched} method.
+ * If the attribute value assertion in the Compare request matched a value of
+ * the attribute or sub-type according to the attribute's equality matching rule
+ * then the result code is set to {@link ResultCode#COMPARE_TRUE} and can be
+ * determined by invoking the {@link #matched} method.
  */
 public interface CompareResult extends Result
 {
@@ -52,6 +56,9 @@
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   CompareResult addReferralURI(String uri)
       throws UnsupportedOperationException, NullPointerException;
 
@@ -60,15 +67,6 @@
   /**
    * {@inheritDoc}
    */
-  CompareResult clearControls() throws UnsupportedOperationException;
-
-
-
-  CompareResult clearReferralURIs()
-      throws UnsupportedOperationException;
-
-
-
   Throwable getCause();
 
 
@@ -76,29 +74,42 @@
   /**
    * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  Iterable<Control> getControls();
+  List<Control> getControls();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   String getDiagnosticMessage();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   String getMatchedDN();
 
 
 
-  Iterable<String> getReferralURIs();
+  /**
+   * {@inheritDoc}
+   */
+  List<String> getReferralURIs();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   ResultCode getResultCode();
 
 
@@ -106,32 +117,27 @@
   /**
    * {@inheritDoc}
    */
-  boolean hasControls();
-
-
-
-  boolean hasReferralURIs();
-
-
-
   boolean isReferral();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   boolean isSuccess();
 
 
 
   /**
-   * Indicates whether or not the attribute value assertion in the
-   * Compare request matched a value of the attribute or sub-type
-   * according to the attribute's equality matching rule.
+   * Indicates whether or not the attribute value assertion in the Compare
+   * request matched a value of the attribute or sub-type according to the
+   * attribute's equality matching rule.
    * <p>
-   * Specifically, this method returns {@code true} if the result code
-   * is equal to {@link ResultCode#COMPARE_TRUE}.
-   * 
-   * @return {@code true} if the attribute value assertion matched,
-   *         otherwise {@code false}.
+   * Specifically, this method returns {@code true} if the result code is equal
+   * to {@link ResultCode#COMPARE_TRUE}.
+   *
+   * @return {@code true} if the attribute value assertion matched, otherwise
+   *         {@code false}.
    */
   boolean matched();
 
@@ -140,26 +146,28 @@
   /**
    * {@inheritDoc}
    */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  CompareResult setCause(Throwable cause) throws UnsupportedOperationException;
 
 
 
-  CompareResult setCause(Throwable cause)
-      throws UnsupportedOperationException;
-
-
-
+  /**
+   * {@inheritDoc}
+   */
   CompareResult setDiagnosticMessage(String message)
       throws UnsupportedOperationException;
 
 
 
-  CompareResult setMatchedDN(String dn)
-      throws UnsupportedOperationException;
+  /**
+   * {@inheritDoc}
+   */
+  CompareResult setMatchedDN(String dn) throws UnsupportedOperationException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   CompareResult setResultCode(ResultCode resultCode)
       throws UnsupportedOperationException, NullPointerException;
 
diff --git a/sdk/src/org/opends/sdk/responses/CompareResultImpl.java b/sdk/src/org/opends/sdk/responses/CompareResultImpl.java
index 14baaa5..ef4331f 100644
--- a/sdk/src/org/opends/sdk/responses/CompareResultImpl.java
+++ b/sdk/src/org/opends/sdk/responses/CompareResultImpl.java
@@ -15,14 +15,14 @@
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at
  * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * compare the following below this CDDL HEADER, with the fields enclosed
+ * add the following below this CDDL HEADER, with the fields enclosed
  * by brackets "[]" replaced with your own identifying information:
  *      Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk.responses;
@@ -42,13 +42,13 @@
 
   /**
    * Creates a new compare result using the provided result code.
-   * 
+   *
    * @param resultCode
    *          The result code.
    * @throws NullPointerException
    *           If {@code resultCode} was {@code null}.
    */
-  CompareResultImpl(ResultCode resultCode) throws NullPointerException
+  CompareResultImpl(final ResultCode resultCode) throws NullPointerException
   {
     super(resultCode);
   }
@@ -89,6 +89,7 @@
 
 
 
+  @Override
   CompareResult getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/responses/ExtendedResult.java b/sdk/src/org/opends/sdk/responses/ExtendedResult.java
index 4cdc79d..ccbed68 100644
--- a/sdk/src/org/opends/sdk/responses/ExtendedResult.java
+++ b/sdk/src/org/opends/sdk/responses/ExtendedResult.java
@@ -29,18 +29,22 @@
 
 
 
+import java.util.List;
+
 import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.ResultCode;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * A Extended result indicates the status of an Extended operation and
- * any additional information associated with the Extended operation,
- * including the optional response name and value. These can be
- * retrieved using the {@link #getResponseName} and
- * {@link #getResponseValue} methods respectively.
+ * A Extended result indicates the status of an Extended operation and any
+ * additional information associated with the Extended operation, including the
+ * optional response name and value. These can be retrieved using the
+ * {@link #getOID} and {@link #getValue} methods respectively.
  */
 public interface ExtendedResult extends Result
 {
@@ -52,6 +56,9 @@
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   ExtendedResult addReferralURI(String uri)
       throws UnsupportedOperationException, NullPointerException;
 
@@ -60,15 +67,6 @@
   /**
    * {@inheritDoc}
    */
-  ExtendedResult clearControls() throws UnsupportedOperationException;
-
-
-
-  ExtendedResult clearReferralURIs()
-      throws UnsupportedOperationException;
-
-
-
   Throwable getCause();
 
 
@@ -76,70 +74,90 @@
   /**
    * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  Iterable<Control> getControls();
+  List<Control> getControls();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   String getDiagnosticMessage();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   String getMatchedDN();
 
 
 
-  Iterable<String> getReferralURIs();
+  /**
+   * Returns the numeric OID, if any, associated with this extended result.
+   *
+   * @return The numeric OID associated with this extended result, or {@code
+   *         null} if there is no OID.
+   */
+  String getOID();
 
 
 
   /**
-   * Returns the dotted-decimal representation of the unique OID
-   * corresponding to this extended result.
-   * 
-   * @return The dotted-decimal representation of the unique OID, or
-   *         {@code null} if none was provided.
+   * {@inheritDoc}
    */
-  String getResponseName();
+  List<String> getReferralURIs();
 
 
 
   /**
-   * Returns the content of this extended result in a form defined by
-   * the extended result.
-   * 
-   * @return The content of this extended result, or {@code null} if
-   *         there is no content.
+   * {@inheritDoc}
    */
-  ByteString getResponseValue();
-
-
-
   ResultCode getResultCode();
 
 
 
   /**
+   * Returns the value, if any, associated with this extended result. Its format
+   * is defined by the specification of this extended result.
+   *
+   * @return The value associated with this extended result, or {@code null} if
+   *         there is no value.
+   */
+  ByteString getValue();
+
+
+
+  /**
+   * Returns {@code true} if this extended result has a value. In some
+   * circumstances it may be useful to determine if a extended result has a
+   * value, without actually calculating the value and incurring any performance
+   * costs.
+   *
+   * @return {@code true} if this extended result has a value, or {@code false}
+   *         if there is no value.
+   */
+  boolean hasValue();
+
+
+
+  /**
    * {@inheritDoc}
    */
-  boolean hasControls();
-
-
-
-  boolean hasReferralURIs();
-
-
-
   boolean isReferral();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   boolean isSuccess();
 
 
@@ -147,26 +165,28 @@
   /**
    * {@inheritDoc}
    */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  ExtendedResult setCause(Throwable cause) throws UnsupportedOperationException;
 
 
 
-  ExtendedResult setCause(Throwable cause)
-      throws UnsupportedOperationException;
-
-
-
+  /**
+   * {@inheritDoc}
+   */
   ExtendedResult setDiagnosticMessage(String message)
       throws UnsupportedOperationException;
 
 
 
-  ExtendedResult setMatchedDN(String dn)
-      throws UnsupportedOperationException;
+  /**
+   * {@inheritDoc}
+   */
+  ExtendedResult setMatchedDN(String dn) throws UnsupportedOperationException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   ExtendedResult setResultCode(ResultCode resultCode)
       throws UnsupportedOperationException, NullPointerException;
 }
diff --git a/sdk/src/org/opends/sdk/responses/ExtendedResultDecoder.java b/sdk/src/org/opends/sdk/responses/ExtendedResultDecoder.java
new file mode 100644
index 0000000..db59197
--- /dev/null
+++ b/sdk/src/org/opends/sdk/responses/ExtendedResultDecoder.java
@@ -0,0 +1,89 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.responses;
+
+
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.ResultCode;
+
+
+
+/**
+ * A factory interface for decoding a generic extended result as an extended
+ * result of specific type.
+ *
+ * @param <S>
+ *          The type of result.
+ */
+public interface ExtendedResultDecoder<S extends ExtendedResult>
+{
+  /**
+   * Adapts the provided error result parameters to an extended operation
+   * result. This method is called when a generic failure occurs, such as a
+   * connection failure, and the error result needs to be converted to a {@code
+   * Result} of type {@code S}.
+   *
+   * @param resultCode
+   *          The result code.
+   * @param matchedDN
+   *          The matched DN, which may be empty if none was provided.
+   * @param diagnosticMessage
+   *          The diagnostic message, which may be empty if none was provided.
+   * @return The decoded extended operation error result.
+   * @throws NullPointerException
+   *           If {@code resultCode}, {@code matchedDN}, or {@code
+   *           diagnosticMessage} were {@code null}.
+   */
+  S adaptExtendedErrorResult(ResultCode resultCode, String matchedDN,
+      String diagnosticMessage) throws NullPointerException;
+
+
+
+  /**
+   * Decodes the provided extended operation result as a {@code Result} of type
+   * {@code S}. This method is called when an extended result is received from
+   * the server. The result may indicate success or failure of the extended
+   * request.
+   *
+   * @param result
+   *          The extended operation result to be decoded.
+   * @param options
+   *          The set of decode options which should be used when decoding the
+   *          extended operation result.
+   * @return The decoded extended operation result.
+   * @throws DecodeException
+   *           If the provided extended operation result could not be decoded.
+   *           For example, if the request name was wrong, or if the request
+   *           value was invalid.
+   */
+  S decodeExtendedResult(ExtendedResult result, DecodeOptions options)
+      throws DecodeException;
+
+}
diff --git a/sdk/src/org/opends/sdk/responses/GenericExtendedResult.java b/sdk/src/org/opends/sdk/responses/GenericExtendedResult.java
index 12dd1fa..f6439ea 100644
--- a/sdk/src/org/opends/sdk/responses/GenericExtendedResult.java
+++ b/sdk/src/org/opends/sdk/responses/GenericExtendedResult.java
@@ -15,29 +15,34 @@
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at
  * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * generic extended the following below this CDDL HEADER, with the fields enclosed
+ * add the following below this CDDL HEADER, with the fields enclosed
  * by brackets "[]" replaced with your own identifying information:
  *      Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk.responses;
 
 
 
+import java.util.List;
+
 import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.ResultCode;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * A Generic Extended result indicates the final status of an Generic
- * Extended operation.
+ * A Generic Extended result indicates the final status of an Generic Extended
+ * operation.
  */
 public interface GenericExtendedResult extends ExtendedResult
 {
@@ -49,6 +54,9 @@
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   GenericExtendedResult addReferralURI(String uri)
       throws UnsupportedOperationException, NullPointerException;
 
@@ -57,16 +65,6 @@
   /**
    * {@inheritDoc}
    */
-  GenericExtendedResult clearControls()
-      throws UnsupportedOperationException;
-
-
-
-  GenericExtendedResult clearReferralURIs()
-      throws UnsupportedOperationException;
-
-
-
   Throwable getCause();
 
 
@@ -74,43 +72,49 @@
   /**
    * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  Iterable<Control> getControls();
+  List<Control> getControls();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   String getDiagnosticMessage();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   String getMatchedDN();
 
 
 
-  Iterable<String> getReferralURIs();
+  /**
+   * {@inheritDoc}
+   */
+  String getOID();
 
 
 
   /**
    * {@inheritDoc}
    */
-  String getResponseName();
+  List<String> getReferralURIs();
 
 
 
   /**
    * {@inheritDoc}
    */
-  ByteString getResponseValue();
-
-
-
   ResultCode getResultCode();
 
 
@@ -118,18 +122,27 @@
   /**
    * {@inheritDoc}
    */
-  boolean hasControls();
+  ByteString getValue();
 
 
 
-  boolean hasReferralURIs();
+  /**
+   * {@inheritDoc}
+   */
+  boolean hasValue();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   boolean isReferral();
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   boolean isSuccess();
 
 
@@ -137,62 +150,63 @@
   /**
    * {@inheritDoc}
    */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
   GenericExtendedResult setCause(Throwable cause)
       throws UnsupportedOperationException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   GenericExtendedResult setDiagnosticMessage(String message)
       throws UnsupportedOperationException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   GenericExtendedResult setMatchedDN(String dn)
       throws UnsupportedOperationException;
 
 
 
   /**
-   * Sets the dotted-decimal representation of the unique OID
-   * corresponding to this generic extended result.
-   * 
+   * Sets the numeric OID, if any, associated with this extended result.
+   *
    * @param oid
-   *          The dotted-decimal representation of the unique OID, or
-   *          {@code null} if there is no response name.
+   *          The numeric OID associated with this extended result, or {@code
+   *          null} if there is no value.
    * @return This generic extended result.
    * @throws UnsupportedOperationException
-   *           If this generic extended result does not permit the
-   *           response name to be set.
+   *           If this generic extended result does not permit the result name
+   *           to be set.
    */
-  GenericExtendedResult setResponseName(String oid)
-      throws UnsupportedOperationException;
+  GenericExtendedResult setOID(String oid) throws UnsupportedOperationException;
 
 
 
   /**
-   * Sets the content of this generic extended result in a form defined
-   * by the extended result.
-   * 
-   * @param bytes
-   *          The content of this generic extended result in a form
-   *          defined by the extended result, or {@code null} if there
-   *          is no content.
-   * @return This generic extended result.
-   * @throws UnsupportedOperationException
-   *           If this generic extended result does not permit the
-   *           response value to be set.
+   * {@inheritDoc}
    */
-  GenericExtendedResult setResponseValue(ByteString bytes)
-      throws UnsupportedOperationException;
-
-
-
   GenericExtendedResult setResultCode(ResultCode resultCode)
       throws UnsupportedOperationException, NullPointerException;
 
+
+
+  /**
+   * Sets the value, if any, associated with this extended result. Its format is
+   * defined by the specification of this extended result.
+   *
+   * @param bytes
+   *          The value associated with this extended result, or {@code null} if
+   *          there is no value.
+   * @return This generic extended result.
+   * @throws UnsupportedOperationException
+   *           If this generic extended result does not permit the result value
+   *           to be set.
+   */
+  GenericExtendedResult setValue(ByteString bytes)
+      throws UnsupportedOperationException;
+
 }
diff --git a/sdk/src/org/opends/sdk/responses/GenericExtendedResultImpl.java b/sdk/src/org/opends/sdk/responses/GenericExtendedResultImpl.java
index cdcc2a0..96de633 100644
--- a/sdk/src/org/opends/sdk/responses/GenericExtendedResultImpl.java
+++ b/sdk/src/org/opends/sdk/responses/GenericExtendedResultImpl.java
@@ -15,14 +15,14 @@
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at
  * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * generic extended the following below this CDDL HEADER, with the fields enclosed
+ * add the following below this CDDL HEADER, with the fields enclosed
  * by brackets "[]" replaced with your own identifying information:
  *      Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk.responses;
@@ -32,14 +32,16 @@
 import org.opends.sdk.ByteString;
 import org.opends.sdk.ResultCode;
 
+import com.sun.opends.sdk.util.StaticUtils;
+
 
 
 /**
  * Generic extended result implementation.
  */
 final class GenericExtendedResultImpl extends
-    AbstractResultImpl<GenericExtendedResult> implements
-    ExtendedResult, GenericExtendedResult
+    AbstractResultImpl<GenericExtendedResult> implements ExtendedResult,
+    GenericExtendedResult
 {
 
   private String responseName = null;
@@ -49,15 +51,14 @@
 
 
   /**
-   * Creates a new generic extended result using the provided result
-   * code.
-   * 
+   * Creates a new generic extended result using the provided result code.
+   *
    * @param resultCode
    *          The result code.
    * @throws NullPointerException
    *           If {@code resultCode} was {@code null}.
    */
-  GenericExtendedResultImpl(ResultCode resultCode)
+  GenericExtendedResultImpl(final ResultCode resultCode)
       throws NullPointerException
   {
     super(resultCode);
@@ -68,7 +69,7 @@
   /**
    * {@inheritDoc}
    */
-  public String getResponseName()
+  public String getOID()
   {
     return responseName;
   }
@@ -78,7 +79,7 @@
   /**
    * {@inheritDoc}
    */
-  public ByteString getResponseValue()
+  public ByteString getValue()
   {
     return responseValue;
   }
@@ -88,7 +89,17 @@
   /**
    * {@inheritDoc}
    */
-  public GenericExtendedResult setResponseName(String oid)
+  public boolean hasValue()
+  {
+    return responseValue != null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public GenericExtendedResult setOID(final String oid)
       throws UnsupportedOperationException
   {
     this.responseName = oid;
@@ -100,7 +111,7 @@
   /**
    * {@inheritDoc}
    */
-  public GenericExtendedResult setResponseValue(ByteString bytes)
+  public GenericExtendedResult setValue(final ByteString bytes)
       throws UnsupportedOperationException
   {
     this.responseValue = bytes;
@@ -116,7 +127,7 @@
   public String toString()
   {
     final StringBuilder builder = new StringBuilder();
-    builder.append("ExtendedResult(resultCode=");
+    builder.append("GenericExtendedResult(resultCode=");
     builder.append(getResultCode());
     builder.append(", matchedDN=");
     builder.append(getMatchedDN());
@@ -125,10 +136,12 @@
     builder.append(", referrals=");
     builder.append(getReferralURIs());
     builder.append(", responseName=");
-    builder.append(getResponseName() == null ? "" : getResponseName());
-    builder.append(", responseValue=");
-    final ByteString value = getResponseValue();
-    builder.append(value == null ? ByteString.empty() : value);
+    builder.append(getOID() == null ? "" : getOID());
+    if (hasValue())
+    {
+      builder.append(", responseValue=");
+      StaticUtils.toHexPlusAscii(getValue(), builder, 4);
+    }
     builder.append(", controls=");
     builder.append(getControls());
     builder.append(")");
@@ -137,6 +150,7 @@
 
 
 
+  @Override
   GenericExtendedResult getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/responses/GenericIntermediateResponse.java b/sdk/src/org/opends/sdk/responses/GenericIntermediateResponse.java
index 5eda851..f3c8006 100644
--- a/sdk/src/org/opends/sdk/responses/GenericIntermediateResponse.java
+++ b/sdk/src/org/opends/sdk/responses/GenericIntermediateResponse.java
@@ -15,32 +15,35 @@
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at
  * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * generic extended the following below this CDDL HEADER, with the fields enclosed
+ * add the following below this CDDL HEADER, with the fields enclosed
  * by brackets "[]" replaced with your own identifying information:
  *      Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk.responses;
 
 
 
+import java.util.List;
+
 import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * A Generic Intermediate response provides a mechanism for
- * communicating unrecognized or unsupported Intermediate responses to
- * the client.
+ * A Generic Intermediate response provides a mechanism for communicating
+ * unrecognized or unsupported Intermediate responses to the client.
  */
-public interface GenericIntermediateResponse extends
-    IntermediateResponse
+public interface GenericIntermediateResponse extends IntermediateResponse
 {
   /**
    * {@inheritDoc}
@@ -53,85 +56,68 @@
   /**
    * {@inheritDoc}
    */
-  GenericIntermediateResponse clearControls()
-      throws UnsupportedOperationException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  List<Control> getControls();
 
 
 
   /**
    * {@inheritDoc}
    */
-  Iterable<Control> getControls();
+  String getOID();
 
 
 
   /**
    * {@inheritDoc}
    */
-  String getResponseName();
+  ByteString getValue();
 
 
 
   /**
    * {@inheritDoc}
    */
-  ByteString getResponseValue();
+  boolean hasValue();
 
 
 
   /**
-   * {@inheritDoc}
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Sets the dotted-decimal representation of the unique OID
-   * corresponding to this generic intermediate response.
-   * 
+   * Sets the numeric OID, if any, associated with this intermediate response.
+   *
    * @param oid
-   *          The dotted-decimal representation of the unique OID, or
-   *          {@code null} if there is no response name.
+   *          The numeric OID associated with this intermediate response, or
+   *          {@code null} if there is no value.
    * @return This generic intermediate response.
    * @throws UnsupportedOperationException
-   *           If this generic intermediate response does not permit the
-   *           response name to be set.
+   *           If this intermediate response does not permit the response name
+   *           to be set.
    */
-  GenericIntermediateResponse setResponseName(String oid)
+  GenericIntermediateResponse setOID(String oid)
       throws UnsupportedOperationException;
 
 
 
   /**
-   * Sets the content of this generic intermediate response in a form
-   * defined by the extended result.
-   * 
+   * Sets the value, if any, associated with this intermediate response. Its
+   * format is defined by the specification of this intermediate response.
+   *
    * @param bytes
-   *          The content of this generic intermediate response in a
-   *          form defined by the intermediate response, or {@code null}
-   *          if there is no content.
+   *          The value associated with this intermediate response, or {@code
+   *          null} if there is no value.
    * @return This generic intermediate response.
    * @throws UnsupportedOperationException
-   *           If this generic intermediate response does not permit the
-   *           response value to be set.
+   *           If this intermediate response does not permit the response value
+   *           to be set.
    */
-  GenericIntermediateResponse setResponseValue(ByteString bytes)
+  GenericIntermediateResponse setValue(ByteString bytes)
       throws UnsupportedOperationException;
 
 }
diff --git a/sdk/src/org/opends/sdk/responses/GenericIntermediateResponseImpl.java b/sdk/src/org/opends/sdk/responses/GenericIntermediateResponseImpl.java
index 6f6e2a1..7cc9838 100644
--- a/sdk/src/org/opends/sdk/responses/GenericIntermediateResponseImpl.java
+++ b/sdk/src/org/opends/sdk/responses/GenericIntermediateResponseImpl.java
@@ -15,14 +15,14 @@
  * When distributing Covered Code, include this CDDL HEADER in each
  * file and include the License file at
  * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * generic extended the following below this CDDL HEADER, with the fields enclosed
+ * add the following below this CDDL HEADER, with the fields enclosed
  * by brackets "[]" replaced with your own identifying information:
  *      Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk.responses;
@@ -31,6 +31,8 @@
 
 import org.opends.sdk.ByteString;
 
+import com.sun.opends.sdk.util.StaticUtils;
+
 
 
 /**
@@ -48,20 +50,20 @@
 
 
   /**
-   * Creates a new generic intermediate response using the provided
-   * response name and value.
-   * 
+   * Creates a new generic intermediate response using the provided response
+   * name and value.
+   *
    * @param responseName
-   *          The dotted-decimal representation of the unique OID
-   *          corresponding to this intermediate response, which may be
-   *          {@code null} indicating that none was provided.
-   * @param responseValue
-   *          The response value associated with this generic
-   *          intermediate response, which may be {@code null}
+   *          The dotted-decimal representation of the unique OID corresponding
+   *          to this intermediate response, which may be {@code null}
    *          indicating that none was provided.
+   * @param responseValue
+   *          The response value associated with this generic intermediate
+   *          response, which may be {@code null} indicating that none was
+   *          provided.
    */
-  GenericIntermediateResponseImpl(String responseName,
-      ByteString responseValue)
+  GenericIntermediateResponseImpl(final String responseName,
+      final ByteString responseValue)
   {
     this.responseName = responseName;
     this.responseValue = responseValue;
@@ -72,7 +74,8 @@
   /**
    * {@inheritDoc}
    */
-  public String getResponseName()
+  @Override
+  public String getOID()
   {
     return responseName;
   }
@@ -82,7 +85,8 @@
   /**
    * {@inheritDoc}
    */
-  public ByteString getResponseValue()
+  @Override
+  public ByteString getValue()
   {
     return responseValue;
   }
@@ -92,7 +96,18 @@
   /**
    * {@inheritDoc}
    */
-  public GenericIntermediateResponse setResponseName(String oid)
+  @Override
+  public boolean hasValue()
+  {
+    return responseValue != null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public GenericIntermediateResponse setOID(final String oid)
       throws UnsupportedOperationException
   {
     this.responseName = oid;
@@ -104,7 +119,7 @@
   /**
    * {@inheritDoc}
    */
-  public GenericIntermediateResponse setResponseValue(ByteString bytes)
+  public GenericIntermediateResponse setValue(final ByteString bytes)
       throws UnsupportedOperationException
   {
     this.responseValue = bytes;
@@ -120,11 +135,13 @@
   public String toString()
   {
     final StringBuilder builder = new StringBuilder();
-    builder.append("IntermediateResponse(responseName=");
-    builder.append(getResponseName() == null ? "" : getResponseName());
-    builder.append(", responseValue=");
-    final ByteString value = getResponseValue();
-    builder.append(value == null ? ByteString.empty() : value);
+    builder.append("GenericIntermediateResponse(responseName=");
+    builder.append(getOID() == null ? "" : getOID());
+    if (hasValue())
+    {
+      builder.append(", requestValue=");
+      StaticUtils.toHexPlusAscii(getValue(), builder, 4);
+    }
     builder.append(", controls=");
     builder.append(getControls());
     builder.append(")");
diff --git a/sdk/src/org/opends/sdk/responses/IntermediateResponse.java b/sdk/src/org/opends/sdk/responses/IntermediateResponse.java
index ce4a051..993b3a9 100644
--- a/sdk/src/org/opends/sdk/responses/IntermediateResponse.java
+++ b/sdk/src/org/opends/sdk/responses/IntermediateResponse.java
@@ -29,22 +29,27 @@
 
 
 
+import java.util.List;
+
 import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
  * An Intermediate response provides a general mechanism for defining
- * single-request/multiple-response operations. This response is
- * intended to be used in conjunction with the Extended operation to
- * define new single-request/multiple-response operations or in
- * conjunction with a control when extending existing operations in a
- * way that requires them to return Intermediate response information.
+ * single-request/multiple-response operations. This response is intended to be
+ * used in conjunction with the Extended operation to define new
+ * single-request/multiple-response operations or in conjunction with a control
+ * when extending existing operations in a way that requires them to return
+ * Intermediate response information.
  * <p>
- * An Intermediate response may convey an optional response name and
- * value. These can be retrieved using the {@link #getResponseName} and
- * {@link #getResponseValue} methods respectively.
+ * An Intermediate response may convey an optional response name and value.
+ * These can be retrieved using the {@link #getOID} and {@link #getValue}
+ * methods respectively.
  */
 public interface IntermediateResponse extends Response
 {
@@ -59,58 +64,49 @@
   /**
    * {@inheritDoc}
    */
-  IntermediateResponse clearControls()
-      throws UnsupportedOperationException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  List<Control> getControls();
 
 
 
   /**
-   * {@inheritDoc}
+   * Returns the numeric OID, if any, associated with this intermediate
+   * response.
+   *
+   * @return The numeric OID associated with this intermediate response, or
+   *         {@code null} if there is no OID.
    */
-  Iterable<Control> getControls();
+  String getOID();
 
 
 
   /**
-   * Returns the dotted-decimal representation of the unique OID
-   * corresponding to this intermediate response.
-   * 
-   * @return The dotted-decimal representation of the unique OID, or
-   *         {@code null} if none was provided.
+   * Returns the value, if any, associated with this intermediate response. Its
+   * format is defined by the specification of this intermediate response.
+   *
+   * @return The value associated with this intermediate response, or {@code
+   *         null} if there is no value.
    */
-  String getResponseName();
+  ByteString getValue();
 
 
 
   /**
-   * Returns the content of this intermediate response in a form defined
-   * by the intermediate response.
-   * 
-   * @return The content of this intermediate response, or {@code null}
-   *         if there is no content.
+   * Returns {@code true} if this intermediate response has a value. In some
+   * circumstances it may be useful to determine if an intermediate response has
+   * a value, without actually calculating the value and incurring any
+   * performance costs.
+   *
+   * @return {@code true} if this intermediate response has a value, or {@code
+   *         false} if there is no value.
    */
-  ByteString getResponseValue();
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  boolean hasValue();
 
 }
diff --git a/sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResult.java b/sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResult.java
new file mode 100644
index 0000000..4f2911d
--- /dev/null
+++ b/sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResult.java
@@ -0,0 +1,235 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.responses;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.ResultCode;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+
+
+/**
+ * The password modify extended result as defined in RFC 3062. The result
+ * includes the generated password, if requested, but only if the modify request
+ * succeeded.
+ *
+ * @see org.opends.sdk.requests.PasswordModifyExtendedRequest
+ * @see <a href="http://tools.ietf.org/html/rfc3909">RFC 3062 - LDAP Password
+ *      Modify Extended Operation </a>
+ */
+public interface PasswordModifyExtendedResult extends ExtendedResult
+{
+
+  /**
+   * {@inheritDoc}
+   */
+  PasswordModifyExtendedResult addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  PasswordModifyExtendedResult addReferralURI(String uri)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  Throwable getCause();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getDiagnosticMessage();
+
+
+
+  /**
+   * Returns the newly generated password, but only if the password modify
+   * request succeeded and a generated password was requested.
+   *
+   * @return The newly generated password, or {@code null} if the password
+   *         modify request failed or a generated password was not requested.
+   */
+  ByteString getGeneratedPassword();
+
+
+
+  /**
+   * Returns the newly generated password decoded as a UTF-8 string, but only if
+   * the password modify request succeeded and a generated password was
+   * requested.
+   *
+   * @return The newly generated password decoded as a UTF-8 string, or {@code
+   *         null} if the password modify request failed or a generated password
+   *         was not requested.
+   */
+  String getGeneratedPasswordAsString();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getMatchedDN();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getOID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<String> getReferralURIs();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ResultCode getResultCode();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ByteString getValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  boolean hasValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  boolean isReferral();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  boolean isSuccess();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  PasswordModifyExtendedResult setCause(Throwable cause)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  PasswordModifyExtendedResult setDiagnosticMessage(String message)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * Sets the generated password.
+   *
+   * @param password
+   *          The generated password, or {@code null} if there is no generated
+   *          password associated with this result.
+   * @return This password modify result.
+   */
+  PasswordModifyExtendedResult setGeneratedPassword(ByteString password);
+
+
+
+  /**
+   * Sets the generated password. The password will be converted to a UTF-8
+   * octet string.
+   *
+   * @param password
+   *          The generated password, or {@code null} if there is no generated
+   *          password associated with this result.
+   * @return This password modify result.
+   */
+  PasswordModifyExtendedResult setGeneratedPassword(String password);
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  PasswordModifyExtendedResult setMatchedDN(String dn)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  PasswordModifyExtendedResult setResultCode(ResultCode resultCode)
+      throws UnsupportedOperationException, NullPointerException;
+
+}
diff --git a/sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResultImpl.java b/sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResultImpl.java
new file mode 100644
index 0000000..5a1e4a2
--- /dev/null
+++ b/sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResultImpl.java
@@ -0,0 +1,189 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.responses;
+
+
+
+import java.io.IOException;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.ByteStringBuilder;
+import org.opends.sdk.ResultCode;
+import org.opends.sdk.asn1.ASN1;
+import org.opends.sdk.asn1.ASN1Writer;
+
+
+
+/**
+ * Password modify extended result implementation.
+ */
+final class PasswordModifyExtendedResultImpl extends
+    AbstractExtendedResult<PasswordModifyExtendedResult> implements
+    PasswordModifyExtendedResult
+{
+  private ByteString password;
+
+  /**
+   * The ASN.1 element type that will be used to encode the genPasswd component
+   * in a password modify extended response.
+   */
+  private static final byte TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD = (byte) 0x80;
+
+
+
+  // Instantiation via factory.
+  PasswordModifyExtendedResultImpl(final ResultCode resultCode)
+  {
+    super(resultCode);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public ByteString getGeneratedPassword()
+  {
+    return password;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getGeneratedPasswordAsString()
+  {
+    return password != null ? password.toString() : null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    // No response name defined.
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    if (password != null)
+    {
+      final ByteStringBuilder buffer = new ByteStringBuilder();
+      final ASN1Writer writer = ASN1.getWriter(buffer);
+
+      try
+      {
+        writer.writeStartSequence();
+        writer.writeOctetString(TYPE_PASSWORD_MODIFY_GENERATED_PASSWORD,
+            password);
+        writer.writeEndSequence();
+      }
+      catch (final IOException ioe)
+      {
+        // This should never happen unless there is a bug somewhere.
+        throw new RuntimeException(ioe);
+      }
+
+      return buffer.toByteString();
+    }
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return password != null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PasswordModifyExtendedResult setGeneratedPassword(
+      final ByteString password)
+  {
+    this.password = password;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public PasswordModifyExtendedResult setGeneratedPassword(final String password)
+  {
+    this.password = (password != null) ? ByteString.valueOf(password) : null;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("PasswordModifyExtendedResponse(resultCode=");
+    builder.append(getResultCode());
+    builder.append(", matchedDN=");
+    builder.append(getMatchedDN());
+    builder.append(", diagnosticMessage=");
+    builder.append(getDiagnosticMessage());
+    builder.append(", referrals=");
+    builder.append(getReferralURIs());
+    if (password != null)
+    {
+      builder.append(", genPassword=");
+      builder.append(password);
+    }
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/responses/Response.java b/sdk/src/org/opends/sdk/responses/Response.java
index 940fc3b..0c92715 100644
--- a/sdk/src/org/opends/sdk/responses/Response.java
+++ b/sdk/src/org/opends/sdk/responses/Response.java
@@ -29,7 +29,12 @@
 
 
 
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
@@ -44,7 +49,7 @@
 
   /**
    * Adds the provided control to this response.
-   * 
+   *
    * @param control
    *          The control to be added.
    * @return This response.
@@ -53,72 +58,42 @@
    * @throws NullPointerException
    *           If {@code control} was {@code null}.
    */
-  Response addControl(Control control)
-      throws UnsupportedOperationException, NullPointerException;
+  Response addControl(Control control) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * Removes all the controls included with this response.
-   * 
-   * @return This response.
-   * @throws UnsupportedOperationException
-   *           If this response does not permit controls to be removed.
-   */
-  Response clearControls() throws UnsupportedOperationException;
-
-
-
-  /**
-   * Returns the first control contained in this response having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be returned.
-   * @return The control, or {@code null} if the control is not included
+   * Decodes and returns the first control in this response having an OID
+   * corresponding to the provided control decoder.
+   *
+   * @param <C>
+   *          The type of control to be decoded and returned.
+   * @param decoder
+   *          The control decoder.
+   * @param options
+   *          The set of decode options which should be used when decoding the
+   *          control.
+   * @return The decoded control, or {@code null} if the control is not included
    *         with this response.
+   * @throws DecodeException
+   *           If the control could not be decoded because it was malformed in
+   *           some way (e.g. the control value was missing, or its content
+   *           could not be decoded).
    * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
+   *           If {@code decoder} or {@code options} was {@code null}.
    */
-  Control getControl(String oid) throws NullPointerException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
-   * Returns an {@code Iterable} containing the controls included with
-   * this response. The returned {@code Iterable} may be used to remove
-   * controls if permitted by this response.
-   * 
-   * @return An {@code Iterable} containing the controls.
+   * Returns a {@code List} containing the controls included with this response.
+   * The returned {@code List} may be modified if permitted by this response.
+   *
+   * @return A {@code List} containing the controls.
    */
-  Iterable<Control> getControls();
-
-
-
-  /**
-   * Indicates whether or not this response has any controls.
-   * 
-   * @return {@code true} if this response has any controls, otherwise
-   *         {@code false}.
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Removes the first control contained in this response having the
-   * specified OID.
-   * 
-   * @param oid
-   *          The OID of the control to be removed.
-   * @return The removed control, or {@code null} if the control is not
-   *         included with this response.
-   * @throws UnsupportedOperationException
-   *           If this response does not permit controls to be removed.
-   * @throws NullPointerException
-   *           If {@code oid} was {@code null}.
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  List<Control> getControls();
 
 }
diff --git a/sdk/src/org/opends/sdk/responses/Responses.java b/sdk/src/org/opends/sdk/responses/Responses.java
index 7d1c577..af646d3 100644
--- a/sdk/src/org/opends/sdk/responses/Responses.java
+++ b/sdk/src/org/opends/sdk/responses/Responses.java
@@ -36,8 +36,7 @@
 
 
 /**
- * This class contains various methods for creating and manipulating
- * responses.
+ * This class contains various methods for creating and manipulating responses.
  * <p>
  * TODO: search reference from LDAP URL.
  * <p>
@@ -61,7 +60,7 @@
    * @throws NullPointerException
    *           If {@code resultCode} was {@code null}.
    */
-  public static BindResult newBindResult(ResultCode resultCode)
+  public static BindResult newBindResult(final ResultCode resultCode)
       throws NullPointerException
   {
     Validator.ensureNotNull(resultCode);
@@ -79,7 +78,7 @@
    * @throws NullPointerException
    *           If {@code resultCode} was {@code null}.
    */
-  public static CompareResult newCompareResult(ResultCode resultCode)
+  public static CompareResult newCompareResult(final ResultCode resultCode)
       throws NullPointerException
   {
     Validator.ensureNotNull(resultCode);
@@ -89,8 +88,7 @@
 
 
   /**
-   * Creates a new generic extended result using the provided result
-   * code.
+   * Creates a new generic extended result using the provided result code.
    *
    * @param resultCode
    *          The result code.
@@ -99,7 +97,7 @@
    *           If {@code resultCode} was {@code null}.
    */
   public static GenericExtendedResult newGenericExtendedResult(
-      ResultCode resultCode) throws NullPointerException
+      final ResultCode resultCode) throws NullPointerException
   {
     Validator.ensureNotNull(resultCode);
     return new GenericExtendedResultImpl(resultCode);
@@ -120,24 +118,42 @@
 
 
   /**
-   * Creates a new generic intermediate response using the provided
-   * response name and value.
+   * Creates a new generic intermediate response using the provided response
+   * name and value.
    *
    * @param responseName
-   *          The dotted-decimal representation of the unique OID
-   *          corresponding to this intermediate response, which may be
-   *          {@code null} indicating that none was provided.
-   * @param responseValue
-   *          The response value associated with this generic
-   *          intermediate response, which may be {@code null}
+   *          The dotted-decimal representation of the unique OID corresponding
+   *          to this intermediate response, which may be {@code null}
    *          indicating that none was provided.
+   * @param responseValue
+   *          The response value associated with this generic intermediate
+   *          response, which may be {@code null} indicating that none was
+   *          provided.
    * @return The new generic intermediate response.
    */
   public static GenericIntermediateResponse newGenericIntermediateResponse(
-      String responseName, ByteString responseValue)
+      final String responseName, final ByteString responseValue)
   {
-    return new GenericIntermediateResponseImpl(responseName,
-        responseValue);
+    return new GenericIntermediateResponseImpl(responseName, responseValue);
+  }
+
+
+
+  /**
+   * Creates a new password modify extended result using the provided result
+   * code, and no generated password.
+   *
+   * @param resultCode
+   *          The result code.
+   * @return The new password modify extended result.
+   * @throws NullPointerException
+   *           If {@code resultCode} was {@code null}.
+   */
+  public static PasswordModifyExtendedResult newPasswordModifyExtendedResult(
+      final ResultCode resultCode) throws NullPointerException
+  {
+    Validator.ensureNotNull(resultCode);
+    return new PasswordModifyExtendedResultImpl(resultCode);
   }
 
 
@@ -151,7 +167,7 @@
    * @throws NullPointerException
    *           If {@code resultCode} was {@code null}.
    */
-  public static Result newResult(ResultCode resultCode)
+  public static Result newResult(final ResultCode resultCode)
       throws NullPointerException
   {
     Validator.ensureNotNull(resultCode);
@@ -161,8 +177,7 @@
 
 
   /**
-   * Creates a new search result entry using the provided distinguished
-   * name.
+   * Creates a new search result entry using the provided distinguished name.
    *
    * @param name
    *          The distinguished name of the entry.
@@ -170,10 +185,10 @@
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public static SearchResultEntry newSearchResultEntry(DN name)
+  public static SearchResultEntry newSearchResultEntry(final DN name)
       throws NullPointerException
   {
-    final Entry entry = new SortedEntry().setName(name);
+    final Entry entry = new LinkedHashMapEntry().setName(name);
     return new SearchResultEntryImpl(entry);
   }
 
@@ -181,10 +196,10 @@
 
   /**
    * Creates a new search result entry backed by the provided entry.
-   * Modifications made to {@code entry} will be reflected in the
-   * returned search result entry. The returned search result entry
-   * supports updates to its list of controls, as well as updates to the
-   * name and attributes if the underlying entry allows.
+   * Modifications made to {@code entry} will be reflected in the returned
+   * search result entry. The returned search result entry supports updates to
+   * its list of controls, as well as updates to the name and attributes if the
+   * underlying entry allows.
    *
    * @param entry
    *          The entry.
@@ -192,7 +207,7 @@
    * @throws NullPointerException
    *           If {@code entry} was {@code null} .
    */
-  public static SearchResultEntry newSearchResultEntry(Entry entry)
+  public static SearchResultEntry newSearchResultEntry(final Entry entry)
       throws NullPointerException
   {
     Validator.ensureNotNull(entry);
@@ -202,63 +217,62 @@
 
 
   /**
-   * Creates a new search result entry using the provided distinguished
-   * name decoded using the default schema.
+   * Creates a new search result entry using the provided distinguished name
+   * decoded using the default schema.
    *
    * @param name
    *          The distinguished name of the entry.
    * @return The new search result entry.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code name} could not be decoded using the default
-   *           schema.
+   *           If {@code name} could not be decoded using the default schema.
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public static SearchResultEntry newSearchResultEntry(String name)
+  public static SearchResultEntry newSearchResultEntry(final String name)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
-    final Entry entry = new SortedEntry().setName(name);
+    final Entry entry = new LinkedHashMapEntry().setName(name);
     return new SearchResultEntryImpl(entry);
   }
 
 
 
   /**
-   * Creates a new search result entry using the provided lines of LDIF
-   * decoded using the default schema.
+   * Creates a new search result entry using the provided lines of LDIF decoded
+   * using the default schema.
    *
    * @param ldifLines
-   *          Lines of LDIF containing an LDIF add change record or an
-   *          LDIF entry record.
+   *          Lines of LDIF containing an LDIF add change record or an LDIF
+   *          entry record.
    * @return The new search result entry.
    * @throws LocalizedIllegalArgumentException
-   *           If {@code ldifLines} was empty, or contained invalid
-   *           LDIF, or could not be decoded using the default schema.
+   *           If {@code ldifLines} was empty, or contained invalid LDIF, or
+   *           could not be decoded using the default schema.
    * @throws NullPointerException
    *           If {@code ldifLines} was {@code null} .
    */
   public static SearchResultEntry newSearchResultEntry(
-      String... ldifLines) throws LocalizedIllegalArgumentException,
+      final String... ldifLines) throws LocalizedIllegalArgumentException,
       NullPointerException
   {
-    return newSearchResultEntry(new SortedEntry(ldifLines));
+    return newSearchResultEntry(new LinkedHashMapEntry(ldifLines));
   }
 
 
 
   /**
-   * Creates a new search result reference using the provided
-   * continuation reference URI.
+   * Creates a new search result reference using the provided continuation
+   * reference URI.
    *
    * @param uri
-   *          The first continuation reference URI to be added to this
-   *          search result reference.
+   *          The first continuation reference URI to be added to this search
+   *          result reference.
    * @return The new search result reference.
    * @throws NullPointerException
    *           If {@code uri} was {@code null}.
    */
-  public static SearchResultReference newSearchResultReference(
-      String uri) throws NullPointerException
+  public static SearchResultReference newSearchResultReference(final String uri)
+      throws NullPointerException
   {
     Validator.ensureNotNull(uri);
     return new SearchResultReferenceImpl(uri);
@@ -266,6 +280,25 @@
 
 
 
+  /**
+   * Creates a new who am I extended result with the provided result code and no
+   * authorization ID.
+   *
+   * @param resultCode
+   *          The result code.
+   * @return The new who am I extended result.
+   * @throws NullPointerException
+   *           If {@code resultCode} was {@code null} .
+   */
+  public static final WhoAmIExtendedResult newWhoAmIExtendedResult(
+      final ResultCode resultCode) throws NullPointerException
+  {
+    Validator.ensureNotNull(resultCode);
+    return new WhoAmIExtendedResultImpl(ResultCode.SUCCESS);
+  }
+
+
+
   // Private constructor.
   private Responses()
   {
diff --git a/sdk/src/org/opends/sdk/responses/Result.java b/sdk/src/org/opends/sdk/responses/Result.java
index ad339e2..24ecd02 100644
--- a/sdk/src/org/opends/sdk/responses/Result.java
+++ b/sdk/src/org/opends/sdk/responses/Result.java
@@ -29,31 +29,36 @@
 
 
 
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.ResultCode;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * A Result is used to indicate the status of an operation performed by
- * the server. A Result is comprised of several fields:
+ * A Result is used to indicate the status of an operation performed by the
+ * server. A Result is comprised of several fields:
  * <ul>
  * <li>The <b>result code</b> can be retrieved using the method
- * {@link #getResultCode}. This indicates the overall outcome of the
- * operation. In particular, whether or not it succeeded which is
- * indicated using a value of {@link ResultCode#SUCCESS}.
- * <li>The optional <b>diagnostic message</b> can be retrieved using the
- * method {@link #getDiagnosticMessage}. At the server's discretion, a
- * diagnostic message may be included in a Result in order to supplement
- * the result code with additional human-readable information.
+ * {@link #getResultCode}. This indicates the overall outcome of the operation.
+ * In particular, whether or not it succeeded which is indicated using a value
+ * of {@link ResultCode#SUCCESS}.
+ * <li>The optional <b>diagnostic message</b> can be retrieved using the method
+ * {@link #getDiagnosticMessage}. At the server's discretion, a diagnostic
+ * message may be included in a Result in order to supplement the result code
+ * with additional human-readable information.
  * <li>The optional <b>matched DN</b> can be retrieved using the method
- * {@link #getMatchedDN}. For certain result codes, this is used to
- * indicate to the client the last entry used in finding the Request's
- * target (or base) entry.
+ * {@link #getMatchedDN}. For certain result codes, this is used to indicate to
+ * the client the last entry used in finding the Request's target (or base)
+ * entry.
  * <li>The optional <b>referrals</b> can be retrieved using the method
- * {@link #getReferralURIs}. Referrals are present in a Result if the
- * result code is set to {@link ResultCode#REFERRAL}, and it are absent
- * with all other result codes.
+ * {@link #getReferralURIs}. Referrals are present in a Result if the result
+ * code is set to {@link ResultCode#REFERRAL}, and it are absent with all other
+ * result codes.
  * </ul>
  */
 public interface Result extends Response
@@ -61,14 +66,14 @@
   /**
    * {@inheritDoc}
    */
-  Result addControl(Control control)
-      throws UnsupportedOperationException, NullPointerException;
+  Result addControl(Control control) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
    * Adds the provided referral URI to this result.
-   * 
+   *
    * @param uri
    *          The referral URI to be added.
    * @return This result.
@@ -77,35 +82,16 @@
    * @throws NullPointerException
    *           If {@code uri} was {@code null}.
    */
-  Result addReferralURI(String uri)
-      throws UnsupportedOperationException, NullPointerException;
+  Result addReferralURI(String uri) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
   /**
-   * {@inheritDoc}
-   */
-  Result clearControls() throws UnsupportedOperationException;
-
-
-
-  /**
-   * Removes all the referral URIs included with this result.
-   * 
-   * @return This result.
-   * @throws UnsupportedOperationException
-   *           If this result does not permit referral URIs to be
-   *           removed.
-   */
-  Result clearReferralURIs() throws UnsupportedOperationException;
-
-
-
-  /**
-   * Returns the throwable cause associated with this result if
-   * available. A cause may be provided in cases where a result
-   * indicates a failure due to a client-side error.
-   * 
+   * Returns the throwable cause associated with this result if available. A
+   * cause may be provided in cases where a result indicates a failure due to a
+   * client-side error.
+   *
    * @return The throwable cause, or {@code null} if none was provided.
    */
   Throwable getCause();
@@ -115,22 +101,23 @@
   /**
    * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  Iterable<Control> getControls();
+  List<Control> getControls();
 
 
 
   /**
    * Returns the diagnostic message associated with this result.
-   * 
-   * @return The diagnostic message, which may be empty if none was
-   *         provided (never {@code null}).
+   *
+   * @return The diagnostic message, which may be empty if none was provided
+   *         (never {@code null}).
    */
   String getDiagnosticMessage();
 
@@ -138,28 +125,28 @@
 
   /**
    * Returns the matched DN associated with this result.
-   * 
-   * @return The matched DN, which may be empty if none was provided
-   *         (never {@code null}).
+   *
+   * @return The matched DN, which may be empty if none was provided (never
+   *         {@code null}).
    */
   String getMatchedDN();
 
 
 
   /**
-   * Returns an {@code Iterable} containing the referral URIs included
-   * with this result. The returned {@code Iterable} may be used to
-   * remove referral URIs if permitted by this result.
-   * 
-   * @return An {@code Iterable} containing the referral URIs.
+   * Returns a {@code List} containing the referral URIs included with this
+   * result. The returned {@code List} may be modified if permitted by this
+   * result.
+   *
+   * @return A {@code List} containing the referral URIs.
    */
-  Iterable<String> getReferralURIs();
+  List<String> getReferralURIs();
 
 
 
   /**
    * Returns the result code associated with this result.
-   * 
+   *
    * @return The result code.
    */
   ResultCode getResultCode();
@@ -167,63 +154,37 @@
 
 
   /**
-   * {@inheritDoc}
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Indicates whether or not this result has any referral URIs.
-   * 
-   * @return {@code true} if this result has any referral URIs,
-   *         otherwise {@code false}.
-   */
-  boolean hasReferralURIs();
-
-
-
-  /**
-   * Indicates whether or not a referral needs to be chased in order to
-   * complete the operation.
+   * Indicates whether or not a referral needs to be chased in order to complete
+   * the operation.
    * <p>
-   * Specifically, this method returns {@code true} if the result code
-   * is equal to {@link ResultCode#REFERRAL}.
-   * 
-   * @return {@code true} if a referral needs to be chased, otherwise
-   *         {@code false}.
+   * Specifically, this method returns {@code true} if the result code is equal
+   * to {@link ResultCode#REFERRAL}.
+   *
+   * @return {@code true} if a referral needs to be chased, otherwise {@code
+   *         false}.
    */
   boolean isReferral();
 
 
 
   /**
-   * Indicates whether or not the request succeeded or not. This method
-   * will return {code true} for all non-error responses.
-   * 
-   * @return {@code true} if the request succeeded, otherwise {@code
-   *         false}.
+   * Indicates whether or not the request succeeded or not. This method will
+   * return {code true} for all non-error responses.
+   *
+   * @return {@code true} if the request succeeded, otherwise {@code false}.
    */
   boolean isSuccess();
 
 
 
   /**
-   * {@inheritDoc}
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
-  /**
-   * Sets the throwable cause associated with this result if available.
-   * A cause may be provided in cases where a result indicates a failure
-   * due to a client-side error.
-   * 
+   * Sets the throwable cause associated with this result if available. A cause
+   * may be provided in cases where a result indicates a failure due to a
+   * client-side error.
+   *
    * @param cause
-   *          The throwable cause, which may be {@code null} indicating
-   *          that none was provided.
+   *          The throwable cause, which may be {@code null} indicating that
+   *          none was provided.
    * @return This result.
    * @throws UnsupportedOperationException
    *           If this result does not permit the cause to be set.
@@ -234,14 +195,13 @@
 
   /**
    * Sets the diagnostic message associated with this result.
-   * 
+   *
    * @param message
    *          The diagnostic message, which may be empty or {@code null}
    *          indicating that none was provided.
    * @return This result.
    * @throws UnsupportedOperationException
-   *           If this result does not permit the diagnostic message to
-   *           be set.
+   *           If this result does not permit the diagnostic message to be set.
    */
   Result setDiagnosticMessage(String message)
       throws UnsupportedOperationException;
@@ -250,10 +210,10 @@
 
   /**
    * Sets the matched DN associated with this result.
-   * 
+   *
    * @param dn
-   *          The matched DN associated, which may be empty or {@code
-   *          null} indicating that none was provided.
+   *          The matched DN associated, which may be empty or {@code null}
+   *          indicating that none was provided.
    * @return This result.
    * @throws UnsupportedOperationException
    *           If this result does not permit the matched DN to be set.
@@ -264,7 +224,7 @@
 
   /**
    * Sets the result code associated with this result.
-   * 
+   *
    * @param resultCode
    *          The result code.
    * @return This result.
diff --git a/sdk/src/org/opends/sdk/responses/ResultImpl.java b/sdk/src/org/opends/sdk/responses/ResultImpl.java
index c050541..0e80959 100644
--- a/sdk/src/org/opends/sdk/responses/ResultImpl.java
+++ b/sdk/src/org/opends/sdk/responses/ResultImpl.java
@@ -36,19 +36,18 @@
 /**
  * A generic result indicates the final status of an operation.
  */
-final class ResultImpl extends AbstractResultImpl<Result> implements
-    Result
+final class ResultImpl extends AbstractResultImpl<Result> implements Result
 {
 
   /**
    * Creates a new generic result using the provided result code.
-   * 
+   *
    * @param resultCode
    *          The result code.
    * @throws NullPointerException
    *           If {@code resultCode} was {@code null}.
    */
-  ResultImpl(ResultCode resultCode) throws NullPointerException
+  ResultImpl(final ResultCode resultCode) throws NullPointerException
   {
     super(resultCode);
   }
@@ -78,6 +77,7 @@
 
 
 
+  @Override
   Result getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/responses/SearchResultEntry.java b/sdk/src/org/opends/sdk/responses/SearchResultEntry.java
index 456ab36..9da4d6a 100644
--- a/sdk/src/org/opends/sdk/responses/SearchResultEntry.java
+++ b/sdk/src/org/opends/sdk/responses/SearchResultEntry.java
@@ -30,46 +30,53 @@
 
 
 import java.util.Collection;
+import java.util.List;
 
 import org.opends.sdk.*;
 import org.opends.sdk.controls.Control;
-import org.opends.sdk.schema.ObjectClass;
-
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * A Search Result Entry represents an entry found during a Search
- * operation.
+ * A Search Result Entry represents an entry found during a Search operation.
  * <p>
- * Each entry returned in a Search Result Entry will contain all
- * appropriate attributes as specified in the Search request, subject to
- * access control and other administrative policy.
+ * Each entry returned in a Search Result Entry will contain all appropriate
+ * attributes as specified in the Search request, subject to access control and
+ * other administrative policy.
  * <p>
- * Note that a Search Result Entry may hold zero attributes. This may
- * happen when none of the attributes of an entry were requested or
- * could be returned.
+ * Note that a Search Result Entry may hold zero attributes. This may happen
+ * when none of the attributes of an entry were requested or could be returned.
  * <p>
- * Note also that each returned attribute may hold zero attribute
- * values. This may happen when only attribute types are requested,
- * access controls prevent the return of values, or other reasons.
+ * Note also that each returned attribute may hold zero attribute values. This
+ * may happen when only attribute types are requested, access controls prevent
+ * the return of values, or other reasons.
  */
 public interface SearchResultEntry extends Response, Entry
 {
+  /**
+   * {@inheritDoc}
+   */
   boolean addAttribute(Attribute attribute)
       throws UnsupportedOperationException, NullPointerException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   boolean addAttribute(Attribute attribute,
       Collection<ByteString> duplicateValues)
       throws UnsupportedOperationException, NullPointerException;
 
 
 
-  SearchResultEntry addAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
+  /**
+   * {@inheritDoc}
+   */
+  SearchResultEntry addAttribute(String attributeDescription, Object... values)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 
 
@@ -81,114 +88,117 @@
 
 
 
-  SearchResultEntry clearAttributes()
-      throws UnsupportedOperationException;
+  /**
+   * {@inheritDoc}
+   */
+  SearchResultEntry clearAttributes() throws UnsupportedOperationException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  SearchResultEntry clearControls()
-      throws UnsupportedOperationException;
+  boolean containsAttribute(Attribute attribute,
+      Collection<ByteString> missingValues) throws NullPointerException;
 
 
 
-  boolean containsAttribute(AttributeDescription attributeDescription)
-      throws NullPointerException;
-
-
-
-  boolean containsAttribute(String attributeDescription)
+  /**
+   * {@inheritDoc}
+   */
+  boolean containsAttribute(String attributeDescription, Object... values)
       throws LocalizedIllegalArgumentException, NullPointerException;
 
 
 
-  boolean containsObjectClass(ObjectClass objectClass)
+  /**
+   * {@inheritDoc}
+   */
+  Iterable<Attribute> getAllAttributes();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  Iterable<Attribute> getAllAttributes(AttributeDescription attributeDescription)
       throws NullPointerException;
 
 
 
-  boolean containsObjectClass(String objectClass)
-      throws NullPointerException;
-
-
-
-  Iterable<Attribute> findAttributes(
-      AttributeDescription attributeDescription)
-      throws NullPointerException;
-
-
-
-  Iterable<Attribute> findAttributes(String attributeDescription)
+  /**
+   * {@inheritDoc}
+   */
+  Iterable<Attribute> getAllAttributes(String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   Attribute getAttribute(AttributeDescription attributeDescription)
       throws NullPointerException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   Attribute getAttribute(String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   int getAttributeCount();
 
 
 
-  Iterable<Attribute> getAttributes();
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  List<Control> getControls();
 
 
 
   /**
    * {@inheritDoc}
    */
-  Iterable<Control> getControls();
-
-
-
   DN getName();
 
 
 
-  Iterable<String> getObjectClasses();
-
-
-
   /**
    * {@inheritDoc}
    */
-  boolean hasControls();
-
-
-
   boolean removeAttribute(Attribute attribute,
       Collection<ByteString> missingValues)
       throws UnsupportedOperationException, NullPointerException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   boolean removeAttribute(AttributeDescription attributeDescription)
       throws UnsupportedOperationException, NullPointerException;
 
 
 
-  SearchResultEntry removeAttribute(String attributeDescription)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
-
-
-
+  /**
+   * {@inheritDoc}
+   */
   SearchResultEntry removeAttribute(String attributeDescription,
       Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException;
@@ -198,29 +208,33 @@
   /**
    * {@inheritDoc}
    */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
-
-
-
   boolean replaceAttribute(Attribute attribute)
       throws UnsupportedOperationException, NullPointerException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   SearchResultEntry replaceAttribute(String attributeDescription,
       Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException;
 
 
 
-  SearchResultEntry setName(DN dn)
-      throws UnsupportedOperationException, NullPointerException;
+  /**
+   * {@inheritDoc}
+   */
+  SearchResultEntry setName(DN dn) throws UnsupportedOperationException,
+      NullPointerException;
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   SearchResultEntry setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException;
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException;
 
 }
diff --git a/sdk/src/org/opends/sdk/responses/SearchResultEntryImpl.java b/sdk/src/org/opends/sdk/responses/SearchResultEntryImpl.java
index a10ea46..424e567 100644
--- a/sdk/src/org/opends/sdk/responses/SearchResultEntryImpl.java
+++ b/sdk/src/org/opends/sdk/responses/SearchResultEntryImpl.java
@@ -32,8 +32,6 @@
 import java.util.Collection;
 
 import org.opends.sdk.*;
-import org.opends.sdk.schema.ObjectClass;
-
 
 
 
@@ -41,8 +39,7 @@
  * Search result entry implementation.
  */
 final class SearchResultEntryImpl extends
-    AbstractResponseImpl<SearchResultEntry> implements
-    SearchResultEntry
+    AbstractResponseImpl<SearchResultEntry> implements SearchResultEntry
 {
 
   private final Entry entry;
@@ -51,17 +48,17 @@
 
   /**
    * Creates a new search result entry backed by the provided entry.
-   * Modifications made to {@code entry} will be reflected in the
-   * returned search result entry. The returned search result entry
-   * supports updates to its list of controls, as well as updates to the
-   * name and attributes if the underlying entry allows.
+   * Modifications made to {@code entry} will be reflected in the returned
+   * search result entry. The returned search result entry supports updates to
+   * its list of controls, as well as updates to the name and attributes if the
+   * underlying entry allows.
    *
    * @param entry
    *          The entry.
    * @throws NullPointerException
    *           If {@code entry} was {@code null} .
    */
-  public SearchResultEntryImpl(Entry entry) throws NullPointerException
+  public SearchResultEntryImpl(final Entry entry) throws NullPointerException
   {
     this.entry = entry;
   }
@@ -71,7 +68,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean addAttribute(Attribute attribute)
+  public boolean addAttribute(final Attribute attribute)
       throws UnsupportedOperationException, NullPointerException
   {
     return entry.addAttribute(attribute);
@@ -82,8 +79,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean addAttribute(Attribute attribute,
-      Collection<ByteString> duplicateValues)
+  public boolean addAttribute(final Attribute attribute,
+      final Collection<ByteString> duplicateValues)
       throws UnsupportedOperationException, NullPointerException
   {
     return entry.addAttribute(attribute, duplicateValues);
@@ -94,8 +91,8 @@
   /**
    * {@inheritDoc}
    */
-  public SearchResultEntry addAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
+  public SearchResultEntry addAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException
   {
     entry.addAttribute(attributeDescription, values);
@@ -119,11 +116,10 @@
   /**
    * {@inheritDoc}
    */
-  public boolean containsAttribute(
-      AttributeDescription attributeDescription)
-      throws NullPointerException
+  public boolean containsAttribute(final Attribute attribute,
+      final Collection<ByteString> missingValues) throws NullPointerException
   {
-    return entry.containsAttribute(attributeDescription);
+    return entry.containsAttribute(attribute, missingValues);
   }
 
 
@@ -131,10 +127,44 @@
   /**
    * {@inheritDoc}
    */
-  public boolean containsAttribute(String attributeDescription)
+  public boolean containsAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
+      NullPointerException
+  {
+    return entry.containsAttribute(attributeDescription, values);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Iterable<Attribute> getAllAttributes()
+  {
+    return entry.getAllAttributes();
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Iterable<Attribute> getAllAttributes(
+      final AttributeDescription attributeDescription)
+      throws NullPointerException
+  {
+    return entry.getAllAttributes(attributeDescription);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public Iterable<Attribute> getAllAttributes(final String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
-    return entry.containsAttribute(attributeDescription);
+    return entry.getAllAttributes(attributeDescription);
   }
 
 
@@ -142,53 +172,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean containsObjectClass(ObjectClass objectClass)
-      throws NullPointerException
-  {
-    return entry.containsObjectClass(objectClass);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean containsObjectClass(String objectClass)
-      throws NullPointerException
-  {
-    return entry.containsObjectClass(objectClass);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Iterable<Attribute> findAttributes(
-      AttributeDescription attributeDescription)
-      throws NullPointerException
-  {
-    return entry.findAttributes(attributeDescription);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Iterable<Attribute> findAttributes(String attributeDescription)
-      throws LocalizedIllegalArgumentException, NullPointerException
-  {
-    return entry.findAttributes(attributeDescription);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Attribute getAttribute(
-      AttributeDescription attributeDescription)
+  public Attribute getAttribute(final AttributeDescription attributeDescription)
       throws NullPointerException
   {
     return entry.getAttribute(attributeDescription);
@@ -199,7 +183,7 @@
   /**
    * {@inheritDoc}
    */
-  public Attribute getAttribute(String attributeDescription)
+  public Attribute getAttribute(final String attributeDescription)
       throws LocalizedIllegalArgumentException, NullPointerException
   {
     return entry.getAttribute(attributeDescription);
@@ -220,16 +204,6 @@
   /**
    * {@inheritDoc}
    */
-  public Iterable<Attribute> getAttributes()
-  {
-    return entry.getAttributes();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
   public DN getName()
   {
     return entry.getName();
@@ -240,18 +214,8 @@
   /**
    * {@inheritDoc}
    */
-  public Iterable<String> getObjectClasses()
-  {
-    return entry.getObjectClasses();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public boolean removeAttribute(Attribute attribute,
-      Collection<ByteString> missingValues)
+  public boolean removeAttribute(final Attribute attribute,
+      final Collection<ByteString> missingValues)
       throws UnsupportedOperationException, NullPointerException
   {
     return entry.removeAttribute(attribute, missingValues);
@@ -262,8 +226,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean removeAttribute(
-      AttributeDescription attributeDescription)
+  public boolean removeAttribute(final AttributeDescription attributeDescription)
       throws UnsupportedOperationException, NullPointerException
   {
     return entry.removeAttribute(attributeDescription);
@@ -274,21 +237,8 @@
   /**
    * {@inheritDoc}
    */
-  public SearchResultEntry removeAttribute(String attributeDescription)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
-  {
-    entry.removeAttribute(attributeDescription);
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public SearchResultEntry removeAttribute(String attributeDescription,
-      Object... values) throws LocalizedIllegalArgumentException,
+  public SearchResultEntry removeAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException
   {
     entry.removeAttribute(attributeDescription, values);
@@ -300,7 +250,7 @@
   /**
    * {@inheritDoc}
    */
-  public boolean replaceAttribute(Attribute attribute)
+  public boolean replaceAttribute(final Attribute attribute)
       throws UnsupportedOperationException, NullPointerException
   {
     return entry.replaceAttribute(attribute);
@@ -311,9 +261,8 @@
   /**
    * {@inheritDoc}
    */
-  public SearchResultEntry replaceAttribute(
-      String attributeDescription, Object... values)
-      throws LocalizedIllegalArgumentException,
+  public SearchResultEntry replaceAttribute(final String attributeDescription,
+      final Object... values) throws LocalizedIllegalArgumentException,
       UnsupportedOperationException, NullPointerException
   {
     entry.replaceAttribute(attributeDescription, values);
@@ -325,7 +274,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchResultEntry setName(DN dn)
+  public SearchResultEntry setName(final DN dn)
       throws UnsupportedOperationException, NullPointerException
   {
     entry.setName(dn);
@@ -337,9 +286,9 @@
   /**
    * {@inheritDoc}
    */
-  public SearchResultEntry setName(String dn)
-      throws LocalizedIllegalArgumentException,
-      UnsupportedOperationException, NullPointerException
+  public SearchResultEntry setName(final String dn)
+      throws LocalizedIllegalArgumentException, UnsupportedOperationException,
+      NullPointerException
   {
     entry.setName(dn);
     return this;
@@ -357,7 +306,7 @@
     builder.append("SearchResultEntry(name=");
     builder.append(getName());
     builder.append(", attributes=");
-    builder.append(getAttributes());
+    builder.append(getAllAttributes());
     builder.append(", controls=");
     builder.append(getControls());
     builder.append(")");
@@ -366,8 +315,10 @@
 
 
 
+  @Override
   SearchResultEntry getThis()
   {
     return this;
   }
+
 }
diff --git a/sdk/src/org/opends/sdk/responses/SearchResultReference.java b/sdk/src/org/opends/sdk/responses/SearchResultReference.java
index 34cefbb..0d6f133 100644
--- a/sdk/src/org/opends/sdk/responses/SearchResultReference.java
+++ b/sdk/src/org/opends/sdk/responses/SearchResultReference.java
@@ -29,13 +29,18 @@
 
 
 
+import java.util.List;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
 import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
 
 
 
 /**
- * A Search Result Reference represents an area not yet explored during
- * a Search operation.
+ * A Search Result Reference represents an area not yet explored during a Search
+ * operation.
  */
 public interface SearchResultReference extends Response
 {
@@ -50,13 +55,13 @@
   /**
    * Adds the provided continuation reference URI to this search result
    * reference.
-   * 
+   *
    * @param uri
    *          The continuation reference URI to be added.
    * @return This search result reference.
    * @throws UnsupportedOperationException
-   *           If this search result reference does not permit
-   *           continuation reference URI to be added.
+   *           If this search result reference does not permit continuation
+   *           reference URI to be added.
    * @throws NullPointerException
    *           If {@code uri} was {@code null}.
    */
@@ -68,84 +73,25 @@
   /**
    * {@inheritDoc}
    */
-  SearchResultReference clearControls()
-      throws UnsupportedOperationException;
-
-
-
-  /**
-   * Removes all the continuation reference URIs included with this
-   * search result reference.
-   * 
-   * @return This search result reference.
-   * @throws UnsupportedOperationException
-   *           If this search result reference does not permit
-   *           continuation reference URIs to be removed.
-   */
-  SearchResultReference clearURIs()
-      throws UnsupportedOperationException;
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
 
 
 
   /**
    * {@inheritDoc}
    */
-  Control getControl(String oid) throws NullPointerException;
+  List<Control> getControls();
 
 
 
   /**
-   * {@inheritDoc}
+   * Returns a {@code List} containing the continuation reference URIs included
+   * with this search result reference. The returned {@code List} may be
+   * modified if permitted by this search result reference.
+   *
+   * @return A {@code List} containing the continuation reference URIs.
    */
-  Iterable<Control> getControls();
-
-
-
-  /**
-   * Returns the number of continuation reference URIs in this search
-   * result reference.
-   * 
-   * @return The number of continuation reference URIs.
-   */
-  int getURICount();
-
-
-
-  /**
-   * Returns an {@code Iterable} containing the continuation reference
-   * URIs included with this search result reference. The returned
-   * {@code Iterable} may be used to remove continuation reference URIs
-   * if permitted by this search result reference.
-   * 
-   * @return An {@code Iterable} containing the continuation reference
-   *         URIs.
-   */
-  Iterable<String> getURIs();
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  boolean hasControls();
-
-
-
-  /**
-   * Indicates whether or not this search result reference has any
-   * continuation reference URIs.
-   * 
-   * @return {@code true} if this search result reference has any
-   *         continuation reference URIs, otherwise {@code false}.
-   */
-  boolean hasURIs();
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  Control removeControl(String oid)
-      throws UnsupportedOperationException, NullPointerException;
+  List<String> getURIs();
 
 }
diff --git a/sdk/src/org/opends/sdk/responses/SearchResultReferenceImpl.java b/sdk/src/org/opends/sdk/responses/SearchResultReferenceImpl.java
index 204ef9c..abb900e 100644
--- a/sdk/src/org/opends/sdk/responses/SearchResultReferenceImpl.java
+++ b/sdk/src/org/opends/sdk/responses/SearchResultReferenceImpl.java
@@ -49,16 +49,16 @@
 
 
   /**
-   * Creates a new search result reference using the provided
-   * continuation reference URI.
-   * 
+   * Creates a new search result reference using the provided continuation
+   * reference URI.
+   *
    * @param uri
-   *          The first continuation reference URI to be added to this
-   *          search result reference.
+   *          The first continuation reference URI to be added to this search
+   *          result reference.
    * @throws NullPointerException
    *           If {@code uri} was {@code null}.
    */
-  SearchResultReferenceImpl(String uri) throws NullPointerException
+  SearchResultReferenceImpl(final String uri) throws NullPointerException
   {
     addURI(uri);
   }
@@ -68,7 +68,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchResultReference addURI(String uri)
+  public SearchResultReference addURI(final String uri)
       throws UnsupportedOperationException, NullPointerException
   {
     Validator.ensureNotNull(uri);
@@ -81,29 +81,7 @@
   /**
    * {@inheritDoc}
    */
-  public SearchResultReference clearURIs()
-      throws UnsupportedOperationException
-  {
-    uris.clear();
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public int getURICount()
-  {
-    return uris.size();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  public Iterable<String> getURIs()
+  public List<String> getURIs()
   {
     return uris;
   }
@@ -113,16 +91,6 @@
   /**
    * {@inheritDoc}
    */
-  public boolean hasURIs()
-  {
-    return !uris.isEmpty();
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
   @Override
   public String toString()
   {
@@ -137,6 +105,7 @@
 
 
 
+  @Override
   SearchResultReference getThis()
   {
     return this;
diff --git a/sdk/src/org/opends/sdk/responses/WhoAmIExtendedResult.java b/sdk/src/org/opends/sdk/responses/WhoAmIExtendedResult.java
new file mode 100644
index 0000000..32ec723
--- /dev/null
+++ b/sdk/src/org/opends/sdk/responses/WhoAmIExtendedResult.java
@@ -0,0 +1,220 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.responses;
+
+
+
+import java.util.List;
+
+import org.opends.sdk.*;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+
+
+
+/**
+ * The who am I extended result as defined in RFC 4532. The result includes the
+ * primary authorization identity, in its primary form, that the server has
+ * associated with the user or application entity, but only if the who am I
+ * request succeeded.
+ * <p>
+ * The authorization identity is specified using an authorization ID, or {@code
+ * authzId}, as defined in RFC 4513 section 5.2.1.8.
+ *
+ * @see org.opends.sdk.requests.WhoAmIExtendedRequest
+ * @see org.opends.sdk.controls.AuthorizationIdentityRequestControl
+ * @see <a href="http://tools.ietf.org/html/rfc4532">RFC 4532 - Lightweight
+ *      Directory Access Protocol (LDAP) "Who am I?" Operation </a>
+ * @see <a href="http://tools.ietf.org/html/rfc4513#section-5.2.1.8">RFC 4513 -
+ *      SASL Authorization Identities (authzId) </a>
+ */
+public interface WhoAmIExtendedResult extends ExtendedResult
+{
+
+  /**
+   * {@inheritDoc}
+   */
+  WhoAmIExtendedResult addControl(Control control)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  WhoAmIExtendedResult addReferralURI(String uri)
+      throws UnsupportedOperationException, NullPointerException;
+
+
+
+  /**
+   * Returns the authorization ID of the user. The authorization ID usually has
+   * the form "dn:" immediately followed by the distinguished name of the user,
+   * or "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @return The authorization ID of the user, or {@code null} if this result
+   *         does not contain an authorization ID.
+   */
+  String getAuthorizationID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  Throwable getCause();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  <C extends Control> C getControl(ControlDecoder<C> decoder,
+      DecodeOptions options) throws NullPointerException, DecodeException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<Control> getControls();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getDiagnosticMessage();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getMatchedDN();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  String getOID();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  List<String> getReferralURIs();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ResultCode getResultCode();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  ByteString getValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  boolean hasValue();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  boolean isReferral();
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  boolean isSuccess();
+
+
+
+  /**
+   * Sets the authorization ID of the user. The authorization ID usually has the
+   * form "dn:" immediately followed by the distinguished name of the user, or
+   * "u:" followed by a user ID string, but other forms are permitted.
+   *
+   * @param authorizationID
+   *          The authorization ID of the user, which may be {@code null} if
+   *          this result does not contain an authorization ID.
+   * @return This who am I result.
+   * @throws LocalizedIllegalArgumentException
+   *           If {@code authorizationID} was non-empty and did not contain a
+   *           valid authorization ID type.
+   */
+  WhoAmIExtendedResult setAuthorizationID(String authorizationID)
+      throws LocalizedIllegalArgumentException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  WhoAmIExtendedResult setCause(Throwable cause)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  WhoAmIExtendedResult setDiagnosticMessage(String message)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  WhoAmIExtendedResult setMatchedDN(String dn)
+      throws UnsupportedOperationException;
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  WhoAmIExtendedResult setResultCode(ResultCode resultCode)
+      throws UnsupportedOperationException, NullPointerException;
+
+}
diff --git a/sdk/src/org/opends/sdk/responses/WhoAmIExtendedResultImpl.java b/sdk/src/org/opends/sdk/responses/WhoAmIExtendedResultImpl.java
new file mode 100644
index 0000000..869cd78
--- /dev/null
+++ b/sdk/src/org/opends/sdk/responses/WhoAmIExtendedResultImpl.java
@@ -0,0 +1,152 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.responses;
+
+
+
+import static com.sun.opends.sdk.messages.Messages.ERR_WHOAMI_INVALID_AUTHZID_TYPE;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.LocalizableMessage;
+import org.opends.sdk.LocalizedIllegalArgumentException;
+import org.opends.sdk.ResultCode;
+
+
+
+/**
+ * Who Am I extended result implementation.
+ */
+final class WhoAmIExtendedResultImpl extends
+    AbstractExtendedResult<WhoAmIExtendedResult> implements
+    WhoAmIExtendedResult
+{
+
+  // The authorization ID.
+  private String authorizationID = null;
+
+
+
+  // Instantiation via factory.
+  WhoAmIExtendedResultImpl(final ResultCode resultCode)
+  {
+    super(resultCode);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public String getAuthorizationID()
+  {
+    return authorizationID;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String getOID()
+  {
+    // No response name defined.
+    return null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public ByteString getValue()
+  {
+    return (authorizationID != null) ? ByteString.valueOf(authorizationID)
+        : null;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean hasValue()
+  {
+    return (authorizationID != null);
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  public WhoAmIExtendedResult setAuthorizationID(final String authorizationID)
+      throws LocalizedIllegalArgumentException
+  {
+    if (authorizationID != null && authorizationID.length() != 0)
+    {
+      final int colonIndex = authorizationID.indexOf(':');
+      if (colonIndex < 0)
+      {
+        final LocalizableMessage message = ERR_WHOAMI_INVALID_AUTHZID_TYPE
+            .get(authorizationID);
+        throw new LocalizedIllegalArgumentException(message);
+      }
+    }
+
+    this.authorizationID = authorizationID;
+    return this;
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  public String toString()
+  {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("WhoAmIExtendedResponse(resultCode=");
+    builder.append(getResultCode());
+    builder.append(", matchedDN=");
+    builder.append(getMatchedDN());
+    builder.append(", diagnosticMessage=");
+    builder.append(getDiagnosticMessage());
+    builder.append(", referrals=");
+    builder.append(getReferralURIs());
+    builder.append(", authzId=");
+    builder.append(authorizationID);
+    builder.append(", controls=");
+    builder.append(getControls());
+    builder.append(")");
+    return builder.toString();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/responses/package-info.java b/sdk/src/org/opends/sdk/responses/package-info.java
index e69befe..66a69da 100755
--- a/sdk/src/org/opends/sdk/responses/package-info.java
+++ b/sdk/src/org/opends/sdk/responses/package-info.java
@@ -29,3 +29,6 @@
  * Classes and interfaces for core LDAP responses.
  */
 package org.opends.sdk.responses;
+
+
+
diff --git a/sdk/src/org/opends/sdk/sasl/AbstractSASLContext.java b/sdk/src/org/opends/sdk/sasl/AbstractSASLContext.java
deleted file mode 100644
index 4f6ff7d..0000000
--- a/sdk/src/org/opends/sdk/sasl/AbstractSASLContext.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-
-import java.io.IOException;
-
-import javax.security.auth.callback.*;
-import javax.security.sasl.AuthorizeCallback;
-import javax.security.sasl.RealmCallback;
-import javax.security.sasl.RealmChoiceCallback;
-import javax.security.sasl.SaslException;
-
-
-
-/**
- * An abstract SASL context.
- */
-abstract class AbstractSASLContext implements SASLContext,
-    CallbackHandler
-{
-  /**
-   * The name of the default protocol used.
-   */
-  static final String SASL_DEFAULT_PROTOCOL = "ldap";
-
-
-
-  public void handle(Callback[] callbacks) throws IOException,
-      UnsupportedCallbackException
-  {
-    for (Callback callback : callbacks)
-    {
-      if (callback instanceof NameCallback)
-      {
-        handle((NameCallback) callback);
-      }
-      else if (callback instanceof PasswordCallback)
-      {
-        handle((PasswordCallback) callback);
-      }
-      else if (callback instanceof AuthorizeCallback)
-      {
-        handle((AuthorizeCallback) callback);
-      }
-      else if (callback instanceof RealmCallback)
-      {
-        handle((RealmCallback) callback);
-      }
-      else if (callback instanceof RealmChoiceCallback)
-      {
-        handle((RealmChoiceCallback) callback);
-      }
-      else if (callback instanceof ChoiceCallback)
-      {
-        handle((ChoiceCallback) callback);
-      }
-      else if (callback instanceof ConfirmationCallback)
-      {
-        handle((ConfirmationCallback) callback);
-      }
-      else if (callback instanceof LanguageCallback)
-      {
-        handle((LanguageCallback) callback);
-      }
-      else if (callback instanceof TextInputCallback)
-      {
-        handle((TextInputCallback) callback);
-      }
-      else if (callback instanceof TextOutputCallback)
-      {
-        handle((TextOutputCallback) callback);
-      }
-      else
-      {
-        org.opends.sdk.LocalizableMessage message =
-            INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-                .getSASLMechanism(), String.valueOf(callback));
-        throw new UnsupportedCallbackException(callback, message
-            .toString());
-      }
-    }
-  }
-
-
-
-  /**
-   * Default implementation just returns the copy of the bytes.
-   */
-  public byte[] unwrap(byte[] incoming, int offset, int len)
-      throws SaslException
-  {
-    byte[] copy = new byte[len];
-    System.arraycopy(incoming, offset, copy, 0, len);
-    return copy;
-  }
-
-
-
-  /**
-   * Default implemenation just returns the copy of the bytes.
-   */
-  public byte[] wrap(byte[] outgoing, int offset, int len)
-      throws SaslException
-  {
-    byte[] copy = new byte[len];
-    System.arraycopy(outgoing, offset, copy, 0, len);
-    return copy;
-  }
-
-
-
-  void handle(AuthorizeCallback callback)
-      throws UnsupportedCallbackException
-  {
-    org.opends.sdk.LocalizableMessage message =
-        INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-            .getSASLMechanism(), String.valueOf(callback));
-    throw new UnsupportedCallbackException(callback, message.toString());
-  }
-
-
-
-  void handle(ChoiceCallback callback)
-      throws UnsupportedCallbackException
-  {
-    org.opends.sdk.LocalizableMessage message =
-        INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-            .getSASLMechanism(), String.valueOf(callback));
-    throw new UnsupportedCallbackException(callback, message.toString());
-  }
-
-
-
-  void handle(ConfirmationCallback callback)
-      throws UnsupportedCallbackException
-  {
-    org.opends.sdk.LocalizableMessage message =
-        INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-            .getSASLMechanism(), String.valueOf(callback));
-    throw new UnsupportedCallbackException(callback, message.toString());
-  }
-
-
-
-  void handle(LanguageCallback callback)
-      throws UnsupportedCallbackException
-  {
-    org.opends.sdk.LocalizableMessage message =
-        INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-            .getSASLMechanism(), String.valueOf(callback));
-    throw new UnsupportedCallbackException(callback, message.toString());
-  }
-
-
-
-  void handle(NameCallback callback)
-      throws UnsupportedCallbackException
-  {
-    org.opends.sdk.LocalizableMessage message =
-        INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-            .getSASLMechanism(), String.valueOf(callback));
-    throw new UnsupportedCallbackException(callback, message.toString());
-  }
-
-
-
-  void handle(PasswordCallback callback)
-      throws UnsupportedCallbackException
-  {
-    org.opends.sdk.LocalizableMessage message =
-        INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-            .getSASLMechanism(), String.valueOf(callback));
-    throw new UnsupportedCallbackException(callback, message.toString());
-  }
-
-
-
-  void handle(RealmCallback callback)
-      throws UnsupportedCallbackException
-  {
-    org.opends.sdk.LocalizableMessage message =
-        INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-            .getSASLMechanism(), String.valueOf(callback));
-    throw new UnsupportedCallbackException(callback, message.toString());
-  }
-
-
-
-  void handle(RealmChoiceCallback callback)
-      throws UnsupportedCallbackException
-  {
-    org.opends.sdk.LocalizableMessage message =
-        INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-            .getSASLMechanism(), String.valueOf(callback));
-    throw new UnsupportedCallbackException(callback, message.toString());
-  }
-
-
-
-  void handle(TextInputCallback callback)
-      throws UnsupportedCallbackException
-  {
-    org.opends.sdk.LocalizableMessage message =
-        INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-            .getSASLMechanism(), String.valueOf(callback));
-    throw new UnsupportedCallbackException(callback, message.toString());
-  }
-
-
-
-  void handle(TextOutputCallback callback)
-      throws UnsupportedCallbackException
-  {
-    org.opends.sdk.LocalizableMessage message =
-        INFO_SASL_UNSUPPORTED_CALLBACK.get(getSASLBindRequest()
-            .getSASLMechanism(), String.valueOf(callback));
-    throw new UnsupportedCallbackException(callback, message.toString());
-  }
-}
diff --git a/sdk/src/org/opends/sdk/sasl/AnonymousSASLBindRequest.java b/sdk/src/org/opends/sdk/sasl/AnonymousSASLBindRequest.java
deleted file mode 100644
index 58dbff6..0000000
--- a/sdk/src/org/opends/sdk/sasl/AnonymousSASLBindRequest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-
-import javax.security.sasl.SaslException;
-
-import org.opends.sdk.ByteString;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * Anonymous SASL bind request.
- */
-public final class AnonymousSASLBindRequest extends
-    SASLBindRequest<AnonymousSASLBindRequest> implements SASLContext
-{
-  /**
-   * The name of the SASL mechanism that does not provide any authentication but
-   * rather uses anonymous access.
-   */
-  public static final String SASL_MECHANISM_ANONYMOUS = "ANONYMOUS";
-
-  private String traceString;
-
-  public void dispose() throws SaslException
-  {
-    // Nothing needed.
-  }
-
-  public boolean evaluateCredentials(ByteString incomingCredentials)
-      throws SaslException
-  {
-    // This is a single stage SASL bind.
-    return true;
-  }
-
-
-  public boolean isComplete()
-  {
-    return true;
-  }
-
-  public boolean isSecure()
-  {
-    return false;
-  }
-
-  public ByteString getSASLCredentials()
-  {
-    return ByteString.valueOf(traceString);
-  }
-
-
-  public byte[] unwrap(byte[] incoming, int offset, int len)
-      throws SaslException
-  {
-    byte[] copy = new byte[len];
-    System.arraycopy(incoming, offset, copy, 0, len);
-    return copy;
-  }
-
-
-  public byte[] wrap(byte[] outgoing, int offset, int len)
-      throws SaslException
-  {
-    byte[] copy = new byte[len];
-    System.arraycopy(outgoing, offset, copy, 0, len);
-    return copy;
-  }
-
-  public AnonymousSASLBindRequest()
-  {
-    this.traceString = "".intern();
-  }
-
-
-
-  public AnonymousSASLBindRequest(String traceString)
-  {
-    Validator.ensureNotNull(traceString);
-    this.traceString = traceString;
-  }
-
-
-
-  public String getSASLMechanism()
-  {
-    return SASL_MECHANISM_ANONYMOUS;
-  }
-
-
-
-  public String getTraceString()
-  {
-    return traceString;
-  }
-
-
-
-  public SASLContext getClientContext(String serverName) throws SaslException
-  {
-    return this;
-  }
-
-  public AnonymousSASLBindRequest getSASLBindRequest() {
-    return this;
-  }
-
-  public AnonymousSASLBindRequest setTraceString(String traceString)
-  {
-    Validator.ensureNotNull(traceString);
-    this.traceString = traceString;
-    return this;
-  }
-
-
-
-  @Override
-  public String toString()
-  {
-    StringBuilder builder = new StringBuilder();
-    builder.append("AnonymousSASLBindRequest(bindDN=");
-    builder.append(getName());
-    builder.append(", authentication=SASL");
-    builder.append(", saslMechanism=");
-    builder.append(getSASLMechanism());
-    builder.append(", traceString=");
-    builder.append(traceString);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder.toString();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/sasl/CRAMMD5SASLBindRequest.java b/sdk/src/org/opends/sdk/sasl/CRAMMD5SASLBindRequest.java
deleted file mode 100644
index 0b3e57f..0000000
--- a/sdk/src/org/opends/sdk/sasl/CRAMMD5SASLBindRequest.java
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * CRAM-MD5 SASL bind request.
- */
-public final class CRAMMD5SASLBindRequest extends
-    SASLBindRequest<CRAMMD5SASLBindRequest>
-{
-  /**
-   * The name of the SASL mechanism based on CRAM-MD5 authentication.
-   */
-  public static final String SASL_MECHANISM_CRAM_MD5 = "CRAM-MD5";
-
-  private String authenticationID;
-  private ByteString password;
-
-  private NameCallbackHandler authIDHandler;
-  private PasswordCallbackHandler passHandler;
-
-  private class CRAMMD5SASLContext extends AbstractSASLContext
-  {
-    private SaslClient saslClient;
-    private ByteString outgoingCredentials = null;
-
-    private CRAMMD5SASLContext(String serverName) throws SaslException {
-      saslClient =
-          Sasl.createSaslClient(new String[] { SASL_MECHANISM_CRAM_MD5 },
-              null, SASL_DEFAULT_PROTOCOL, serverName, null, this);
-
-      if (saslClient.hasInitialResponse())
-      {
-        byte[] bytes = saslClient.evaluateChallenge(new byte[0]);
-        if (bytes != null)
-        {
-          this.outgoingCredentials = ByteString.wrap(bytes);
-        }
-      }
-    }
-
-    public void dispose() throws SaslException
-    {
-      saslClient.dispose();
-    }
-
-    public boolean evaluateCredentials(ByteString incomingCredentials)
-        throws SaslException
-    {
-      byte[] bytes =
-          saslClient.evaluateChallenge(incomingCredentials.toByteArray());
-      if (bytes != null)
-      {
-        this.outgoingCredentials = ByteString.wrap(bytes);
-      }
-      else
-      {
-        this.outgoingCredentials = null;
-      }
-
-      return isComplete();
-    }
-
-    public ByteString getSASLCredentials()
-    {
-      return outgoingCredentials;
-    }
-
-    public boolean isComplete()
-    {
-      return saslClient.isComplete();
-    }
-
-    public boolean isSecure()
-    {
-      return false;
-    }
-
-    @Override
-    protected void handle(NameCallback callback)
-        throws UnsupportedCallbackException
-    {
-      if (authIDHandler == null)
-      {
-        callback.setName(authenticationID);
-      }
-      else
-      {
-        if(authIDHandler.handle(callback))
-        {
-          authenticationID = callback.getName();
-          authIDHandler = null;
-        }
-      }
-    }
-
-    @Override
-    protected void handle(PasswordCallback callback)
-        throws UnsupportedCallbackException
-    {
-      if (passHandler == null)
-      {
-        callback.setPassword(password.toString().toCharArray());
-      }
-      else
-      {
-        if(passHandler.handle(callback))
-        {
-          password = ByteString.valueOf(callback.getPassword());
-          passHandler = null;
-        }
-      }
-    }
-
-    public CRAMMD5SASLBindRequest getSASLBindRequest() {
-      return CRAMMD5SASLBindRequest.this;
-    }
-  }
-
-  public CRAMMD5SASLBindRequest(DN authenticationDN, ByteString password)
-  {
-    Validator.ensureNotNull(authenticationDN, password);
-    this.authenticationID = "dn:" + authenticationDN.toString();
-    this.password = password;
-  }
-
-
-
-  public CRAMMD5SASLBindRequest(String authenticationID,
-                                ByteString password)
-  {
-    Validator.ensureNotNull(authenticationID, password);
-    this.authenticationID = authenticationID;
-    this.password = password;
-  }
-
-
-
-  public String getAuthenticationID()
-  {
-    return authenticationID;
-  }
-
-
-
-  public NameCallbackHandler getAuthIDHandler()
-  {
-    return authIDHandler;
-  }
-
-
-
-  public PasswordCallbackHandler getPassHandler()
-  {
-    return passHandler;
-  }
-
-
-
-  public ByteString getPassword()
-  {
-    return password;
-  }
-
-
-
-
-  public String getSASLMechanism()
-  {
-    return SASL_MECHANISM_CRAM_MD5;
-  }
-
-
-
-  public SASLContext getClientContext(String serverName) throws SaslException
-  {
-    return new CRAMMD5SASLContext(serverName);
-  }
-
-
-
-  public CRAMMD5SASLBindRequest setAuthenticationID(
-      String authenticationID)
-  {
-    Validator.ensureNotNull(authenticationID);
-    this.authenticationID = authenticationID;
-    return this;
-  }
-
-
-
-  public CRAMMD5SASLBindRequest setAuthIDHandler(
-      NameCallbackHandler authIDHandler)
-  {
-    this.authIDHandler = authIDHandler;
-    return this;
-  }
-
-
-
-  public CRAMMD5SASLBindRequest setPassHandler(
-      PasswordCallbackHandler passHandler)
-  {
-    this.passHandler = passHandler;
-    return this;
-  }
-
-
-
-  public CRAMMD5SASLBindRequest setPassword(ByteString password)
-  {
-    Validator.ensureNotNull(password);
-    this.password = password;
-    return this;
-  }
-
-
-
-  @Override
-  public String toString()
-  {
-    StringBuilder builder = new StringBuilder();
-    builder.append("CRAMMD5SASLBindRequest(bindDN=");
-    builder.append(getName());
-    builder.append(", authentication=SASL");
-    builder.append(", saslMechanism=");
-    builder.append(getSASLMechanism());
-    builder.append(", authenticationID=");
-    builder.append(authenticationID);
-    builder.append(", password=");
-    builder.append(password);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder.toString();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/sasl/DigestMD5SASLBindRequest.java b/sdk/src/org/opends/sdk/sasl/DigestMD5SASLBindRequest.java
deleted file mode 100644
index fc76f26..0000000
--- a/sdk/src/org/opends/sdk/sasl/DigestMD5SASLBindRequest.java
+++ /dev/null
@@ -1,437 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.sasl.RealmCallback;
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * Digest-MD5 SASL bind request.
- */
-public final class DigestMD5SASLBindRequest extends
-    SASLBindRequest<DigestMD5SASLBindRequest>
-{
-  /**
-   * The name of the SASL mechanism based on DIGEST-MD5 authentication.
-   */
-  public static final String SASL_MECHANISM_DIGEST_MD5 = "DIGEST-MD5";
-
-  private String authenticationID;
-  private String authorizationID;
-  private ByteString password;
-  private String realm;
-
-  private NameCallbackHandler authIDHandler;
-  private PasswordCallbackHandler passHandler;
-  private TextInputCallbackHandler realmHandler;
-
-  private class DigestMD5SASLContext extends AbstractSASLContext
-  {
-    private SaslClient saslClient;
-    private ByteString outgoingCredentials = null;
-
-    private DigestMD5SASLContext(String serverName) throws SaslException {
-      Map<String, String> props = new HashMap<String, String>();
-      props.put(Sasl.QOP, "auth-conf,auth-int,auth");
-      saslClient =
-          Sasl.createSaslClient(
-              new String[] { SASL_MECHANISM_DIGEST_MD5 },
-              authorizationID, SASL_DEFAULT_PROTOCOL, serverName, props,
-              this);
-
-      if (saslClient.hasInitialResponse())
-      {
-        byte[] bytes = saslClient.evaluateChallenge(new byte[0]);
-        if (bytes != null)
-        {
-          this.outgoingCredentials = ByteString.wrap(bytes);
-        }
-      }
-    }
-
-    public void dispose() throws SaslException
-    {
-      saslClient.dispose();
-    }
-
-    public boolean evaluateCredentials(ByteString incomingCredentials)
-        throws SaslException
-    {
-      byte[] bytes =
-          saslClient.evaluateChallenge(incomingCredentials.toByteArray());
-      if (bytes != null)
-      {
-        this.outgoingCredentials = ByteString.wrap(bytes);
-      }
-      else
-      {
-        this.outgoingCredentials = null;
-      }
-
-      return isComplete();
-    }
-
-    public ByteString getSASLCredentials()
-    {
-      return outgoingCredentials;
-    }
-
-
-    public boolean isComplete()
-    {
-      return saslClient.isComplete();
-    }
-
-
-
-    public boolean isSecure()
-    {
-      String qop = (String) saslClient.getNegotiatedProperty(Sasl.QOP);
-      return (qop.equalsIgnoreCase("auth-int") || qop
-          .equalsIgnoreCase("auth-conf"));
-    }
-
-    @Override
-    public byte[] unwrap(byte[] incoming, int offset, int len)
-        throws SaslException
-    {
-      return saslClient.unwrap(incoming, offset, len);
-    }
-
-
-
-    @Override
-    public byte[] wrap(byte[] outgoing, int offset, int len)
-        throws SaslException
-    {
-      return saslClient.wrap(outgoing, offset, len);
-    }
-
-
-
-    @Override
-    protected void handle(NameCallback callback)
-        throws UnsupportedCallbackException
-    {
-      if (authIDHandler == null)
-      {
-        callback.setName(authenticationID);
-      }
-      else
-      {
-        if(authIDHandler.handle(callback))
-        {
-          authenticationID = callback.getName();
-          authIDHandler = null;
-        }
-      }
-    }
-
-
-
-    @Override
-    protected void handle(PasswordCallback callback)
-        throws UnsupportedCallbackException
-    {
-      if (passHandler == null)
-      {
-        callback.setPassword(password.toString().toCharArray());
-      }
-      else
-      {
-        if(passHandler.handle(callback))
-        {
-          password = ByteString.valueOf(callback.getPassword());
-          passHandler = null;
-        }
-      }
-    }
-
-
-
-    @Override
-    protected void handle(RealmCallback callback)
-        throws UnsupportedCallbackException
-    {
-      if (realmHandler == null)
-      {
-        if (realm == null)
-        {
-          callback.setText(callback.getDefaultText());
-        }
-        else
-        {
-          callback.setText(realm);
-        }
-      }
-      else
-      {
-        if(realmHandler.handle(callback))
-        {
-          realm = callback.getText();
-          realmHandler = null;
-        }
-      }
-    }
-
-    public DigestMD5SASLBindRequest getSASLBindRequest() {
-      return DigestMD5SASLBindRequest.this;
-    }
-  }
-
-  public DigestMD5SASLBindRequest(DN authenticationDN,
-                                  ByteString password)
-  {
-    Validator.ensureNotNull(authenticationDN, password);
-    this.authenticationID = "dn:" + authenticationDN.toString();
-    this.password = password;
-  }
-
-
-
-  public DigestMD5SASLBindRequest(DN authenticationDN,
-                                  DN authorizationDN, ByteString password)
-  {
-    Validator
-        .ensureNotNull(authenticationDN, authorizationDN, password);
-    this.authenticationID = "dn:" + authenticationDN.toString();
-    this.authorizationID = "dn:" + authorizationDN.toString();
-    this.password = password;
-  }
-
-
-
-  public DigestMD5SASLBindRequest(DN authenticationDN,
-                                  DN authorizationDN, ByteString password, String realm)
-  {
-    Validator.ensureNotNull(authenticationDN, authorizationDN,
-        password);
-    this.authenticationID = "dn:" + authenticationDN.toString();
-    this.authorizationID = "dn:" + authorizationDN.toString();
-    this.password = password;
-    this.realm = realm;
-  }
-
-
-
-  public DigestMD5SASLBindRequest(String authenticationID,
-                                  ByteString password)
-  {
-    Validator.ensureNotNull(authenticationID, password);
-    this.authenticationID = authenticationID;
-    this.password = password;
-  }
-
-
-
-  public DigestMD5SASLBindRequest(String authenticationID,
-                                  String authorizationID, ByteString password)
-  {
-    Validator
-        .ensureNotNull(authenticationID, password);
-    this.authenticationID = authenticationID;
-    this.authorizationID = authorizationID;
-    this.password = password;
-  }
-
-
-
-  public DigestMD5SASLBindRequest(String authenticationID,
-                                  String authorizationID, ByteString password, String realm)
-  {
-    Validator.ensureNotNull(authenticationID, password);
-    this.authenticationID = authenticationID;
-    this.authorizationID = authorizationID;
-    this.password = password;
-    this.realm = realm;
-  }
-
-
-
-  public String getAuthenticationID()
-  {
-    return authenticationID;
-  }
-
-
-
-  public NameCallbackHandler getAuthIDHandler()
-  {
-    return authIDHandler;
-  }
-
-
-
-  public String getAuthorizationID()
-  {
-    return authorizationID;
-  }
-
-
-
-  public PasswordCallbackHandler getPassHandler()
-  {
-    return passHandler;
-  }
-
-
-
-  public ByteString getPassword()
-  {
-    return password;
-  }
-
-
-
-  public String getRealm()
-  {
-    return realm;
-  }
-
-
-
-  public TextInputCallbackHandler getRealmHandler()
-  {
-    return realmHandler;
-  }
-
-
-  @Override
-  public String getSASLMechanism()
-  {
-    return SASL_MECHANISM_DIGEST_MD5;
-  }
-
-
-
-  public SASLContext getClientContext(String serverName) throws SaslException
-  {
-    return new DigestMD5SASLContext(serverName);
-  }
-
-
-
-  public DigestMD5SASLBindRequest setAuthenticationID(
-      String authenticationID)
-  {
-    Validator.ensureNotNull(authenticationID);
-    this.authenticationID = authenticationID;
-    return this;
-  }
-
-
-
-  public DigestMD5SASLBindRequest setAuthIDHandler(
-      NameCallbackHandler authIDHandler)
-  {
-    this.authIDHandler = authIDHandler;
-    return this;
-  }
-
-
-
-  public DigestMD5SASLBindRequest setAuthorizationID(
-      String authorizationID)
-  {
-    this.authorizationID = authorizationID;
-    return this;
-  }
-
-
-
-  public DigestMD5SASLBindRequest setPassHandler(
-      PasswordCallbackHandler passHandler)
-  {
-    this.passHandler = passHandler;
-    return this;
-  }
-
-
-
-  public DigestMD5SASLBindRequest setPassword(ByteString password)
-  {
-    Validator.ensureNotNull(password);
-    this.password = password;
-    return this;
-  }
-
-
-
-  public DigestMD5SASLBindRequest setRealm(String realm)
-  {
-    this.realm = realm;
-    return this;
-  }
-
-
-
-  public void setRealmHandler(TextInputCallbackHandler realmHandler)
-  {
-    this.realmHandler = realmHandler;
-  }
-
-
-
-  @Override
-  public String toString()
-  {
-    StringBuilder builder = new StringBuilder();
-    builder.append("DigestMD5SASLBindRequest(bindDN=");
-    builder.append(getName());
-    builder.append(", authentication=SASL");
-    builder.append(", saslMechanism=");
-    builder.append(getSASLMechanism());
-    builder.append(", authenticationID=");
-    builder.append(authenticationID);
-    builder.append(", authorizationID=");
-    builder.append(authorizationID);
-    builder.append(", realm=");
-    builder.append(realm);
-    builder.append(", password=");
-    builder.append(password);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder.toString();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/sasl/ExternalSASLBindRequest.java b/sdk/src/org/opends/sdk/sasl/ExternalSASLBindRequest.java
deleted file mode 100644
index 82a11f6..0000000
--- a/sdk/src/org/opends/sdk/sasl/ExternalSASLBindRequest.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * External SASL bind request.
- */
-public final class ExternalSASLBindRequest extends
-    SASLBindRequest<ExternalSASLBindRequest>
-{
-  /**
-   * The name of the SASL mechanism based on external authentication.
-   */
-  public static final String SASL_MECHANISM_EXTERNAL = "EXTERNAL";
-
-  private String authorizationID;
-
-  private class ExternalSASLContext extends AbstractSASLContext
-  {
-    private SaslClient saslClient;
-    private ByteString outgoingCredentials = null;
-
-    private ExternalSASLContext(String serverName) throws SaslException {
-      saslClient =
-          Sasl.createSaslClient(new String[] { SASL_MECHANISM_EXTERNAL },
-              authorizationID, SASL_DEFAULT_PROTOCOL, serverName, null,
-              this);
-
-      if (saslClient.hasInitialResponse())
-      {
-        byte[] bytes = saslClient.evaluateChallenge(new byte[0]);
-        if (bytes != null)
-        {
-          this.outgoingCredentials = ByteString.wrap(bytes);
-        }
-      }
-    }
-
-    public void dispose() throws SaslException
-
-    {
-      saslClient.dispose();
-    }
-
-
-
-    public boolean evaluateCredentials(ByteString incomingCredentials)
-        throws SaslException
-    {
-      byte[] bytes =
-          saslClient.evaluateChallenge(incomingCredentials.toByteArray());
-      if (bytes != null)
-      {
-        this.outgoingCredentials = ByteString.wrap(bytes);
-      }
-      else
-      {
-        this.outgoingCredentials = null;
-      }
-
-      return isComplete();
-    }
-
-    public ByteString getSASLCredentials()
-    {
-      return outgoingCredentials;
-    }
-
-
-
-    public boolean isComplete()
-    {
-      return saslClient.isComplete();
-    }
-
-
-
-    public boolean isSecure()
-    {
-      return false;
-    }
-
-    public ExternalSASLBindRequest getSASLBindRequest() {
-      return ExternalSASLBindRequest.this;
-    }   
-  }
-
-  public ExternalSASLBindRequest()
-  {
-  }
-
-
-
-  public ExternalSASLBindRequest(DN authorizationDN)
-  {
-    Validator.ensureNotNull(authorizationDN);
-    this.authorizationID = "dn:" + authorizationDN.toString();
-  }
-
-
-
-  public ExternalSASLBindRequest(String authorizationID)
-  {
-    this.authorizationID = authorizationID;
-  }
-
-
-
-  public String getAuthorizationID()
-  {
-    return authorizationID;
-  }
-
-
-
-  public String getSASLMechanism()
-  {
-    return SASL_MECHANISM_EXTERNAL;
-  }
-
-
-
-  public SASLContext getClientContext(String serverName) throws SaslException
-  {
-    return new ExternalSASLContext(serverName);
-  }
-
-
-
-  public ExternalSASLBindRequest setAuthorizationID(
-      String authorizationID)
-  {
-    this.authorizationID = authorizationID;
-    return this;
-  }
-
-
-
-  @Override
-  public String toString()
-  {
-    StringBuilder builder = new StringBuilder();
-    builder.append("ExternalSASLBindRequest(bindDN=");
-    builder.append(getName());
-    builder.append(", authentication=SASL");
-    builder.append(", saslMechanism=");
-    builder.append(getSASLMechanism());
-    builder.append(", authorizationID=");
-    builder.append(authorizationID);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder.toString();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/sasl/GSSAPISASLBindRequest.java b/sdk/src/org/opends/sdk/sasl/GSSAPISASLBindRequest.java
deleted file mode 100644
index 54184f5..0000000
--- a/sdk/src/org/opends/sdk/sasl/GSSAPISASLBindRequest.java
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-
-
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginException;
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-import org.opends.sdk.LocalizableMessage;
-
-import com.sun.opends.sdk.util.Validator;
-import com.sun.security.auth.callback.TextCallbackHandler;
-import com.sun.security.auth.module.Krb5LoginModule;
-
-
-/**
- * GSSAPI SASL bind request.
- */
-public final class GSSAPISASLBindRequest extends
-    SASLBindRequest<GSSAPISASLBindRequest>
-{
-  /**
-   * The name of the SASL mechanism based on GSS-API authentication.
-   */
-  public static final String SASL_MECHANISM_GSSAPI = "GSSAPI";
-
-  private final Subject subject;
-  private String authorizationID;
-
-  private class GSSAPISASLContext extends AbstractSASLContext
-  {
-    private String serverName;
-    private SaslClient saslClient;
-    private ByteString outgoingCredentials = null;
-
-    private ByteString incomingCredentials;
-
-    PrivilegedExceptionAction<Boolean> evaluateAction =
-        new PrivilegedExceptionAction<Boolean>()
-        {
-          public Boolean run() throws Exception
-          {
-            byte[] bytes =
-                saslClient.evaluateChallenge(incomingCredentials
-                    .toByteArray());
-            if (bytes != null)
-            {
-              outgoingCredentials = ByteString.wrap(bytes);
-            }
-            else
-            {
-              outgoingCredentials = null;
-            }
-
-            return isComplete();
-          }
-        };
-
-    PrivilegedExceptionAction<Object> invokeAction =
-        new PrivilegedExceptionAction<Object>()
-        {
-          public Object run() throws Exception
-          {
-            Map<String, String> props = new HashMap<String, String>();
-            props.put(Sasl.QOP, "auth-conf,auth-int,auth");
-            saslClient =
-                Sasl.createSaslClient(
-                    new String[] { SASL_MECHANISM_GSSAPI },
-                    authorizationID, SASL_DEFAULT_PROTOCOL, serverName,
-                    props, GSSAPISASLContext.this);
-
-            if (saslClient.hasInitialResponse())
-            {
-              byte[] bytes = saslClient.evaluateChallenge(new byte[0]);
-              if (bytes != null)
-              {
-                outgoingCredentials = ByteString.wrap(bytes);
-              }
-            }
-            return null;
-          }
-        };
-
-    private GSSAPISASLContext(String serverName) throws SaslException {
-      this.serverName = serverName;
-
-      try
-      {
-        Subject.doAs(subject, invokeAction);
-      }
-      catch (PrivilegedActionException e)
-      {
-        if (e.getCause() instanceof SaslException)
-        {
-          throw (SaslException) e.getCause();
-        }
-
-        // This should not happen. Must be a bug.
-        LocalizableMessage msg =
-            ERR_SASL_CONTEXT_CREATE_ERROR.get(SASL_MECHANISM_GSSAPI,
-                getExceptionMessage(e));
-        throw new SaslException(msg.toString(), e.getCause());
-      }
-    }
-
-    public void dispose() throws SaslException
-    {
-      saslClient.dispose();
-    }
-
-
-
-    public boolean evaluateCredentials(ByteString incomingCredentials)
-        throws SaslException
-    {
-      this.incomingCredentials = incomingCredentials;
-      try
-      {
-        return Subject.doAs(subject, evaluateAction);
-      }
-      catch (PrivilegedActionException e)
-      {
-        if (e.getCause() instanceof SaslException)
-        {
-          throw (SaslException) e.getCause();
-        }
-
-        // This should not happen. Must be a bug.
-        LocalizableMessage msg =
-            ERR_SASL_PROTOCOL_ERROR.get(SASL_MECHANISM_GSSAPI,
-                getExceptionMessage(e));
-        throw new SaslException(msg.toString(), e.getCause());
-      }
-    }
-
-    public ByteString getSASLCredentials()
-    {
-      return outgoingCredentials;
-    }
-
-
-
-    public boolean isComplete()
-    {
-      return saslClient.isComplete();
-    }
-
-
-
-    public boolean isSecure()
-    {
-      String qop = (String) saslClient.getNegotiatedProperty(Sasl.QOP);
-      return (qop.equalsIgnoreCase("auth-int") || qop
-          .equalsIgnoreCase("auth-conf"));
-    }
-
-    public GSSAPISASLBindRequest getSASLBindRequest() {
-      return GSSAPISASLBindRequest.this;
-    }
-  }
-
-
-  public GSSAPISASLBindRequest(Subject subject)
-  {
-    Validator.ensureNotNull(subject);
-    this.subject = subject;
-  }
-
-
-
-  public GSSAPISASLBindRequest(Subject subject, DN authorizationDN)
-  {
-    Validator.ensureNotNull(subject, authorizationDN);
-    this.subject = subject;
-    this.authorizationID = "dn:" + authorizationDN.toString();
-  }
-
-
-
-  public GSSAPISASLBindRequest(Subject subject, String authorizationID)
-  {
-    Validator.ensureNotNull(subject);
-    this.subject = subject;
-    this.authorizationID = authorizationID;
-  }
-
-
-
-  public String getAuthorizationID()
-  {
-    return authorizationID;
-  }
-
-
-
-  public String getSASLMechanism()
-  {
-    return SASL_MECHANISM_GSSAPI;
-  }
-
-
-
-  public SASLContext getClientContext(String serverName) throws SaslException
-  {
-    return new GSSAPISASLContext(serverName);
-  }
-
-
-
-  public GSSAPISASLBindRequest setAuthorizationID(String authorizationID)
-  {
-    this.authorizationID = authorizationID;
-    return this;
-  }
-
-
-
-  @Override
-  public String toString()
-  {
-    StringBuilder builder = new StringBuilder();
-    builder.append("GSSAPISASLBindRequest(bindDN=");
-    builder.append(getName());
-    builder.append(", authentication=SASL");
-    builder.append(", saslMechanism=");
-    builder.append(getSASLMechanism());
-    builder.append(", subject=");
-    builder.append(subject);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder.toString();
-  }
-
-  public static Subject Kerberos5Login(String authenticationID,
-                                       ByteString password,
-                                       String realm, String kdc)
-      throws LoginException {
-    Map<String, Object> state = new HashMap<String, Object>();
-    state.put("javax.security.auth.login.name", authenticationID);
-    state.put("javax.security.auth.login.password",
-        password.toString().toCharArray());
-    state.put("javax.security.auth.useSubjectCredsOnly", "true");
-    state.put("java.security.krb5.realm", realm);
-    state.put("java.security.krb5.kdc", kdc);
-
-    Map<String, Object> options = new HashMap<String, Object>();
-    options.put("debug", "true");
-    options.put("tryFirstPass", "true");
-    options.put("useTicketCache", "true");
-    options.put("doNotPrompt", "true");
-    options.put("storePass", "false");
-    options.put("forwardable", "true");
-
-    Subject subject = new Subject();
-    Krb5LoginModule login = new Krb5LoginModule();
-    login.initialize(subject, new TextCallbackHandler(), state,
-        options);
-    if(login.login()){
-      login.commit();
-    }
-    return subject;
-  }
-}
diff --git a/sdk/src/org/opends/sdk/sasl/GenericSASLBindRequest.java b/sdk/src/org/opends/sdk/sasl/GenericSASLBindRequest.java
deleted file mode 100644
index 1c1102b..0000000
--- a/sdk/src/org/opends/sdk/sasl/GenericSASLBindRequest.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-
-
-import javax.security.sasl.SaslException;
-
-import org.opends.sdk.ByteString;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-/**
- * Generic SASL bind request.
- */
-public class GenericSASLBindRequest extends
-    SASLBindRequest<GenericSASLBindRequest> implements SASLContext
-{
-  // The SASL credentials.
-  private ByteString saslCredentials;
-
-  // The SASL mechanism.
-  private String saslMechanism;
-
-
-
-  public GenericSASLBindRequest(String saslMechanism,
-      ByteString saslCredentials)
-  {
-    Validator.ensureNotNull(saslMechanism);
-    this.saslCredentials = saslCredentials;
-    this.saslMechanism = saslMechanism;
-  }
-
-  public void dispose() throws SaslException
-  {
-    // Nothing needed.
-  }
-
-  public boolean evaluateCredentials(ByteString incomingCredentials)
-      throws SaslException
-  {
-    // This is a single stage SASL bind.
-    return true;
-  }
-
-
-  public boolean isComplete()
-  {
-    return true;
-  }
-
-  public boolean isSecure()
-  {
-    return false;
-  }
-
-
-  public byte[] unwrap(byte[] incoming, int offset, int len)
-      throws SaslException
-  {
-    byte[] copy = new byte[len];
-    System.arraycopy(incoming, offset, copy, 0, len);
-    return copy;
-  }
-
-
-  public byte[] wrap(byte[] outgoing, int offset, int len)
-      throws SaslException
-  {
-    byte[] copy = new byte[len];
-    System.arraycopy(outgoing, offset, copy, 0, len);
-    return copy;
-  }
-
-  public ByteString getSASLCredentials()
-  {
-    return saslCredentials;
-  }
-
-  public String getSASLMechanism()
-  {
-    return saslMechanism;
-  }
-
-  public SASLContext getClientContext(String serverName) throws SaslException
-  {
-    return this;
-  }
-
-  public GenericSASLBindRequest getSASLBindRequest() {
-    return this;
-  }
-
-  /**
-   * Sets the SASL credentials for this bind request.
-   *
-   * @param saslCredentials
-   *          The SASL credentials for this bind request, or {@code
-   *          null} if there are none or if the bind does not use SASL
-   *          authentication.
-   * @return This raw bind request.
-   */
-  public GenericSASLBindRequest setSASLCredentials(
-      ByteString saslCredentials)
-  {
-    this.saslCredentials = saslCredentials;
-    return this;
-  }
-
-
-
-  /**
-   * Sets The SASL mechanism for this bind request.
-   *
-   * @param saslMechanism
-   *          The SASL mechanism for this bind request, or {@code null}
-   *          if there are none or if the bind does not use SASL
-   *          authentication.
-   * @return This raw bind request.
-   */
-  public GenericSASLBindRequest setSASLMechanism(String saslMechanism)
-  {
-    Validator.ensureNotNull(saslMechanism);
-    this.saslMechanism = saslMechanism;
-    return this;
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  public String toString()
-  {
-    StringBuilder builder = new StringBuilder();
-    builder.append("SASLBindRequest(bindDN=");
-    builder.append(getName());
-    builder.append(", authentication=SASL");
-    builder.append(", saslMechanism=");
-    builder.append(saslMechanism);
-    builder.append(", saslCredentials=");
-    builder.append(saslCredentials);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder.toString();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/sasl/NameCallbackHandler.java b/sdk/src/org/opends/sdk/sasl/NameCallbackHandler.java
deleted file mode 100644
index 913e3c0..0000000
--- a/sdk/src/org/opends/sdk/sasl/NameCallbackHandler.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-
-
-import javax.security.auth.callback.NameCallback;
-
-
-
-/**
- * Name call-back.
- */
-public interface NameCallbackHandler
-{
-  public boolean handle(NameCallback callback);
-}
diff --git a/sdk/src/org/opends/sdk/sasl/PlainSASLBindRequest.java b/sdk/src/org/opends/sdk/sasl/PlainSASLBindRequest.java
deleted file mode 100644
index dcfbec4..0000000
--- a/sdk/src/org/opends/sdk/sasl/PlainSASLBindRequest.java
+++ /dev/null
@@ -1,321 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.sasl.Sasl;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-import org.opends.sdk.ByteString;
-import org.opends.sdk.DN;
-
-import com.sun.opends.sdk.util.Validator;
-
-
-
-/**
- * Plain SASL bind request.
- */
-public final class PlainSASLBindRequest extends
-    SASLBindRequest<PlainSASLBindRequest>
-{
-  /**
-   * The name of the SASL mechanism based on PLAIN authentication.
-   */
-  public static final String SASL_MECHANISM_PLAIN = "PLAIN";
-
-  private String authenticationID;
-  private String authorizationID;
-  private ByteString password;
-
-  private NameCallbackHandler authIDHandler;
-  private PasswordCallbackHandler passHandler;
-
-  private class PlainSASLContext extends AbstractSASLContext
-  {
-    private SaslClient saslClient;
-    private ByteString outgoingCredentials = null;
-
-    private PlainSASLContext(String serverName) throws SaslException {
-      saslClient =
-          Sasl.createSaslClient(new String[] { SASL_MECHANISM_PLAIN },
-              authorizationID, SASL_DEFAULT_PROTOCOL, serverName, null,
-              this);
-
-      if (saslClient.hasInitialResponse())
-      {
-        byte[] bytes = saslClient.evaluateChallenge(new byte[0]);
-        if (bytes != null)
-        {
-          this.outgoingCredentials = ByteString.wrap(bytes);
-        }
-      }
-    }
-
-    public void dispose() throws SaslException
-    {
-      saslClient.dispose();
-    }
-
-
-
-    public boolean evaluateCredentials(ByteString incomingCredentials)
-        throws SaslException
-    {
-      byte[] bytes =
-          saslClient.evaluateChallenge(incomingCredentials.toByteArray());
-      if (bytes != null)
-      {
-        this.outgoingCredentials = ByteString.wrap(bytes);
-      }
-      else
-      {
-        this.outgoingCredentials = null;
-      }
-
-      return isComplete();
-    }
-
-
-    public ByteString getSASLCredentials()
-    {
-      return outgoingCredentials;
-    }
-
-
-
-    public boolean isComplete()
-    {
-      return saslClient.isComplete();
-    }
-
-
-
-    public boolean isSecure()
-    {
-      return false;
-    }
-
-
-
-    @Override
-    protected void handle(NameCallback callback)
-        throws UnsupportedCallbackException
-    {
-      if (authIDHandler == null)
-      {
-        callback.setName(authenticationID);
-      }
-      else
-      {
-        if(authIDHandler.handle(callback))
-        {
-          authenticationID = callback.getName();
-          authIDHandler = null;
-        }
-      }
-    }
-
-
-
-    @Override
-    protected void handle(PasswordCallback callback)
-        throws UnsupportedCallbackException
-    {
-      if (passHandler == null)
-      {
-        callback.setPassword(password.toString().toCharArray());
-      }
-      else
-      {
-        if(passHandler.handle(callback))
-        {
-          password = ByteString.valueOf(callback.getPassword());
-          passHandler = null;
-        }
-      }
-    }
-
-    public PlainSASLBindRequest getSASLBindRequest() {
-      return PlainSASLBindRequest.this;
-    }
-  }
-
-  public PlainSASLBindRequest(DN authenticationDN, ByteString password)
-  {
-    Validator.ensureNotNull(authenticationDN, password);
-    this.authenticationID = "dn:" + authenticationDN.toString();
-    this.password = password;
-  }
-
-
-
-  public PlainSASLBindRequest(DN authenticationDN, DN authorizationDN,
-                              ByteString password)
-  {
-    Validator
-        .ensureNotNull(authenticationDN, authorizationDN, password);
-    this.authenticationID = "dn:" + authenticationDN.toString();
-    this.authorizationID = "dn:" + authorizationDN.toString();
-    this.password = password;
-  }
-
-
-
-  public PlainSASLBindRequest(String authenticationID,
-                              ByteString password)
-  {
-    Validator.ensureNotNull(authenticationID, password);
-    this.authenticationID = authenticationID;
-    this.password = password;
-  }
-
-
-
-  public PlainSASLBindRequest(String authenticationID,
-                              String authorizationID, ByteString password)
-  {
-    Validator
-        .ensureNotNull(authenticationID, password);
-    this.authenticationID = authenticationID;
-    this.authorizationID = authorizationID;
-    this.password = password;
-  }
-
-
-
-  public String getAuthenticationID()
-  {
-    return authenticationID;
-  }
-
-
-
-  public NameCallbackHandler getAuthIDHandler()
-  {
-    return authIDHandler;
-  }
-
-
-
-  public String getAuthorizationID()
-  {
-    return authorizationID;
-  }
-
-
-
-  public PasswordCallbackHandler getPassHandler()
-  {
-    return passHandler;
-  }
-
-
-
-  public ByteString getPassword()
-  {
-    return password;
-  }
-
-
-
-  public String getSASLMechanism()
-  {
-    return SASL_MECHANISM_PLAIN;
-  }
-
-
-
-  public SASLContext getClientContext(String serverName) throws SaslException
-  {
-    return new PlainSASLContext(serverName);
-  }
-
-
-
-  public PlainSASLBindRequest setAuthenticationID(
-      String authenticationID)
-  {
-    Validator.ensureNotNull(authenticationID);
-    this.authenticationID = authenticationID;
-    return this;
-  }
-
-
-
-  public PlainSASLBindRequest setAuthIDHandler(
-      NameCallbackHandler authIDHandler)
-  {
-    this.authIDHandler = authIDHandler;
-    return this;
-  }
-
-
-
-  public PlainSASLBindRequest setPassHandler(
-      PasswordCallbackHandler passHandler)
-  {
-    this.passHandler = passHandler;
-    return this;
-  }
-
-
-
-  public PlainSASLBindRequest setPassword(ByteString password)
-  {
-    Validator.ensureNotNull(password);
-    this.password = password;
-    return this;
-  }
-
-
-
-  @Override
-  public String toString()
-  {
-    StringBuilder builder = new StringBuilder();
-    builder.append("PlainSASLBindRequest(bindDN=");
-    builder.append(getName());
-    builder.append(", authentication=SASL");
-    builder.append(", saslMechanism=");
-    builder.append(getSASLMechanism());
-    builder.append(", authenticationID=");
-    builder.append(authenticationID);
-    builder.append(", authorizationID=");
-    builder.append(authorizationID);
-    builder.append(", password=");
-    builder.append(password);
-    builder.append(", controls=");
-    builder.append(getControls());
-    builder.append(")");
-    return builder.toString();
-  }
-}
diff --git a/sdk/src/org/opends/sdk/sasl/SASLBindRequest.java b/sdk/src/org/opends/sdk/sasl/SASLBindRequest.java
deleted file mode 100644
index 0401e38..0000000
--- a/sdk/src/org/opends/sdk/sasl/SASLBindRequest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-
-
-import javax.security.sasl.SaslException;
-
-import org.opends.sdk.DN;
-import org.opends.sdk.requests.AbstractBindRequest;
-
-
-
-/**
- * SASL bind request.
- */
-public abstract class SASLBindRequest<R extends SASLBindRequest<R>>
-    extends AbstractBindRequest<R>
-{
-  /**
-   * Returns the SASL mechanism for this bind request.
-   *
-   * @return The SASL mechanism for this bind request, or {@code null}
-   *         if there are none or if the bind does not use SASL
-   *         authentication.
-   */
-  public abstract String getSASLMechanism();
-
-
-
-  public abstract SASLContext getClientContext(String serverName)
-      throws SaslException;
-
-
-
-  public DN getName()
-  {
-    return DN.rootDN();
-  }
-
-}
diff --git a/sdk/src/org/opends/sdk/sasl/SASLContext.java b/sdk/src/org/opends/sdk/sasl/SASLContext.java
deleted file mode 100644
index 3f666a0..0000000
--- a/sdk/src/org/opends/sdk/sasl/SASLContext.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-
-
-import javax.security.sasl.SaslException;
-
-import org.opends.sdk.ByteString;
-
-
-
-/**
- * SASL context that is used for the lifetime of the SASL bound connection.
- */
-public interface SASLContext
-{
-  public void dispose() throws SaslException;
-
-  /**
-   * Returns the SASL credentials for this bind request.
-   *
-   * @return The SASL credentials for this bind request, or {@code null}
-   *         if there are none or if the bind does not use SASL
-   *         authentication.
-   */
-  public ByteString getSASLCredentials();
-
-
-  public boolean evaluateCredentials(ByteString saslCredentials)
-      throws SaslException;
-
-
-
-  public boolean isComplete();
-
-
-
-  public boolean isSecure();
-
-
-
-  public byte[] unwrap(byte[] incoming, int offset, int len)
-      throws SaslException;
-
-
-
-  public byte[] wrap(byte[] outgoing, int offset, int len)
-      throws SaslException;
-
-  public SASLBindRequest<?> getSASLBindRequest();
-}
diff --git a/sdk/src/org/opends/sdk/sasl/TextInputCallbackHandler.java b/sdk/src/org/opends/sdk/sasl/TextInputCallbackHandler.java
deleted file mode 100644
index 6712689..0000000
--- a/sdk/src/org/opends/sdk/sasl/TextInputCallbackHandler.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk.sasl;
-
-
-
-import javax.security.auth.callback.TextInputCallback;
-
-
-
-/**
- * Text input call-back.
- */
-public interface TextInputCallbackHandler
-{
-  public boolean handle(TextInputCallback callback);
-}
diff --git a/sdk/src/org/opends/sdk/schema/AbstractMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/AbstractMatchingRuleImpl.java
index 3de718d..2e9309c 100644
--- a/sdk/src/org/opends/sdk/schema/AbstractMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/AbstractMatchingRuleImpl.java
@@ -39,8 +39,8 @@
 
 
 /**
- * This class implements a default equality or approximate matching rule
- * that matches normalized values in byte order.
+ * This class implements a default equality or approximate matching rule that
+ * matches normalized values in byte order.
  */
 abstract class AbstractMatchingRuleImpl implements MatchingRuleImpl
 {
@@ -51,36 +51,37 @@
 
 
     protected DefaultEqualityAssertion(
-        ByteSequence normalizedAssertionValue)
+        final ByteSequence normalizedAssertionValue)
     {
       this.normalizedAssertionValue = normalizedAssertionValue;
     }
 
 
 
-    public ConditionResult matches(ByteSequence attributeValue)
+    public ConditionResult matches(final ByteSequence attributeValue)
     {
       return normalizedAssertionValue.equals(attributeValue) ? ConditionResult.TRUE
           : ConditionResult.FALSE;
     }
   }
 
+
+
   private static final Assertion UNDEFINED_ASSERTION = new Assertion()
   {
-    public ConditionResult matches(ByteSequence attributeValue)
+    public ConditionResult matches(final ByteSequence attributeValue)
     {
       return ConditionResult.UNDEFINED;
     }
   };
 
-  private static final Comparator<ByteSequence> DEFAULT_COMPARATOR =
-      new Comparator<ByteSequence>()
-      {
-        public int compare(ByteSequence o1, ByteSequence o2)
-        {
-          return o1.compareTo(o2);
-        }
-      };
+  private static final Comparator<ByteSequence> DEFAULT_COMPARATOR = new Comparator<ByteSequence>()
+  {
+    public int compare(final ByteSequence o1, final ByteSequence o2)
+    {
+      return o1.compareTo(o2);
+    }
+  };
 
 
 
@@ -91,41 +92,41 @@
 
 
 
-  public Comparator<ByteSequence> comparator(Schema schema)
+  public Comparator<ByteSequence> comparator(final Schema schema)
   {
     return DEFAULT_COMPARATOR;
   }
 
 
 
-  public Assertion getAssertion(Schema schema, ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
-    return new DefaultEqualityAssertion(normalizeAttributeValue(schema,
-        value));
+    return new DefaultEqualityAssertion(normalizeAttributeValue(schema, value));
   }
 
 
 
-  public Assertion getAssertion(Schema schema, ByteSequence subInitial,
-      List<? extends ByteSequence> subAnyElements, ByteSequence subFinal)
-      throws DecodeException
+  public Assertion getAssertion(final Schema schema,
+      final ByteSequence subInitial,
+      final List<? extends ByteSequence> subAnyElements,
+      final ByteSequence subFinal) throws DecodeException
   {
     return UNDEFINED_ASSERTION;
   }
 
 
 
-  public Assertion getGreaterOrEqualAssertion(Schema schema,
-      ByteSequence value) throws DecodeException
+  public Assertion getGreaterOrEqualAssertion(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     return UNDEFINED_ASSERTION;
   }
 
 
 
-  public Assertion getLessOrEqualAssertion(Schema schema,
-      ByteSequence value) throws DecodeException
+  public Assertion getLessOrEqualAssertion(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     return UNDEFINED_ASSERTION;
   }
diff --git a/sdk/src/org/opends/sdk/schema/AbstractOrderingMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/AbstractOrderingMatchingRuleImpl.java
index 2746636..db6822b 100644
--- a/sdk/src/org/opends/sdk/schema/AbstractOrderingMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/AbstractOrderingMatchingRuleImpl.java
@@ -47,14 +47,13 @@
 
 
   @Override
-  public Assertion getAssertion(Schema schema, ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
-    final ByteString normAssertion =
-        normalizeAttributeValue(schema, value);
+    final ByteString normAssertion = normalizeAttributeValue(schema, value);
     return new Assertion()
     {
-      public ConditionResult matches(ByteSequence attributeValue)
+      public ConditionResult matches(final ByteSequence attributeValue)
       {
         return attributeValue.compareTo(normAssertion) < 0 ? ConditionResult.TRUE
             : ConditionResult.FALSE;
@@ -65,14 +64,13 @@
 
 
   @Override
-  public Assertion getGreaterOrEqualAssertion(Schema schema,
-      ByteSequence value) throws DecodeException
+  public Assertion getGreaterOrEqualAssertion(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
-    final ByteString normAssertion =
-        normalizeAttributeValue(schema, value);
+    final ByteString normAssertion = normalizeAttributeValue(schema, value);
     return new Assertion()
     {
-      public ConditionResult matches(ByteSequence attributeValue)
+      public ConditionResult matches(final ByteSequence attributeValue)
       {
         return attributeValue.compareTo(normAssertion) >= 0 ? ConditionResult.TRUE
             : ConditionResult.FALSE;
@@ -83,14 +81,13 @@
 
 
   @Override
-  public Assertion getLessOrEqualAssertion(Schema schema,
-      ByteSequence value) throws DecodeException
+  public Assertion getLessOrEqualAssertion(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
-    final ByteString normAssertion =
-        normalizeAttributeValue(schema, value);
+    final ByteString normAssertion = normalizeAttributeValue(schema, value);
     return new Assertion()
     {
-      public ConditionResult matches(ByteSequence attributeValue)
+      public ConditionResult matches(final ByteSequence attributeValue)
       {
         return attributeValue.compareTo(normAssertion) <= 0 ? ConditionResult.TRUE
             : ConditionResult.FALSE;
diff --git a/sdk/src/org/opends/sdk/schema/AbstractSubstringMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/AbstractSubstringMatchingRuleImpl.java
index 785b730..1885f48 100644
--- a/sdk/src/org/opends/sdk/schema/AbstractSubstringMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/AbstractSubstringMatchingRuleImpl.java
@@ -35,7 +35,6 @@
 
 import org.opends.sdk.*;
 
-import com.sun.opends.sdk.util.StaticUtils;
 import com.sun.opends.sdk.util.SubstringReader;
 
 
@@ -55,8 +54,8 @@
 
 
 
-    protected DefaultSubstringAssertion(ByteString normInitial,
-        ByteString[] normAnys, ByteString normFinal)
+    protected DefaultSubstringAssertion(final ByteString normInitial,
+        final ByteString[] normAnys, final ByteString normFinal)
     {
       this.normInitial = normInitial;
       this.normAnys = normAnys;
@@ -65,7 +64,7 @@
 
 
 
-    public ConditionResult matches(ByteSequence attributeValue)
+    public ConditionResult matches(final ByteSequence attributeValue)
     {
       final int valueLength = attributeValue.length();
 
@@ -164,13 +163,12 @@
 
 
   @Override
-  public Assertion getAssertion(Schema schema, ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     if (value.length() == 0)
     {
-      throw DecodeException.error(
-          WARN_ATTR_SYNTAX_SUBSTRING_EMPTY.get());
+      throw DecodeException.error(WARN_ATTR_SYNTAX_SUBSTRING_EMPTY.get());
     }
 
     ByteSequence initialString = null;
@@ -181,36 +179,33 @@
 
     if (valueString.length() == 1 && valueString.charAt(0) == '*')
     {
-      return getAssertion(schema, initialString, anyStrings,
-          finalString);
+      return getAssertion(schema, initialString, anyStrings, finalString);
     }
 
     final char[] escapeChars = new char[] { '*' };
     final SubstringReader reader = new SubstringReader(valueString);
 
-    ByteString bytes =
-        StaticUtils.evaluateEscapes(reader, escapeChars, false);
+    ByteString bytes = evaluateEscapes(reader, escapeChars, false);
     if (bytes.length() > 0)
     {
       initialString = normalizeSubString(schema, bytes);
     }
     if (reader.remaining() == 0)
     {
-      throw DecodeException.error(
-          WARN_ATTR_SYNTAX_SUBSTRING_NO_WILDCARDS
-              .get(value.toString()));
+      throw DecodeException.error(WARN_ATTR_SYNTAX_SUBSTRING_NO_WILDCARDS
+          .get(value.toString()));
     }
     while (true)
     {
       reader.read();
-      bytes = StaticUtils.evaluateEscapes(reader, escapeChars, false);
+      bytes = evaluateEscapes(reader, escapeChars, false);
       if (reader.remaining() > 0)
       {
         if (bytes.length() == 0)
         {
-          throw DecodeException.error(
-              WARN_ATTR_SYNTAX_SUBSTRING_CONSECUTIVE_WILDCARDS
-                  .get(value.toString(), reader.pos()));
+          throw DecodeException
+              .error(WARN_ATTR_SYNTAX_SUBSTRING_CONSECUTIVE_WILDCARDS.get(value
+                  .toString(), reader.pos()));
         }
         if (anyStrings == null)
         {
@@ -234,13 +229,13 @@
 
 
   @Override
-  public Assertion getAssertion(Schema schema, ByteSequence subInitial,
-      List<? extends ByteSequence> subAnyElements, ByteSequence subFinal)
-      throws DecodeException
+  public Assertion getAssertion(final Schema schema,
+      final ByteSequence subInitial,
+      final List<? extends ByteSequence> subAnyElements,
+      final ByteSequence subFinal) throws DecodeException
   {
-    final ByteString normInitial =
-        subInitial == null ? null : normalizeSubString(schema,
-            subInitial);
+    final ByteString normInitial = subInitial == null ? null
+        : normalizeSubString(schema, subInitial);
 
     ByteString[] normAnys = null;
     if (subAnyElements != null && !subAnyElements.isEmpty())
@@ -251,18 +246,294 @@
         normAnys[i] = normalizeSubString(schema, subAnyElements.get(i));
       }
     }
-    final ByteString normFinal =
-        subFinal == null ? null : normalizeSubString(schema, subFinal);
+    final ByteString normFinal = subFinal == null ? null : normalizeSubString(
+        schema, subFinal);
 
-    return new DefaultSubstringAssertion(normInitial, normAnys,
-        normFinal);
+    return new DefaultSubstringAssertion(normInitial, normAnys, normFinal);
   }
 
 
 
-  ByteString normalizeSubString(Schema schema, ByteSequence value)
+  ByteString normalizeSubString(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     return normalizeAttributeValue(schema, value);
   }
+
+
+
+  private char evaluateEscapedChar(final SubstringReader reader,
+      final char[] escapeChars) throws DecodeException
+  {
+    final char c1 = reader.read();
+    byte b;
+    switch (c1)
+    {
+    case '0':
+      b = 0x00;
+      break;
+    case '1':
+      b = 0x10;
+      break;
+    case '2':
+      b = 0x20;
+      break;
+    case '3':
+      b = 0x30;
+      break;
+    case '4':
+      b = 0x40;
+      break;
+    case '5':
+      b = 0x50;
+      break;
+    case '6':
+      b = 0x60;
+      break;
+    case '7':
+      b = 0x70;
+      break;
+    case '8':
+      b = (byte) 0x80;
+      break;
+    case '9':
+      b = (byte) 0x90;
+      break;
+    case 'A':
+    case 'a':
+      b = (byte) 0xA0;
+      break;
+    case 'B':
+    case 'b':
+      b = (byte) 0xB0;
+      break;
+    case 'C':
+    case 'c':
+      b = (byte) 0xC0;
+      break;
+    case 'D':
+    case 'd':
+      b = (byte) 0xD0;
+      break;
+    case 'E':
+    case 'e':
+      b = (byte) 0xE0;
+      break;
+    case 'F':
+    case 'f':
+      b = (byte) 0xF0;
+      break;
+    default:
+      if (c1 == 0x5C)
+      {
+        return c1;
+      }
+      if (escapeChars != null)
+      {
+        for (final char escapeChar : escapeChars)
+        {
+          if (c1 == escapeChar)
+          {
+            return c1;
+          }
+        }
+      }
+      final LocalizableMessage message = ERR_INVALID_ESCAPE_CHAR.get(reader
+          .getString(), c1);
+      throw DecodeException.error(message);
+    }
+
+    // The two positions must be the hex characters that
+    // comprise the escaped value.
+    if (reader.remaining() == 0)
+    {
+      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_LENGTH
+          .get(reader.getString());
+
+      throw DecodeException.error(message);
+    }
+
+    final char c2 = reader.read();
+    switch (c2)
+    {
+    case '0':
+      // No action required.
+      break;
+    case '1':
+      b |= 0x01;
+      break;
+    case '2':
+      b |= 0x02;
+      break;
+    case '3':
+      b |= 0x03;
+      break;
+    case '4':
+      b |= 0x04;
+      break;
+    case '5':
+      b |= 0x05;
+      break;
+    case '6':
+      b |= 0x06;
+      break;
+    case '7':
+      b |= 0x07;
+      break;
+    case '8':
+      b |= 0x08;
+      break;
+    case '9':
+      b |= 0x09;
+      break;
+    case 'A':
+    case 'a':
+      b |= 0x0A;
+      break;
+    case 'B':
+    case 'b':
+      b |= 0x0B;
+      break;
+    case 'C':
+    case 'c':
+      b |= 0x0C;
+      break;
+    case 'D':
+    case 'd':
+      b |= 0x0D;
+      break;
+    case 'E':
+    case 'e':
+      b |= 0x0E;
+      break;
+    case 'F':
+    case 'f':
+      b |= 0x0F;
+      break;
+    default:
+      final LocalizableMessage message = ERR_HEX_DECODE_INVALID_CHARACTER.get(
+          new String(new char[] { c1, c2 }), c1);
+      throw DecodeException.error(message);
+    }
+    return (char) b;
+  }
+
+
+
+  private ByteString evaluateEscapes(final SubstringReader reader,
+      final char[] escapeChars, final boolean trim) throws DecodeException
+  {
+    return evaluateEscapes(reader, escapeChars, escapeChars, trim);
+  }
+
+
+
+  private ByteString evaluateEscapes(final SubstringReader reader,
+      final char[] escapeChars, final char[] delimiterChars, final boolean trim)
+      throws DecodeException
+  {
+    int length = 0;
+    int lengthWithoutSpace = 0;
+    char c;
+    ByteStringBuilder valueBuffer = null;
+
+    if (trim)
+    {
+      reader.skipWhitespaces();
+    }
+
+    reader.mark();
+    while (reader.remaining() > 0)
+    {
+      c = reader.read();
+      if (c == 0x5C) // The backslash character
+      {
+        if (valueBuffer == null)
+        {
+          valueBuffer = new ByteStringBuilder();
+        }
+        valueBuffer.append(reader.read(length));
+        valueBuffer.append(evaluateEscapedChar(reader, escapeChars));
+        reader.mark();
+        length = lengthWithoutSpace = 0;
+      }
+      if (delimiterChars != null)
+      {
+        for (final char delimiterChar : delimiterChars)
+        {
+          if (c == delimiterChar)
+          {
+            reader.reset();
+            if (valueBuffer != null)
+            {
+              if (trim)
+              {
+                valueBuffer.append(reader.read(lengthWithoutSpace));
+              }
+              else
+              {
+                valueBuffer.append(reader.read(length));
+              }
+              return valueBuffer.toByteString();
+            }
+            else
+            {
+              if (trim)
+              {
+                if (lengthWithoutSpace > 0)
+                {
+                  return ByteString.valueOf(reader.read(lengthWithoutSpace));
+                }
+                return ByteString.empty();
+              }
+              if (length > 0)
+              {
+                return ByteString.valueOf(reader.read(length));
+              }
+              return ByteString.empty();
+            }
+          }
+        }
+      }
+      length++;
+      if (c != ' ')
+      {
+        lengthWithoutSpace = length;
+      }
+      else
+      {
+        lengthWithoutSpace++;
+      }
+    }
+
+    reader.reset();
+    if (valueBuffer != null)
+    {
+      if (trim)
+      {
+        valueBuffer.append(reader.read(lengthWithoutSpace));
+      }
+      else
+      {
+        valueBuffer.append(reader.read(length));
+      }
+      return valueBuffer.toByteString();
+    }
+    else
+    {
+      if (trim)
+      {
+        if (lengthWithoutSpace > 0)
+        {
+          return ByteString.valueOf(reader.read(lengthWithoutSpace));
+        }
+        return ByteString.empty();
+      }
+      if (length > 0)
+      {
+        return ByteString.valueOf(reader.read(length));
+      }
+      return ByteString.empty();
+    }
+  }
 }
diff --git a/sdk/src/org/opends/sdk/schema/AbstractSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/AbstractSyntaxImpl.java
index 22c1717..81ac6a0 100644
--- a/sdk/src/org/opends/sdk/schema/AbstractSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/AbstractSyntaxImpl.java
@@ -30,8 +30,8 @@
 
 
 /**
- * This class defines the set of methods and structures that must be
- * implemented to define a new attribute syntax.
+ * This class defines the set of methods and structures that must be implemented
+ * to define a new attribute syntax.
  */
 abstract class AbstractSyntaxImpl implements SyntaxImpl
 {
diff --git a/sdk/src/org/opends/sdk/schema/AttributeType.java b/sdk/src/org/opends/sdk/schema/AttributeType.java
index 6f5788a..bba7148 100644
--- a/sdk/src/org/opends/sdk/schema/AttributeType.java
+++ b/sdk/src/org/opends/sdk/schema/AttributeType.java
@@ -30,7 +30,7 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.SCHEMA_PROPERTY_APPROX_RULE;
 
 import java.util.Collections;
 import java.util.Iterator;
@@ -45,14 +45,14 @@
 
 
 /**
- * This class defines a data structure for storing and interacting with
- * an attribute type, which contains information about the format of an
- * attribute and the syntax and matching rules that should be used when
- * interacting with it.
+ * This class defines a data structure for storing and interacting with an
+ * attribute type, which contains information about the format of an attribute
+ * and the syntax and matching rules that should be used when interacting with
+ * it.
  * <p>
- * Where ordered sets of names, or extra properties are provided, the
- * ordering will be preserved when the associated fields are accessed
- * via their getters or via the {@link #toString()} methods.
+ * Where ordered sets of names, or extra properties are provided, the ordering
+ * will be preserved when the associated fields are accessed via their getters
+ * or via the {@link #toString()} methods.
  */
 public final class AttributeType extends SchemaElement implements
     Comparable<AttributeType>
@@ -129,13 +129,14 @@
 
 
 
-  AttributeType(String oid, List<String> names, String description,
-      boolean obsolete, String superiorType,
-      String equalityMatchingRule, String orderingMatchingRule,
-      String substringMatchingRule, String approximateMatchingRule,
-      String syntax, boolean singleValue, boolean collective,
-      boolean noUserModification, AttributeUsage attributeUsage,
-      Map<String, List<String>> extraProperties, String definition)
+  AttributeType(final String oid, final List<String> names,
+      final String description, final boolean obsolete,
+      final String superiorType, final String equalityMatchingRule,
+      final String orderingMatchingRule, final String substringMatchingRule,
+      final String approximateMatchingRule, final String syntax,
+      final boolean singleValue, final boolean collective,
+      final boolean noUserModification, final AttributeUsage attributeUsage,
+      final Map<String, List<String>> extraProperties, final String definition)
   {
     super(description, extraProperties);
 
@@ -173,8 +174,9 @@
 
 
 
-  AttributeType(String oid, List<String> names, String description,
-      MatchingRule equalityMatchingRule, Syntax syntax)
+  AttributeType(final String oid, final List<String> names,
+      final String description, final MatchingRule equalityMatchingRule,
+      final Syntax syntax)
   {
     super(description, Collections.<String, List<String>> emptyMap());
 
@@ -205,24 +207,24 @@
 
 
   /**
-   * Compares this attribute type to the provided attribute type. The
-   * sort-order is defined as follows:
+   * Compares this attribute type to the provided attribute type. The sort-order
+   * is defined as follows:
    * <ul>
-   * <li>The {@code objectClass} attribute is less than all other
-   * attribute types.
+   * <li>The {@code objectClass} attribute is less than all other attribute
+   * types.
    * <li>User attributes are less than operational attributes.
    * <li>Lexicographic comparison of the primary name or OID.
    * </ul>
    *
    * @param type
    *          The attribute type to be compared.
-   * @return A negative integer, zero, or a positive integer as this
-   *         attribute type is less than, equal to, or greater than the
-   *         specified attribute type.
+   * @return A negative integer, zero, or a positive integer as this attribute
+   *         type is less than, equal to, or greater than the specified
+   *         attribute type.
    * @throws NullPointerException
    *           If {@code name} was {@code null}.
    */
-  public int compareTo(AttributeType type) throws NullPointerException
+  public int compareTo(final AttributeType type) throws NullPointerException
   {
     if (isObjectClassType)
     {
@@ -251,7 +253,7 @@
 
 
   @Override
-  public boolean equals(Object o)
+  public boolean equals(final Object o)
   {
     if (this == o)
     {
@@ -270,11 +272,11 @@
 
 
   /**
-   * Retrieves the matching rule that should be used for approximate
-   * matching with this attribute type.
+   * Returns the matching rule that should be used for approximate matching with
+   * this attribute type.
    *
-   * @return The matching rule that should be used for approximate
-   *         matching with this attribute type.
+   * @return The matching rule that should be used for approximate matching with
+   *         this attribute type.
    */
   public MatchingRule getApproximateMatchingRule()
   {
@@ -284,11 +286,11 @@
 
 
   /**
-   * Retrieves the matching rule that should be used for equality
-   * matching with this attribute type.
+   * Returns the matching rule that should be used for equality matching with
+   * this attribute type.
    *
-   * @return The matching rule that should be used for equality matching
-   *         with this attribute type.
+   * @return The matching rule that should be used for equality matching with
+   *         this attribute type.
    */
   public MatchingRule getEqualityMatchingRule()
   {
@@ -298,9 +300,9 @@
 
 
   /**
-   * Retrieves the name or OID for this schema definition. If it has one
-   * or more names, then the primary name will be returned. If it does
-   * not have any names, then the OID will be returned.
+   * Returns the name or OID for this schema definition. If it has one or more
+   * names, then the primary name will be returned. If it does not have any
+   * names, then the OID will be returned.
    *
    * @return The name or OID for this schema definition.
    */
@@ -316,13 +318,13 @@
 
 
   /**
-   * Retrieves an iterable over the set of user-defined names that may
-   * be used to reference this schema definition.
+   * Returns an unmodifiable list containing the user-defined names that may be
+   * used to reference this schema definition.
    *
-   * @return Returns an iterable over the set of user-defined names that
+   * @return Returns an unmodifiable list containing the user-defined names that
    *         may be used to reference this schema definition.
    */
-  public Iterable<String> getNames()
+  public List<String> getNames()
   {
     return names;
   }
@@ -330,7 +332,7 @@
 
 
   /**
-   * Retrieves the OID for this schema definition.
+   * Returns the OID for this schema definition.
    *
    * @return The OID for this schema definition.
    */
@@ -343,11 +345,11 @@
 
 
   /**
-   * Retrieves the matching rule that should be used for ordering with
-   * this attribute type.
+   * Returns the matching rule that should be used for ordering with this
+   * attribute type.
    *
-   * @return The matching rule that should be used for ordering with
-   *         this attribute type.
+   * @return The matching rule that should be used for ordering with this
+   *         attribute type.
    */
   public MatchingRule getOrderingMatchingRule()
   {
@@ -357,11 +359,11 @@
 
 
   /**
-   * Retrieves the matching rule that should be used for substring
-   * matching with this attribute type.
+   * Returns the matching rule that should be used for substring matching with
+   * this attribute type.
    *
-   * @return The matching rule that should be used for substring
-   *         matching with this attribute type.
+   * @return The matching rule that should be used for substring matching with
+   *         this attribute type.
    */
   public MatchingRule getSubstringMatchingRule()
   {
@@ -371,10 +373,10 @@
 
 
   /**
-   * Retrieves the superior type for this attribute type.
+   * Returns the superior type for this attribute type.
    *
-   * @return The superior type for this attribute type, or
-   *         <CODE>null</CODE> if it does not have one.
+   * @return The superior type for this attribute type, or <CODE>null</CODE> if
+   *         it does not have one.
    */
   public AttributeType getSuperiorType()
   {
@@ -384,7 +386,7 @@
 
 
   /**
-   * Retrieves the syntax for this attribute type.
+   * Returns the syntax for this attribute type.
    *
    * @return The syntax for this attribute type.
    */
@@ -396,7 +398,7 @@
 
 
   /**
-   * Retrieves the usage indicator for this attribute type.
+   * Returns the usage indicator for this attribute type.
    *
    * @return The usage indicator for this attribute type.
    */
@@ -420,10 +422,10 @@
    *
    * @param name
    *          The name for which to make the determination.
-   * @return {@code true} if the specified name is assigned to this
-   *         schema definition, or {@code false} if not.
+   * @return {@code true} if the specified name is assigned to this schema
+   *         definition, or {@code false} if not.
    */
-  public boolean hasName(String name)
+  public boolean hasName(final String name)
   {
     for (final String n : names)
     {
@@ -438,16 +440,14 @@
 
 
   /**
-   * Indicates whether this schema definition has the specified name or
-   * OID.
+   * Indicates whether this schema definition has the specified name or OID.
    *
    * @param value
    *          The value for which to make the determination.
-   * @return {@code true} if the provided value matches the OID or one
-   *         of the names assigned to this schema definition, or {@code
-   *         false} if not.
+   * @return {@code true} if the provided value matches the OID or one of the
+   *         names assigned to this schema definition, or {@code false} if not.
    */
-  public boolean hasNameOrOID(String value)
+  public boolean hasNameOrOID(final String value)
   {
     return hasName(value) || getOID().equals(value);
   }
@@ -457,8 +457,8 @@
   /**
    * Indicates whether this attribute type is declared "collective".
    *
-   * @return {@code true} if this attribute type is declared
-   *         "collective", or {@code false} if not.
+   * @return {@code true} if this attribute type is declared "collective", or
+   *         {@code false} if not.
    */
   public boolean isCollective()
   {
@@ -468,8 +468,7 @@
 
 
   /**
-   * Indicates whether this attribute type is declared
-   * "no-user-modification".
+   * Indicates whether this attribute type is declared "no-user-modification".
    *
    * @return {@code true} if this attribute type is declared
    *         "no-user-modification", or {@code false} if not.
@@ -482,11 +481,11 @@
 
 
   /**
-   * Indicates whether or not this attribute type is the {@code
-   * objectClass} attribute type having the OID 2.5.4.0.
+   * Indicates whether or not this attribute type is the {@code objectClass}
+   * attribute type having the OID 2.5.4.0.
    *
-   * @return {@code true} if this attribute type is the {@code
-   *         objectClass} attribute type, or {@code false} if not.
+   * @return {@code true} if this attribute type is the {@code objectClass}
+   *         attribute type, or {@code false} if not.
    */
   public boolean isObjectClass()
   {
@@ -498,8 +497,8 @@
   /**
    * Indicates whether this schema definition is declared "obsolete".
    *
-   * @return {@code true} if this schema definition is declared
-   *         "obsolete", or {@code false} if not.
+   * @return {@code true} if this schema definition is declared "obsolete", or
+   *         {@code false} if not.
    */
   public boolean isObsolete()
   {
@@ -511,11 +510,11 @@
   /**
    * Indicates whether this is an operational attribute. An operational
    * attribute is one with a usage of "directoryOperation",
-   * "distributedOperation", or "dSAOperation" (i.e., only
-   * userApplications is not operational).
+   * "distributedOperation", or "dSAOperation" (i.e., only userApplications is
+   * not operational).
    *
-   * @return {@code true} if this is an operational attribute, or
-   *         {@code false} if not.
+   * @return {@code true} if this is an operational attribute, or {@code false}
+   *         if not.
    */
   public boolean isOperational()
   {
@@ -527,8 +526,8 @@
   /**
    * Indicates whether this attribute type is declared "single-value".
    *
-   * @return {@code true} if this attribute type is declared
-   *         "single-value", or {@code false} if not.
+   * @return {@code true} if this attribute type is declared "single-value", or
+   *         {@code false} if not.
    */
   public boolean isSingleValue()
   {
@@ -538,17 +537,18 @@
 
 
   /**
-   * Indicates whether or not this attribute type is a sub-type of the
-   * provided attribute type.
+   * Indicates whether or not this attribute type is a sub-type of the provided
+   * attribute type.
    *
    * @param type
    *          The attribute type for which to make the determination.
-   * @return {@code true} if this attribute type is a sub-type of the
-   *         provided attribute type, or {@code false} if not.
+   * @return {@code true} if this attribute type is a sub-type of the provided
+   *         attribute type, or {@code false} if not.
    * @throws NullPointerException
    *           If {@code type} was {@code null}.
    */
-  public boolean isSubTypeOf(AttributeType type)
+  public boolean isSubTypeOf(final AttributeType type)
+      throws NullPointerException
   {
     AttributeType tmp = this;
     do
@@ -558,18 +558,19 @@
         return true;
       }
       tmp = tmp.getSuperiorType();
-    } while (tmp != null);
+    }
+    while (tmp != null);
     return false;
   }
 
 
 
   /**
-   * Retrieves the string representation of this schema definition in
-   * the form specified in RFC 2252.
+   * Returns the string representation of this schema definition in the form
+   * specified in RFC 2252.
    *
-   * @return The string representation of this schema definition in the
-   *         form specified in RFC 2252.
+   * @return The string representation of this schema definition in the form
+   *         specified in RFC 2252.
    */
   @Override
   public String toString()
@@ -582,17 +583,16 @@
   AttributeType duplicate()
   {
     return new AttributeType(oid, names, description, isObsolete,
-        superiorTypeOID, equalityMatchingRuleOID,
-        orderingMatchingRuleOID, substringMatchingRuleOID,
-        approximateMatchingRuleOID, syntaxOID, isSingleValue,
-        isCollective, isNoUserModification, attributeUsage,
+        superiorTypeOID, equalityMatchingRuleOID, orderingMatchingRuleOID,
+        substringMatchingRuleOID, approximateMatchingRuleOID, syntaxOID,
+        isSingleValue, isCollective, isNoUserModification, attributeUsage,
         extraProperties, definition);
   }
 
 
 
   @Override
-  void toStringContent(StringBuilder buffer)
+  void toStringContent(final StringBuilder buffer)
   {
     buffer.append(oid);
 
@@ -701,7 +701,7 @@
    * {@inheritDoc}
    */
   @Override
-  void validate(List<LocalizableMessage> warnings, Schema schema)
+  void validate(final List<LocalizableMessage> warnings, final Schema schema)
       throws SchemaException
   {
     if (superiorTypeOID != null)
@@ -710,7 +710,7 @@
       {
         superiorType = schema.getAttributeType(superiorTypeOID);
       }
-      catch (UnknownSchemaElementException e)
+      catch (final UnknownSchemaElementException e)
       {
         final LocalizableMessage message = WARN_ATTR_SYNTAX_ATTRTYPE_UNKNOWN_SUPERIOR_TYPE
             .get(getNameOrOID(), superiorTypeOID);
@@ -753,8 +753,8 @@
         // never fail since the core schema is non-strict and will
         // substitute the syntax if required.
         syntax = Schema.getCoreSchema().getSyntax(syntaxOID);
-        final LocalizableMessage message = WARN_ATTR_TYPE_NOT_DEFINED
-            .get(getNameOrOID(), syntaxOID, syntax.toString());
+        final LocalizableMessage message = WARN_ATTR_TYPE_NOT_DEFINED.get(
+            getNameOrOID(), syntaxOID, syntax.toString());
         warnings.add(message);
       }
       else
@@ -762,8 +762,7 @@
         syntax = schema.getSyntax(syntaxOID);
       }
     }
-    else if (getSuperiorType() != null
-        && getSuperiorType().getSyntax() != null)
+    else if (getSuperiorType() != null && getSuperiorType().getSyntax() != null)
     {
       // Try to inherit the syntax from the superior type if possible
       syntax = getSuperiorType().getSyntax();
@@ -774,10 +773,9 @@
       // Use explicitly defined matching rule first.
       try
       {
-        equalityMatchingRule = schema
-            .getMatchingRule(equalityMatchingRuleOID);
+        equalityMatchingRule = schema.getMatchingRule(equalityMatchingRuleOID);
       }
-      catch (UnknownSchemaElementException e)
+      catch (final UnknownSchemaElementException e)
       {
         final LocalizableMessage message = WARN_ATTR_SYNTAX_ATTRTYPE_UNKNOWN_EQUALITY_MR
             .get(getNameOrOID(), equalityMatchingRuleOID);
@@ -788,8 +786,7 @@
         && getSuperiorType().getEqualityMatchingRule() != null)
     {
       // Inherit matching rule from superior type if possible
-      equalityMatchingRule = getSuperiorType()
-          .getEqualityMatchingRule();
+      equalityMatchingRule = getSuperiorType().getEqualityMatchingRule();
     }
     else if (getSyntax() != null
         && getSyntax().getEqualityMatchingRule() != null)
@@ -803,10 +800,9 @@
       // Use explicitly defined matching rule first.
       try
       {
-        orderingMatchingRule = schema
-            .getMatchingRule(orderingMatchingRuleOID);
+        orderingMatchingRule = schema.getMatchingRule(orderingMatchingRuleOID);
       }
-      catch (UnknownSchemaElementException e)
+      catch (final UnknownSchemaElementException e)
       {
         final LocalizableMessage message = WARN_ATTR_SYNTAX_ATTRTYPE_UNKNOWN_ORDERING_MR
             .get(getNameOrOID(), orderingMatchingRuleOID);
@@ -817,8 +813,7 @@
         && getSuperiorType().getOrderingMatchingRule() != null)
     {
       // Inherit matching rule from superior type if possible
-      orderingMatchingRule = getSuperiorType()
-          .getOrderingMatchingRule();
+      orderingMatchingRule = getSuperiorType().getOrderingMatchingRule();
     }
     else if (getSyntax() != null
         && getSyntax().getOrderingMatchingRule() != null)
@@ -835,7 +830,7 @@
         substringMatchingRule = schema
             .getMatchingRule(substringMatchingRuleOID);
       }
-      catch (UnknownSchemaElementException e)
+      catch (final UnknownSchemaElementException e)
       {
         final LocalizableMessage message = WARN_ATTR_SYNTAX_ATTRTYPE_UNKNOWN_SUBSTRING_MR
             .get(getNameOrOID(), substringMatchingRuleOID);
@@ -846,8 +841,7 @@
         && getSuperiorType().getSubstringMatchingRule() != null)
     {
       // Inherit matching rule from superior type if possible
-      substringMatchingRule = getSuperiorType()
-          .getSubstringMatchingRule();
+      substringMatchingRule = getSuperiorType().getSubstringMatchingRule();
     }
     else if (getSyntax() != null
         && getSyntax().getSubstringMatchingRule() != null)
@@ -864,7 +858,7 @@
         approximateMatchingRule = schema
             .getMatchingRule(approximateMatchingRuleOID);
       }
-      catch (UnknownSchemaElementException e)
+      catch (final UnknownSchemaElementException e)
       {
         final LocalizableMessage message = WARN_ATTR_SYNTAX_ATTRTYPE_UNKNOWN_APPROXIMATE_MR
             .get(getNameOrOID(), approximateMatchingRuleOID);
@@ -875,21 +869,18 @@
         && getSuperiorType().getApproximateMatchingRule() != null)
     {
       // Inherit matching rule from superior type if possible
-      approximateMatchingRule = getSuperiorType()
-          .getApproximateMatchingRule();
+      approximateMatchingRule = getSuperiorType().getApproximateMatchingRule();
     }
     else if (getSyntax() != null
         && getSyntax().getApproximateMatchingRule() != null)
     {
       // Use default for syntax
-      approximateMatchingRule = getSyntax()
-          .getApproximateMatchingRule();
+      approximateMatchingRule = getSyntax().getApproximateMatchingRule();
     }
 
     // If the attribute type is COLLECTIVE, then it must have a usage of
     // userApplications.
-    if (isCollective()
-        && getUsage() != AttributeUsage.USER_APPLICATIONS)
+    if (isCollective() && getUsage() != AttributeUsage.USER_APPLICATIONS)
     {
       final LocalizableMessage message = WARN_ATTR_SYNTAX_ATTRTYPE_COLLECTIVE_IS_OPERATIONAL
           .get(getNameOrOID());
diff --git a/sdk/src/org/opends/sdk/schema/AttributeTypeSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/AttributeTypeSyntaxImpl.java
index c2e4d68..4afeb85 100644
--- a/sdk/src/org/opends/sdk/schema/AttributeTypeSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/AttributeTypeSyntaxImpl.java
@@ -29,8 +29,16 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_ATTRTYPE_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_ATTRTYPE_EXPECTED_OPEN_PARENTHESIS;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_ILLEGAL_TOKEN;
+import static com.sun.opends.sdk.messages.Messages.
+  WARN_ATTR_SYNTAX_ATTRTYPE_INVALID_ATTRIBUTE_USAGE;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OID_FIRST_COMPONENT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_ATTRIBUTE_TYPE_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DecodeException;
@@ -43,9 +51,9 @@
 
 
 /**
- * This class defines the attribute type description syntax, which is
- * used to hold attribute type definitions in the server schema. The
- * format of this syntax is defined in RFC 2252.
+ * This class defines the attribute type description syntax, which is used to
+ * hold attribute type definitions in the server schema. The format of this
+ * syntax is defined in RFC 2252.
  */
 final class AttributeTypeSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -72,8 +80,8 @@
 
 
 
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     try
     {
@@ -88,8 +96,8 @@
       {
         // This means that the definition was empty or contained only
         // whitespace. That is illegal.
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_ATTRTYPE_EMPTY_VALUE.get();
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_ATTRTYPE_EMPTY_VALUE
+            .get();
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("AttributeTypeSyntax",
             "valueIsAcceptable", e);
@@ -101,9 +109,8 @@
       final char c = reader.read();
       if (c != '(')
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_ATTRTYPE_EXPECTED_OPEN_PARENTHESIS.get(
-                definition, (reader.pos() - 1), String.valueOf(c));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_ATTRTYPE_EXPECTED_OPEN_PARENTHESIS
+            .get(definition, (reader.pos() - 1), String.valueOf(c));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("AttributeTypeSyntax",
             "valueIsAcceptable", e);
@@ -235,9 +242,8 @@
               && !usageStr.equalsIgnoreCase("distributedoperation")
               && !usageStr.equalsIgnoreCase("dsaoperation"))
           {
-            final LocalizableMessage message =
-                WARN_ATTR_SYNTAX_ATTRTYPE_INVALID_ATTRIBUTE_USAGE.get(
-                    String.valueOf(oid), usageStr);
+            final LocalizableMessage message = WARN_ATTR_SYNTAX_ATTRTYPE_INVALID_ATTRIBUTE_USAGE
+                .get(String.valueOf(oid), usageStr);
             final DecodeException e = DecodeException.error(message);
             StaticUtils.DEBUG_LOG.throwing("AttributeTypeSyntax",
                 "valueIsAcceptable", e);
@@ -255,8 +261,8 @@
         }
         else
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
+              .get(tokenName);
           final DecodeException e = DecodeException.error(message);
           StaticUtils.DEBUG_LOG.throwing("AttributeTypeSyntax",
               "valueIsAcceptable", e);
diff --git a/sdk/src/org/opends/sdk/schema/AttributeUsage.java b/sdk/src/org/opends/sdk/schema/AttributeUsage.java
index ac6e3e6..65d2481 100644
--- a/sdk/src/org/opends/sdk/schema/AttributeUsage.java
+++ b/sdk/src/org/opends/sdk/schema/AttributeUsage.java
@@ -30,8 +30,8 @@
 
 
 /**
- * This enumeration defines the set of possible attribute usage values
- * that may apply to an attribute type, as defined in RFC 2252.
+ * This enumeration defines the set of possible attribute usage values that may
+ * apply to an attribute type, as defined in RFC 2252.
  */
 public enum AttributeUsage
 {
@@ -46,14 +46,14 @@
   DIRECTORY_OPERATION("directoryOperation", true),
 
   /**
-   * The attribute usage intended for non-standard operational
-   * attributes shared among multiple DSAs.
+   * The attribute usage intended for non-standard operational attributes shared
+   * among multiple DSAs.
    */
   DISTRIBUTED_OPERATION("distributedOperation", true),
 
   /**
-   * The attribute usage intended for non-standard operational
-   * attributes used by a single DSA.
+   * The attribute usage intended for non-standard operational attributes used
+   * by a single DSA.
    */
   DSA_OPERATION("dSAOperation", true);
 
@@ -67,16 +67,15 @@
 
 
   /**
-   * Creates a new attribute usage with the provided string
-   * representation.
-   * 
+   * Creates a new attribute usage with the provided string representation.
+   *
    * @param usageString
    *          The string representation of this attribute usage.
    * @param isOperational
-   *          <code>true</code> if attributes having this attribute
-   *          usage are operational, or <code>false</code> otherwise.
+   *          <code>true</code> if attributes having this attribute usage are
+   *          operational, or <code>false</code> otherwise.
    */
-  private AttributeUsage(String usageString, boolean isOperational)
+  private AttributeUsage(final String usageString, final boolean isOperational)
   {
     this.usageString = usageString;
     this.isOperational = isOperational;
@@ -87,10 +86,9 @@
   /**
    * Determine whether or not attributes having this attribute usage are
    * operational.
-   * 
-   * @return Returns <code>true</code> if attributes having this
-   *         attribute usage are operational, or <code>false</code>
-   *         otherwise.
+   *
+   * @return Returns <code>true</code> if attributes having this attribute usage
+   *         are operational, or <code>false</code> otherwise.
    */
   public boolean isOperational()
   {
@@ -101,7 +99,7 @@
 
   /**
    * Retrieves a string representation of this attribute usage.
-   * 
+   *
    * @return A string representation of this attribute usage.
    */
   @Override
diff --git a/sdk/src/org/opends/sdk/schema/AuthPasswordExactEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/AuthPasswordExactEqualityMatchingRuleImpl.java
index b54cceb..ab5a823 100644
--- a/sdk/src/org/opends/sdk/schema/AuthPasswordExactEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/AuthPasswordExactEqualityMatchingRuleImpl.java
@@ -35,22 +35,21 @@
 
 
 /**
- * This class implements the authPasswordMatch matching rule defined in
- * RFC 3112.
+ * This class implements the authPasswordMatch matching rule defined in RFC
+ * 3112.
  */
 final class AuthPasswordExactEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
-    final StringBuilder[] authPWComponents =
-        AuthPasswordSyntaxImpl.decodeAuthPassword(value.toString());
+    final StringBuilder[] authPWComponents = AuthPasswordSyntaxImpl
+        .decodeAuthPassword(value.toString());
 
-    final StringBuilder normalizedValue =
-        new StringBuilder(2 + authPWComponents[0].length()
-            + authPWComponents[1].length()
-            + authPWComponents[2].length());
+    final StringBuilder normalizedValue = new StringBuilder(2
+        + authPWComponents[0].length() + authPWComponents[1].length()
+        + authPWComponents[2].length());
     normalizedValue.append(authPWComponents[0]);
     normalizedValue.append('$');
     normalizedValue.append(authPWComponents[1]);
diff --git a/sdk/src/org/opends/sdk/schema/AuthPasswordSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/AuthPasswordSyntaxImpl.java
index 17585dc..f58743a 100644
--- a/sdk/src/org/opends/sdk/schema/AuthPasswordSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/AuthPasswordSyntaxImpl.java
@@ -30,7 +30,8 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_AUTH_PASSWORD_EXACT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_AUTH_PASSWORD_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DecodeException;
@@ -39,27 +40,25 @@
 
 
 
-
 /**
- * This class defines the auth password attribute syntax, which is
- * defined in RFC 3112 and is used to hold authentication information.
- * Only equality matching will be allowed by default.
+ * This class defines the auth password attribute syntax, which is defined in
+ * RFC 3112 and is used to hold authentication information. Only equality
+ * matching will be allowed by default.
  */
 final class AuthPasswordSyntaxImpl extends AbstractSyntaxImpl
 {
   /**
-   * Decodes the provided authentication password value into its
-   * component parts.
-   * 
+   * Decodes the provided authentication password value into its component
+   * parts.
+   *
    * @param authPasswordValue
    *          The authentication password value to be decoded.
    * @return A three-element array, containing the scheme, authInfo, and
    *         authValue components of the given string, in that order.
    * @throws DecodeException
-   *           If a problem is encountered while attempting to decode
-   *           the value.
+   *           If a problem is encountered while attempting to decode the value.
    */
-  static StringBuilder[] decodeAuthPassword(String authPasswordValue)
+  static StringBuilder[] decodeAuthPassword(final String authPasswordValue)
       throws DecodeException
   {
     // Create placeholders for the values to return.
@@ -132,8 +131,8 @@
       case '$':
         break readScheme;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_AUTHPW_INVALID_SCHEME_CHAR.get(pos);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_AUTHPW_INVALID_SCHEME_CHAR
+            .get(pos);
         throw DecodeException.error(message);
       }
     }
@@ -158,8 +157,8 @@
     }
     else
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_AUTHPW_NO_SCHEME_SEPARATOR.get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_AUTHPW_NO_SCHEME_SEPARATOR
+          .get();
       throw DecodeException.error(message);
     }
 
@@ -185,8 +184,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_AUTHPW_INVALID_AUTH_INFO_CHAR.get(pos);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_AUTHPW_INVALID_AUTH_INFO_CHAR
+            .get(pos);
         throw DecodeException.error(message);
       }
     }
@@ -194,7 +193,8 @@
     // The authInfo element must consist of at least one character.
     if (scheme.length() == 0)
     {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_AUTHPW_NO_AUTH_INFO.get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_AUTHPW_NO_AUTH_INFO
+          .get();
       throw DecodeException.error(message);
     }
 
@@ -211,8 +211,8 @@
     }
     else
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_AUTHPW_NO_AUTH_INFO_SEPARATOR.get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_AUTHPW_NO_AUTH_INFO_SEPARATOR
+          .get();
       throw DecodeException.error(message);
     }
 
@@ -238,8 +238,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_AUTHPW_INVALID_AUTH_VALUE_CHAR.get(pos);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_AUTHPW_INVALID_AUTH_VALUE_CHAR
+            .get(pos);
         throw DecodeException.error(message);
       }
     }
@@ -247,8 +247,8 @@
     // The authValue element must consist of at least one character.
     if (scheme.length() == 0)
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_AUTHPW_NO_AUTH_VALUE.get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_AUTHPW_NO_AUTH_VALUE
+          .get();
       throw DecodeException.error(message);
     }
 
@@ -262,8 +262,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_AUTHPW_INVALID_TRAILING_CHAR.get(pos);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_AUTHPW_INVALID_TRAILING_CHAR
+            .get(pos);
         throw DecodeException.error(message);
       }
     }
@@ -275,15 +275,15 @@
 
 
   /**
-   * Indicates whether the provided value is encoded using the auth
-   * password syntax.
-   * 
+   * Indicates whether the provided value is encoded using the auth password
+   * syntax.
+   *
    * @param value
    *          The value for which to make the determination.
-   * @return <CODE>true</CODE> if the value appears to be encoded using
-   *         the auth password syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the value appears to be encoded using the auth
+   *         password syntax, or <CODE>false</CODE> if not.
    */
-  static boolean isEncoded(ByteSequence value)
+  static boolean isEncoded(final ByteSequence value)
   {
     // FIXME -- Make this more efficient, and don't use exceptions for
     // flow control.
@@ -323,8 +323,8 @@
 
 
 
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     try
     {
diff --git a/sdk/src/org/opends/sdk/schema/BinarySyntaxImpl.java b/sdk/src/org/opends/sdk/schema/BinarySyntaxImpl.java
index e8a0c18..8eeede5 100644
--- a/sdk/src/org/opends/sdk/schema/BinarySyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/BinarySyntaxImpl.java
@@ -29,18 +29,19 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_BINARY_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class defines the binary attribute syntax, which is essentially
- * a byte array using very strict matching. Equality, ordering, and
- * substring matching will be allowed by default.
+ * This class defines the binary attribute syntax, which is essentially a byte
+ * array using very strict matching. Equality, ordering, and substring matching
+ * will be allowed by default.
  */
 final class BinarySyntaxImpl extends AbstractSyntaxImpl
 {
@@ -75,21 +76,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // All values will be acceptable for the binary syntax.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleImpl.java
index 23293b1..d54d865 100644
--- a/sdk/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_BIT_STRING_INVALID_BIT;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_BIT_STRING_NOT_QUOTED;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_BIT_STRING_TOO_SHORT;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -37,33 +39,30 @@
 
 
 
-
 /**
- * This class defines the bitStringMatch matching rule defined in X.520
- * and referenced in RFC 2252.
+ * This class defines the bitStringMatch matching rule defined in X.520 and
+ * referenced in RFC 2252.
  */
-final class BitStringEqualityMatchingRuleImpl extends
-    AbstractMatchingRuleImpl
+final class BitStringEqualityMatchingRuleImpl extends AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     final String valueString = value.toString().toUpperCase();
 
     final int length = valueString.length();
     if (length < 3)
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_BIT_STRING_TOO_SHORT.get(value.toString());
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_BIT_STRING_TOO_SHORT
+          .get(value.toString());
       throw DecodeException.error(message);
     }
 
-    if (valueString.charAt(0) != '\''
-        || valueString.charAt(length - 2) != '\''
+    if (valueString.charAt(0) != '\'' || valueString.charAt(length - 2) != '\''
         || valueString.charAt(length - 1) != 'B')
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_BIT_STRING_NOT_QUOTED.get(value.toString());
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_BIT_STRING_NOT_QUOTED
+          .get(value.toString());
       throw DecodeException.error(message);
     }
 
@@ -76,9 +75,8 @@
         // These characters are fine.
         break;
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_BIT_STRING_INVALID_BIT.get(value
-                .toString(), String.valueOf(valueString.charAt(i)));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_BIT_STRING_INVALID_BIT
+            .get(value.toString(), String.valueOf(valueString.charAt(i)));
         throw DecodeException.error(message);
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/BitStringSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/BitStringSyntaxImpl.java
index c090990..5ebdfe8 100644
--- a/sdk/src/org/opends/sdk/schema/BitStringSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/BitStringSyntaxImpl.java
@@ -29,19 +29,21 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_BIT_STRING_INVALID_BIT;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_BIT_STRING_NOT_QUOTED;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_BIT_STRING_TOO_SHORT;
+import static org.opends.sdk.schema.SchemaConstants.EMR_BIT_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_BIT_STRING_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class defines the bit string attribute syntax, which is
- * comprised of a string of binary digits surrounded by single quotes
- * and followed by a capital letter "B" (e.g., '101001'B).
+ * This class defines the bit string attribute syntax, which is comprised of a
+ * string of binary digits surrounded by single quotes and followed by a capital
+ * letter "B" (e.g., '101001'B).
  */
 final class BitStringSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -68,38 +70,37 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     final String valueString = value.toString().toUpperCase();
 
     final int length = valueString.length();
     if (length < 3)
     {
-      invalidReason.append(WARN_ATTR_SYNTAX_BIT_STRING_TOO_SHORT
-          .get(value.toString()));
+      invalidReason.append(WARN_ATTR_SYNTAX_BIT_STRING_TOO_SHORT.get(value
+          .toString()));
       return false;
     }
 
-    if (valueString.charAt(0) != '\''
-        || valueString.charAt(length - 2) != '\''
+    if (valueString.charAt(0) != '\'' || valueString.charAt(length - 2) != '\''
         || valueString.charAt(length - 1) != 'B')
     {
-      invalidReason.append(WARN_ATTR_SYNTAX_BIT_STRING_NOT_QUOTED
-          .get(value.toString()));
+      invalidReason.append(WARN_ATTR_SYNTAX_BIT_STRING_NOT_QUOTED.get(value
+          .toString()));
       return false;
     }
 
@@ -112,9 +113,8 @@
         // These characters are fine.
         break;
       default:
-        invalidReason.append(WARN_ATTR_SYNTAX_BIT_STRING_INVALID_BIT
-            .get(value.toString(), String
-                .valueOf(valueString.charAt(i))));
+        invalidReason.append(WARN_ATTR_SYNTAX_BIT_STRING_INVALID_BIT.get(value
+            .toString(), String.valueOf(valueString.charAt(i))));
         return false;
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleImpl.java
index f50ad09..a2b1e7e 100644
--- a/sdk/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleImpl.java
@@ -28,7 +28,7 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_ILLEGAL_BOOLEAN;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -37,14 +37,13 @@
 
 
 /**
- * This class defines the booleanMatch matching rule defined in X.520
- * and referenced in RFC 4519.
+ * This class defines the booleanMatch matching rule defined in X.520 and
+ * referenced in RFC 4519.
  */
-final class BooleanEqualityMatchingRuleImpl extends
-    AbstractMatchingRuleImpl
+final class BooleanEqualityMatchingRuleImpl extends AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     final String valueString = value.toString().toUpperCase();
     if (valueString.equals("TRUE") || valueString.equals("YES")
@@ -58,7 +57,7 @@
       return SchemaConstants.FALSE_VALUE;
     }
 
-    throw DecodeException.error(WARN_ATTR_SYNTAX_ILLEGAL_BOOLEAN
-        .get(value.toString()));
+    throw DecodeException.error(WARN_ATTR_SYNTAX_ILLEGAL_BOOLEAN.get(value
+        .toString()));
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/BooleanSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/BooleanSyntaxImpl.java
index ed402c0..a882e3c 100644
--- a/sdk/src/org/opends/sdk/schema/BooleanSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/BooleanSyntaxImpl.java
@@ -29,21 +29,21 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_ILLEGAL_BOOLEAN;
+import static org.opends.sdk.schema.SchemaConstants.EMR_BOOLEAN_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_BOOLEAN_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class defines the Boolean attribute syntax, which only allows
- * values of "TRUE" or "FALSE" (although this implementation is more
- * flexible and will also allow "YES", "ON", or "1" instead of "TRUE",
- * or "NO", "OFF", or "0" instead of "FALSE"). Only equality matching is
- * allowed by default for this syntax.
+ * This class defines the Boolean attribute syntax, which only allows values of
+ * "TRUE" or "FALSE" (although this implementation is more flexible and will
+ * also allow "YES", "ON", or "1" instead of "TRUE", or "NO", "OFF", or "0"
+ * instead of "FALSE"). Only equality matching is allowed by default for this
+ * syntax.
  */
 final class BooleanSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -70,29 +70,29 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     final String valueString = value.toString().toUpperCase();
 
-    final boolean returnValue =
-        valueString.equals("TRUE") || valueString.equals("YES")
-            || valueString.equals("ON") || valueString.equals("1")
-            || valueString.equals("FALSE") || valueString.equals("NO")
-            || valueString.equals("OFF") || valueString.equals("0");
+    final boolean returnValue = valueString.equals("TRUE")
+        || valueString.equals("YES") || valueString.equals("ON")
+        || valueString.equals("1") || valueString.equals("FALSE")
+        || valueString.equals("NO") || valueString.equals("OFF")
+        || valueString.equals("0");
 
     if (!returnValue)
     {
diff --git a/sdk/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleImpl.java
index 5a9297c..4c3ea6e 100644
--- a/sdk/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.NO_CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -36,14 +38,13 @@
 
 
 /**
- * This class defines the caseExactMatch matching rule defined in X.520
- * and referenced in RFC 4519.
+ * This class defines the caseExactMatch matching rule defined in X.520 and
+ * referenced in RFC 4519.
  */
-final class CaseExactEqualityMatchingRuleImpl extends
-    AbstractMatchingRuleImpl
+final class CaseExactEqualityMatchingRuleImpl extends AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, NO_CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleImpl.java
index a24d556..dc62800 100644
--- a/sdk/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleImpl.java
@@ -28,8 +28,10 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER;
+import static com.sun.opends.sdk.util.StringPrepProfile.NO_CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -38,16 +40,15 @@
 
 
 
-
 /**
- * This class implements the caseExactIA5Match matching rule defined in
- * RFC 2252.
+ * This class implements the caseExactIA5Match matching rule defined in RFC
+ * 2252.
  */
 final class CaseExactIA5EqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, NO_CASE_FOLD);
@@ -85,9 +86,8 @@
         // This is not a valid character for an IA5 string. If strict
         // syntax enforcement is enabled, then we'll throw an exception.
         // Otherwise, we'll get rid of the character.
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER.get(
-                value.toString(), String.valueOf(c));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER
+            .get(value.toString(), String.valueOf(c));
         throw DecodeException.error(message);
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleImpl.java
index 04308b1..ae72948 100644
--- a/sdk/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleImpl.java
@@ -28,8 +28,10 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER;
+import static com.sun.opends.sdk.util.StringPrepProfile.NO_CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -38,18 +40,17 @@
 
 
 
-
 /**
- * This class implements the caseExactIA5SubstringsMatch matching rule.
- * This matching rule actually isn't defined in any official
- * specification, but some directory vendors do provide an
- * implementation using an OID from their own private namespace.
+ * This class implements the caseExactIA5SubstringsMatch matching rule. This
+ * matching rule actually isn't defined in any official specification, but some
+ * directory vendors do provide an implementation using an OID from their own
+ * private namespace.
  */
 final class CaseExactIA5SubstringMatchingRuleImpl extends
     AbstractSubstringMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     return normalize(TRIM, value);
   }
@@ -57,7 +58,7 @@
 
 
   @Override
-  ByteString normalizeSubString(Schema schema, ByteSequence value)
+  ByteString normalizeSubString(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     return normalize(false, value);
@@ -65,7 +66,7 @@
 
 
 
-  private ByteString normalize(boolean trim, ByteSequence value)
+  private ByteString normalize(final boolean trim, final ByteSequence value)
       throws DecodeException
   {
     final StringBuilder buffer = new StringBuilder();
@@ -104,9 +105,8 @@
         // This is not a valid character for an IA5 string. If strict
         // syntax enforcement is enabled, then we'll throw an exception.
         // Otherwise, we'll get rid of the character.
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER.get(
-                value.toString(), String.valueOf(c));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER
+            .get(value.toString(), String.valueOf(c));
         throw DecodeException.error(message);
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleImpl.java
index 85f64cb..e52d735 100644
--- a/sdk/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.NO_CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -36,14 +38,14 @@
 
 
 /**
- * This class defines the caseExactOrderingMatch matching rule defined
- * in X.520 and referenced in RFC 4519.
+ * This class defines the caseExactOrderingMatch matching rule defined in X.520
+ * and referenced in RFC 4519.
  */
 final class CaseExactOrderingMatchingRuleImpl extends
     AbstractOrderingMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, NO_CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleImpl.java
index faf9556..2089814 100644
--- a/sdk/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.NO_CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -37,14 +39,14 @@
 
 
 /**
- * This class defines the caseExactSubstringsMatch matching rule defined
- * in X.520 and referenced in RFC 2252.
+ * This class defines the caseExactSubstringsMatch matching rule defined in
+ * X.520 and referenced in RFC 2252.
  */
 final class CaseExactSubstringMatchingRuleImpl extends
     AbstractSubstringMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     return normalize(TRIM, value);
   }
@@ -52,7 +54,7 @@
 
 
   @Override
-  ByteString normalizeSubString(Schema schema, ByteSequence value)
+  ByteString normalizeSubString(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     return normalize(false, value);
@@ -60,7 +62,7 @@
 
 
 
-  private ByteString normalize(boolean trim, ByteSequence value)
+  private ByteString normalize(final boolean trim, final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, trim, NO_CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleImpl.java
index 249f028..feb9af4 100644
--- a/sdk/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -36,14 +38,13 @@
 
 
 /**
- * This class defines the caseIgnoreMatch matching rule defined in X.520
- * and referenced in RFC 2252.
+ * This class defines the caseIgnoreMatch matching rule defined in X.520 and
+ * referenced in RFC 2252.
  */
-final class CaseIgnoreEqualityMatchingRuleImpl extends
-    AbstractMatchingRuleImpl
+final class CaseIgnoreEqualityMatchingRuleImpl extends AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java
index 47b3c66..b001604 100644
--- a/sdk/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java
@@ -28,8 +28,10 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -38,16 +40,15 @@
 
 
 
-
 /**
- * This class implements the caseIgnoreIA5Match matching rule defined in
- * RFC 2252.
+ * This class implements the caseIgnoreIA5Match matching rule defined in RFC
+ * 2252.
  */
 final class CaseIgnoreIA5EqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, CASE_FOLD);
@@ -85,9 +86,8 @@
         // This is not a valid character for an IA5 string. If strict
         // syntax enforcement is enabled, then we'll throw an exception.
         // Otherwise, we'll get rid of the character.
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER.get(
-                value.toString(), String.valueOf(c));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER
+            .get(value.toString(), String.valueOf(c));
         throw DecodeException.error(message);
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java
index ae52491..7120311 100644
--- a/sdk/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java
@@ -28,8 +28,10 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -38,16 +40,15 @@
 
 
 
-
 /**
- * This class implements the caseIgnoreIA5SubstringsMatch matching rule
- * defined in RFC 2252.
+ * This class implements the caseIgnoreIA5SubstringsMatch matching rule defined
+ * in RFC 2252.
  */
 final class CaseIgnoreIA5SubstringMatchingRuleImpl extends
     AbstractSubstringMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     return normalize(TRIM, value);
   }
@@ -55,7 +56,7 @@
 
 
   @Override
-  ByteString normalizeSubString(Schema schema, ByteSequence value)
+  ByteString normalizeSubString(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     return normalize(false, value);
@@ -63,7 +64,7 @@
 
 
 
-  private ByteString normalize(boolean trim, ByteSequence value)
+  private ByteString normalize(final boolean trim, final ByteSequence value)
       throws DecodeException
   {
     final StringBuilder buffer = new StringBuilder();
@@ -102,9 +103,8 @@
         // This is not a valid character for an IA5 string. If strict
         // syntax enforcement is enabled, then we'll throw an exception.
         // Otherwise, we'll get rid of the character.
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER.get(
-                value.toString(), String.valueOf(c));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER
+            .get(value.toString(), String.valueOf(c));
         throw DecodeException.error(message);
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/CaseIgnoreListEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseIgnoreListEqualityMatchingRuleImpl.java
index 6dc1544..c079eb4 100644
--- a/sdk/src/org/opends/sdk/schema/CaseIgnoreListEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseIgnoreListEqualityMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -36,14 +38,14 @@
 
 
 /**
- * This class implements the caseIgnoreListMatch matching rule defined
- * in X.520 and referenced in RFC 2252.
+ * This class implements the caseIgnoreListMatch matching rule defined in X.520
+ * and referenced in RFC 2252.
  */
 final class CaseIgnoreListEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/CaseIgnoreListSubstringMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseIgnoreListSubstringMatchingRuleImpl.java
index f349095..12cd2b4 100644
--- a/sdk/src/org/opends/sdk/schema/CaseIgnoreListSubstringMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseIgnoreListSubstringMatchingRuleImpl.java
@@ -28,7 +28,8 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -39,14 +40,14 @@
 
 
 /**
- * This class implements the caseIgnoreListSubstringsMatch matching rule
- * defined in X.520 and referenced in RFC 2252.
+ * This class implements the caseIgnoreListSubstringsMatch matching rule defined
+ * in X.520 and referenced in RFC 2252.
  */
 final class CaseIgnoreListSubstringMatchingRuleImpl extends
     AbstractSubstringMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, StringPrepProfile.TRIM, CASE_FOLD);
@@ -98,7 +99,7 @@
 
 
   @Override
-  ByteString normalizeSubString(Schema schema, ByteSequence value)
+  ByteString normalizeSubString(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     // In this case, the process for normalizing a substring is the same
diff --git a/sdk/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleImpl.java
index baea2ad..fe59961 100644
--- a/sdk/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -36,14 +38,14 @@
 
 
 /**
- * This class defines the caseIgnoreOrderingMatch matching rule defined
- * in X.520 and referenced in RFC 2252.
+ * This class defines the caseIgnoreOrderingMatch matching rule defined in X.520
+ * and referenced in RFC 2252.
  */
 final class CaseIgnoreOrderingMatchingRuleImpl extends
     AbstractOrderingMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleImpl.java
index d243560..f9ac602 100644
--- a/sdk/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleImpl.java
@@ -28,7 +28,8 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -39,14 +40,14 @@
 
 
 /**
- * This class defines the caseIgnoreSubstringsMatch matching rule
- * defined in X.520 and referenced in RFC 2252.
+ * This class defines the caseIgnoreSubstringsMatch matching rule defined in
+ * X.520 and referenced in RFC 2252.
  */
 final class CaseIgnoreSubstringMatchingRuleImpl extends
     AbstractSubstringMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     return normalize(TRIM, value);
   }
@@ -54,7 +55,7 @@
 
 
   @Override
-  ByteString normalizeSubString(Schema schema, ByteSequence value)
+  ByteString normalizeSubString(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     return normalize(false, value);
@@ -62,7 +63,7 @@
 
 
 
-  private ByteString normalize(boolean trim, ByteSequence value)
+  private ByteString normalize(final boolean trim, final ByteSequence value)
   {
 
     final StringBuilder buffer = new StringBuilder();
diff --git a/sdk/src/org/opends/sdk/schema/CertificateListSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/CertificateListSyntaxImpl.java
index 48734cb..bbcde01 100644
--- a/sdk/src/org/opends/sdk/schema/CertificateListSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CertificateListSyntaxImpl.java
@@ -29,19 +29,19 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_CERTLIST_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the certificate list attribute syntax. This
- * should be restricted to holding only X.509 certificate lists, but we
- * will accept any set of bytes. It will be treated much like the octet
- * string attribute syntax.
+ * This class implements the certificate list attribute syntax. This should be
+ * restricted to holding only X.509 certificate lists, but we will accept any
+ * set of bytes. It will be treated much like the octet string attribute syntax.
  */
 final class CertificateListSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -85,21 +85,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // All values will be acceptable for the certificate list syntax.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/CertificatePairSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/CertificatePairSyntaxImpl.java
index 72bb68b..3385048 100644
--- a/sdk/src/org/opends/sdk/schema/CertificatePairSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CertificatePairSyntaxImpl.java
@@ -29,19 +29,19 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_CERTPAIR_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the certificate pair attribute syntax. This
- * should be restricted to holding only X.509 certificate pairs, but we
- * will accept any set of bytes. It will be treated much like the octet
- * string attribute syntax.
+ * This class implements the certificate pair attribute syntax. This should be
+ * restricted to holding only X.509 certificate pairs, but we will accept any
+ * set of bytes. It will be treated much like the octet string attribute syntax.
  */
 final class CertificatePairSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -84,21 +84,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // All values will be acceptable for the certificate pair syntax.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/CertificateSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/CertificateSyntaxImpl.java
index d12b271..ed693fd 100644
--- a/sdk/src/org/opends/sdk/schema/CertificateSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CertificateSyntaxImpl.java
@@ -29,19 +29,19 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_CERTIFICATE_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the certificate attribute syntax. This should
- * be restricted to holding only X.509 certificates, but we will accept
- * any set of bytes. It will be treated much like the octet string
- * attribute syntax.
+ * This class implements the certificate attribute syntax. This should be
+ * restricted to holding only X.509 certificates, but we will accept any set of
+ * bytes. It will be treated much like the octet string attribute syntax.
  */
 final class CertificateSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -84,21 +84,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // All values will be acceptable for the certificate syntax.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/ConflictingSchemaElementException.java b/sdk/src/org/opends/sdk/schema/ConflictingSchemaElementException.java
index c814f89..bd749e3 100644
--- a/sdk/src/org/opends/sdk/schema/ConflictingSchemaElementException.java
+++ b/sdk/src/org/opends/sdk/schema/ConflictingSchemaElementException.java
@@ -29,30 +29,28 @@
 
 
 
-import org.opends.sdk.LocalizedIllegalArgumentException;
 import org.opends.sdk.LocalizableMessage;
-
+import org.opends.sdk.LocalizedIllegalArgumentException;
 
 
 
 /**
- * Thrown when addition of a schema element to a schema builder fails
- * because the OID of the schema element conflicts with an existing
- * schema element and the caller explicitly requested not to override
- * existing schema elements.
+ * Thrown when addition of a schema element to a schema builder fails because
+ * the OID of the schema element conflicts with an existing schema element and
+ * the caller explicitly requested not to override existing schema elements.
  */
 @SuppressWarnings("serial")
 public class ConflictingSchemaElementException extends
     LocalizedIllegalArgumentException
 {
   /**
-   * Creates a new conflicting schema element exception with the
-   * provided message.
-   * 
+   * Creates a new conflicting schema element exception with the provided
+   * message.
+   *
    * @param message
    *          The message that explains the problem that occurred.
    */
-  public ConflictingSchemaElementException(LocalizableMessage message)
+  public ConflictingSchemaElementException(final LocalizableMessage message)
   {
     super(message);
   }
diff --git a/sdk/src/org/opends/sdk/schema/CoreSchema.java b/sdk/src/org/opends/sdk/schema/CoreSchema.java
index 7ebcaa1..83f07ec 100644
--- a/sdk/src/org/opends/sdk/schema/CoreSchema.java
+++ b/sdk/src/org/opends/sdk/schema/CoreSchema.java
@@ -30,409 +30,437 @@
 
 
 /**
- * The OpenDS SDK core schema contains standard LDAP RFC schema elements. These include:
+ * The OpenDS SDK core schema contains standard LDAP RFC schema elements. These
+ * include:
  * <ul>
- * <li><a href="http://tools.ietf.org/html/rfc4512">RFC 4512 -
- * Lightweight Directory Access Protocol (LDAP): Directory Information
- * Models </a>
- * <li><a href="http://tools.ietf.org/html/rfc4517">RFC 4517 -
- * Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching
- * Rules </a>
- * <li><a href="http://tools.ietf.org/html/rfc4519">RFC 4519 -
- * Lightweight Directory Access Protocol (LDAP): Schema for User
- * Applications </a>
- * <li><a href="http://tools.ietf.org/html/rfc4530">RFC 4530 -
- * Lightweight Directory Access Protocol (LDAP): entryUUID Operational
- * Attribute </a>
- * <li><a href="http://tools.ietf.org/html/rfc3045">RFC 3045 - Storing
- * Vendor Information in the LDAP Root DSE </a>
+ * <li><a href="http://tools.ietf.org/html/rfc4512">RFC 4512 - Lightweight
+ * Directory Access Protocol (LDAP): Directory Information Models </a>
+ * <li><a href="http://tools.ietf.org/html/rfc4517">RFC 4517 - Lightweight
+ * Directory Access Protocol (LDAP): Syntaxes and Matching Rules </a>
+ * <li><a href="http://tools.ietf.org/html/rfc4519">RFC 4519 - Lightweight
+ * Directory Access Protocol (LDAP): Schema for User Applications </a>
+ * <li><a href="http://tools.ietf.org/html/rfc4530">RFC 4530 - Lightweight
+ * Directory Access Protocol (LDAP): entryUUID Operational Attribute </a>
+ * <li><a href="http://tools.ietf.org/html/rfc3045">RFC 3045 - Storing Vendor
+ * Information in the LDAP Root DSE </a>
  * <li><a href="http://tools.ietf.org/html/rfc3112">RFC 3112 - LDAP
  * Authentication Password Schema </a>
  * </ul>
  * <p>
- * The core schema is non-strict: attempts to retrieve
- * non-existent Attribute Types will return a temporary
- * Attribute Type having the Octet String syntax.
+ * The core schema is non-strict: attempts to retrieve non-existent Attribute
+ * Types will return a temporary Attribute Type having the Octet String syntax.
  */
 public final class CoreSchema
 {
   // Core Syntaxes
-  private static final Syntax ATTRIBUTE_TYPE_DESCRIPTION_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.3");
-  private static final Syntax AUTHENTICATION_PASSWORD_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.4203.1.1.2");
-  private static final Syntax BINARY_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.5");
-  private static final Syntax BIT_STRING_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.6");
-  private static final Syntax BOOLEAN_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.7");
-  private static final Syntax CERTIFICATE_LIST_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.9");
-  private static final Syntax CERTIFICATE_PAIR_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.10");
-  private static final Syntax CERTIFICATE_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.8");
-  private static final Syntax COUNTRY_STRING_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.11");
-  private static final Syntax DELIVERY_METHOD_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.14");
-  private static final Syntax DIRECTORY_STRING_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.15");
-  private static final Syntax DIT_CONTENT_RULE_DESCRIPTION_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.16");
-  private static final Syntax DIT_STRUCTURE_RULE_DESCRIPTION_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.17");
-  private static final Syntax DN_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.12");
-  private static final Syntax ENHANCED_GUIDE_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.21");
-  private static final Syntax FACSIMILE_TELEPHONE_NUMBER_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.22");
-  private static final Syntax FAX_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.23");
-  private static final Syntax GENERALIZED_TIME_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.24");
-  private static final Syntax GUIDE_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.25");
-  private static final Syntax IA5_STRING_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.26");
-  private static final Syntax INTEGER_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.27");
-  private static final Syntax JPEG_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.28");
-  private static final Syntax LDAP_SYNTAX_DESCRIPTION_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.54");
-  private static final Syntax MATCHING_RULE_DESCRIPTION_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.30");
-  private static final Syntax MATCHING_RULE_USE_DESCRIPTION_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.31");
-  private static final Syntax NAME_AND_OPTIONAL_UID_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.34");
-  private static final Syntax NAME_FORM_DESCRIPTION_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.35");
-  private static final Syntax NUMERIC_STRING_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.36");
-  private static final Syntax OBJECT_CLASS_DESCRIPTION_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.37");
-  private static final Syntax OCTET_STRING_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.40");
-  private static final Syntax OID_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.38");
-  private static final Syntax OTHER_MAILBOX_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.39");
-  private static final Syntax POSTAL_ADDRESS_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.41");
-  private static final Syntax PRESENTATION_ADDRESS_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.43");
-  private static final Syntax PRINTABLE_STRING_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.44");
-  private static final Syntax PROTOCOL_INFORMATION_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.42");
-  private static final Syntax SUBSTRING_ASSERTION_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.58");
-  private static final Syntax SUPPORTED_ALGORITHM_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.49");
-  private static final Syntax TELEPHONE_NUMBER_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.50");
-  private static final Syntax TELETEX_TERMINAL_IDENTIFIER_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.51");
-  private static final Syntax TELEX_NUMBER_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.52");
-  private static final Syntax UTC_TIME_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.53");
-  private static final Syntax UUID_SYNTAX =
-    CoreSchemaImpl.getInstance().getSyntax("1.3.6.1.1.16.1");
+  private static final Syntax ATTRIBUTE_TYPE_DESCRIPTION_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.3");
+  private static final Syntax AUTHENTICATION_PASSWORD_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.4203.1.1.2");
+  private static final Syntax BINARY_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.5");
+  private static final Syntax BIT_STRING_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.6");
+  private static final Syntax BOOLEAN_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.7");
+  private static final Syntax CERTIFICATE_LIST_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.9");
+  private static final Syntax CERTIFICATE_PAIR_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.10");
+  private static final Syntax CERTIFICATE_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.8");
+  private static final Syntax COUNTRY_STRING_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.11");
+  private static final Syntax DELIVERY_METHOD_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.14");
+  private static final Syntax DIRECTORY_STRING_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.15");
+  private static final Syntax DIT_CONTENT_RULE_DESCRIPTION_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.16");
+  private static final Syntax DIT_STRUCTURE_RULE_DESCRIPTION_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.17");
+  private static final Syntax DN_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.12");
+  private static final Syntax ENHANCED_GUIDE_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.21");
+  private static final Syntax FACSIMILE_TELEPHONE_NUMBER_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.22");
+  private static final Syntax FAX_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.23");
+  private static final Syntax GENERALIZED_TIME_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.24");
+  private static final Syntax GUIDE_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.25");
+  private static final Syntax IA5_STRING_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.26");
+  private static final Syntax INTEGER_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.27");
+  private static final Syntax JPEG_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.28");
+  private static final Syntax LDAP_SYNTAX_DESCRIPTION_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.54");
+  private static final Syntax MATCHING_RULE_DESCRIPTION_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.30");
+  private static final Syntax MATCHING_RULE_USE_DESCRIPTION_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.31");
+  private static final Syntax NAME_AND_OPTIONAL_UID_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.34");
+  private static final Syntax NAME_FORM_DESCRIPTION_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.35");
+  private static final Syntax NUMERIC_STRING_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.36");
+  private static final Syntax OBJECT_CLASS_DESCRIPTION_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.37");
+  private static final Syntax OCTET_STRING_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.40");
+  private static final Syntax OID_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.38");
+  private static final Syntax OTHER_MAILBOX_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.39");
+  private static final Syntax POSTAL_ADDRESS_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.41");
+  private static final Syntax PRESENTATION_ADDRESS_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.43");
+  private static final Syntax PRINTABLE_STRING_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.44");
+  private static final Syntax PROTOCOL_INFORMATION_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.42");
+  private static final Syntax SUBSTRING_ASSERTION_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.58");
+  private static final Syntax SUPPORTED_ALGORITHM_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.49");
+  private static final Syntax TELEPHONE_NUMBER_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.50");
+  private static final Syntax TELETEX_TERMINAL_IDENTIFIER_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.51");
+  private static final Syntax TELEX_NUMBER_SYNTAX = CoreSchemaImpl
+      .getInstance().getSyntax("1.3.6.1.4.1.1466.115.121.1.52");
+  private static final Syntax UTC_TIME_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.4.1.1466.115.121.1.53");
+  private static final Syntax UUID_SYNTAX = CoreSchemaImpl.getInstance()
+      .getSyntax("1.3.6.1.1.16.1");
 
   // Core Matching Rules
-  private static final MatchingRule AUTH_PASSWORD_EXACT_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("1.3.6.1.4.1.4203.1.2.2");
-  private static final MatchingRule BIT_STRING_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.16");
-  private static final MatchingRule BOOLEAN_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.13");
-  private static final MatchingRule CASE_EXACT_IA5_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("1.3.6.1.4.1.1466.109.114.1");
-  private static final MatchingRule CASE_EXACT_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.5");
-  private static final MatchingRule CASE_EXACT_ORDERING_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.6");
-  private static final MatchingRule CASE_EXACT_SUBSTRINGS_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.7");
-  private static final MatchingRule CASE_IGNORE_IA5_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("1.3.6.1.4.1.1466.109.114.2");
-  private static final MatchingRule CASE_IGNORE_IA5_SUBSTRINGS_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("1.3.6.1.4.1.1466.109.114.3");
-  private static final MatchingRule CASE_IGNORE_LIST_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.11");
-  private static final MatchingRule CASE_IGNORE_LIST_SUBSTRINGS_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.12");
-  private static final MatchingRule CASE_IGNORE_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.2");
-  private static final MatchingRule CASE_IGNORE_ORDERING_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.3");
-  private static final MatchingRule CASE_IGNORE_SUBSTRINGS_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.4");
-  private static final MatchingRule DIRECTORY_STRING_FIRST_COMPONENT_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.31");
-  private static final MatchingRule DISTINGUISHED_NAME_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.1");
-  private static final MatchingRule GENERALIZED_TIME_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.27");
-  private static final MatchingRule GENERALIZED_TIME_ORDERING_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.28");
-  private static final MatchingRule INTEGER_FIRST_COMPONENT_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.29");
-  private static final MatchingRule INTEGER_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.14");
-  private static final MatchingRule INTEGER_ORDERING_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.15");
-  private static final MatchingRule KEYWORD_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.33");
-  private static final MatchingRule NUMERIC_STRING_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.8");
-  private static final MatchingRule NUMERIC_STRING_ORDERING_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.9");
-  private static final MatchingRule NUMERIC_STRING_SUBSTRINGS_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.10");
-  private static final MatchingRule OBJECT_IDENTIFIER_FIRST_COMPONENT_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.30");
-  private static final MatchingRule OBJECT_IDENTIFIER_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.0");
-  private static final MatchingRule OCTET_STRING_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.17");
-  private static final MatchingRule OCTET_STRING_ORDERING_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.18");
-  private static final MatchingRule OCTET_STRING_SUBSTRINGS_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.19");
-  private static final MatchingRule PRESENTATION_ADDRESS_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.22");
-  private static final MatchingRule PROTOCOL_INFORMATION_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.24");
-  private static final MatchingRule TELEPHONE_NUMBER_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.20");
-  private static final MatchingRule TELEPHONE_NUMBER_SUBSTRINGS_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.21");
-  private static final MatchingRule UNIQUE_MEMBER_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.23");
-  private static final MatchingRule UUID_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("1.3.6.1.1.16.2");
-  private static final MatchingRule UUID_ORDERING_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("1.3.6.1.1.16.3");
-  private static final MatchingRule WORD_MATCHING_RULE =
-    CoreSchemaImpl.getInstance().getMatchingRule("2.5.13.32");
+  private static final MatchingRule AUTH_PASSWORD_EXACT_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("1.3.6.1.4.1.4203.1.2.2");
+  private static final MatchingRule BIT_STRING_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.16");
+  private static final MatchingRule BOOLEAN_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.13");
+  private static final MatchingRule CASE_EXACT_IA5_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("1.3.6.1.4.1.1466.109.114.1");
+  private static final MatchingRule CASE_EXACT_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.5");
+  private static final MatchingRule CASE_EXACT_ORDERING_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.6");
+  private static final MatchingRule CASE_EXACT_SUBSTRINGS_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.7");
+  private static final MatchingRule CASE_IGNORE_IA5_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("1.3.6.1.4.1.1466.109.114.2");
+  private static final MatchingRule CASE_IGNORE_IA5_SUBSTRINGS_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("1.3.6.1.4.1.1466.109.114.3");
+  private static final MatchingRule CASE_IGNORE_LIST_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.11");
+  private static final MatchingRule CASE_IGNORE_LIST_SUBSTRINGS_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.12");
+  private static final MatchingRule CASE_IGNORE_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.2");
+  private static final MatchingRule CASE_IGNORE_ORDERING_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.3");
+  private static final MatchingRule CASE_IGNORE_SUBSTRINGS_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.4");
+  private static final MatchingRule DIRECTORY_STRING_FIRST_COMPONENT_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.31");
+  private static final MatchingRule DISTINGUISHED_NAME_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.1");
+  private static final MatchingRule GENERALIZED_TIME_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.27");
+  private static final MatchingRule GENERALIZED_TIME_ORDERING_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.28");
+  private static final MatchingRule INTEGER_FIRST_COMPONENT_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.29");
+  private static final MatchingRule INTEGER_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.14");
+  private static final MatchingRule INTEGER_ORDERING_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.15");
+  private static final MatchingRule KEYWORD_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.33");
+  private static final MatchingRule NUMERIC_STRING_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.8");
+  private static final MatchingRule NUMERIC_STRING_ORDERING_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.9");
+  private static final MatchingRule NUMERIC_STRING_SUBSTRINGS_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.10");
+  private static final MatchingRule OBJECT_IDENTIFIER_FIRST_COMPONENT_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.30");
+  private static final MatchingRule OBJECT_IDENTIFIER_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.0");
+  private static final MatchingRule OCTET_STRING_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.17");
+  private static final MatchingRule OCTET_STRING_ORDERING_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.18");
+  private static final MatchingRule OCTET_STRING_SUBSTRINGS_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.19");
+  private static final MatchingRule PRESENTATION_ADDRESS_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.22");
+  private static final MatchingRule PROTOCOL_INFORMATION_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.24");
+  private static final MatchingRule TELEPHONE_NUMBER_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.20");
+  private static final MatchingRule TELEPHONE_NUMBER_SUBSTRINGS_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.21");
+  private static final MatchingRule UNIQUE_MEMBER_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.23");
+  private static final MatchingRule UUID_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("1.3.6.1.1.16.2");
+  private static final MatchingRule UUID_ORDERING_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("1.3.6.1.1.16.3");
+  private static final MatchingRule WORD_MATCHING_RULE = CoreSchemaImpl
+      .getInstance().getMatchingRule("2.5.13.32");
 
   // Core Attribute Types
-  private static final AttributeType ALIASED_OBJECT_NAME_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.1");
-  private static final AttributeType ALT_SERVER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.6");
-  private static final AttributeType ATTRIBUTE_TYPES_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.21.5");
-  private static final AttributeType AUTH_PASSWORD_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.4.1.4203.1.3.4");
-  private static final AttributeType BUSINESS_CATEGORY_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.15");
-  private static final AttributeType CN_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.3");
-  private static final AttributeType CREATE_TIMESTAMP_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.18.1");
-  private static final AttributeType CREATORS_NAME_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.18.3");
-  private static final AttributeType C_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.6");
-  private static final AttributeType DC_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("0.9.2342.19200300.100.1.25");
-  private static final AttributeType DESCRIPTION_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.13");
-  private static final AttributeType DESTINATION_INDICATOR_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.27");
-  private static final AttributeType DISTINGUISHED_NAME_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.49");
-  private static final AttributeType DIT_CONTENT_RULES_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.21.2");
-  private static final AttributeType DIT_STRUCTURE_RULES_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.21.1");
-  private static final AttributeType DN_QUALIFIER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.46");
-  private static final AttributeType ENHANCED_SEARCH_GUIDE_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.47");
-  private static final AttributeType ENTRY_UUID_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.1.16.4");
-  private static final AttributeType FACSIMILE_TELEPHONE_NUMBER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.23");
-  private static final AttributeType GENERATION_QUALIFIER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.44");
-  private static final AttributeType GIVEN_NAME_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.42");
-  private static final AttributeType GOVERNING_STRUCTURE_RULE_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.21.10");
-  private static final AttributeType HOUSE_IDENTIFIER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.51");
-  private static final AttributeType INITIALS_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.43");
-  private static final AttributeType INTERNATIONAL_ISDN_NUMBER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.25");
-  private static final AttributeType LDAP_SYNTAXES_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.16");
-  private static final AttributeType L_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.7");
-  private static final AttributeType MATCHING_RULES_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.21.4");
-  private static final AttributeType MATCHING_RULE_USE_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.21.8");
-  private static final AttributeType MEMBER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.31");
-  private static final AttributeType MODIFIERS_NAME_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.18.4");
-  private static final AttributeType MODIFY_TIMESTAMP_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.18.2");
-  private static final AttributeType NAME_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.41");
-  private static final AttributeType NAME_FORMS_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.21.7");
-  private static final AttributeType NAMING_CONTEXTS_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.5");
-  private static final AttributeType OBJECT_CLASSES_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.21.6");
-  private static final AttributeType OBJECT_CLASS_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.0");
-  private static final AttributeType OU_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.11");
-  private static final AttributeType OWNER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.32");
-  private static final AttributeType O_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.10");
-  private static final AttributeType PHYSICAL_DELIVERY_OFFICE_NAME_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.19");
-  private static final AttributeType POSTAL_ADDRESS_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.16");
-  private static final AttributeType POSTAL_CODE_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.17");
-  private static final AttributeType POST_OFFICE_BOX_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.18");
-  private static final AttributeType PREFERRED_DELIVERY_METHOD_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.28");
-  private static final AttributeType REGISTERED_ADDRESS_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.26");
-  private static final AttributeType ROLE_OCCUPANT_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.33");
-  private static final AttributeType SEARCH_GUIDE_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.14");
-  private static final AttributeType SEE_ALSO_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.34");
-  private static final AttributeType SERIAL_NUMBER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.5");
-  private static final AttributeType SN_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.4");
-  private static final AttributeType STREET_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.9");
-  private static final AttributeType STRUCTURAL_OBJECT_CLASS_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.21.9");
-  private static final AttributeType ST_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.8");
-  private static final AttributeType SUBSCHEMA_SUBENTRY_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.18.10");
-  private static final AttributeType SUPPORTED_AUTH_PASSWORD_SCHEMES_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.4.1.4203.1.3.3");
-  private static final AttributeType SUPPORTED_CONTROL_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.13");
-  private static final AttributeType SUPPORTED_EXTENSION_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.7");
-  private static final AttributeType SUPPORTED_FEATURES_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.4.1.4203.1.3.5");
-  private static final AttributeType SUPPORTED_LDAP_VERSION_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.15");
-  private static final AttributeType SUPPORTED_SASL_MECHANISMS_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.14");
-  private static final AttributeType TELEPHONE_NUMBER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.20");
-  private static final AttributeType TELETEX_TERMINAL_IDENTIFIER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.22");
-  private static final AttributeType TELEX_NUMBER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.21");
-  private static final AttributeType TITLE_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.12");
-  private static final AttributeType UID_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("0.9.2342.19200300.100.1.1");
-  private static final AttributeType UNIQUE_MEMBER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.50");
-  private static final AttributeType USER_PASSWORD_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.35");
-  private static final AttributeType VENDOR_NAME_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.1.4");
-  private static final AttributeType VENDOR_VERSION_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("1.3.6.1.1.5");
-  private static final AttributeType X121_ADDRESS_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.24");
-  private static final AttributeType X500_UNIQUE_IDENTIFIER_ATTRIBUTE_TYPE =
-    CoreSchemaImpl.getInstance().getAttributeType("2.5.4.45");
+  private static final AttributeType ALIASED_OBJECT_NAME_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.1");
+  private static final AttributeType ALT_SERVER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.6");
+  private static final AttributeType ATTRIBUTE_TYPES_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.21.5");
+  private static final AttributeType AUTH_PASSWORD_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.4.1.4203.1.3.4");
+  private static final AttributeType BUSINESS_CATEGORY_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.15");
+  private static final AttributeType CN_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.3");
+  private static final AttributeType CREATE_TIMESTAMP_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.18.1");
+  private static final AttributeType CREATORS_NAME_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.18.3");
+  private static final AttributeType C_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.6");
+  private static final AttributeType DC_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("0.9.2342.19200300.100.1.25");
+  private static final AttributeType DESCRIPTION_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.13");
+  private static final AttributeType DESTINATION_INDICATOR_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.27");
+  private static final AttributeType DISTINGUISHED_NAME_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.49");
+  private static final AttributeType DIT_CONTENT_RULES_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.21.2");
+  private static final AttributeType DIT_STRUCTURE_RULES_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.21.1");
+  private static final AttributeType DN_QUALIFIER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.46");
+  private static final AttributeType ENHANCED_SEARCH_GUIDE_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.47");
+  private static final AttributeType ENTRY_UUID_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.1.16.4");
+  private static final AttributeType FACSIMILE_TELEPHONE_NUMBER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.23");
+  private static final AttributeType GENERATION_QUALIFIER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.44");
+  private static final AttributeType GIVEN_NAME_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.42");
+  private static final AttributeType GOVERNING_STRUCTURE_RULE_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.21.10");
+  private static final AttributeType HOUSE_IDENTIFIER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.51");
+  private static final AttributeType INITIALS_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.43");
+  private static final AttributeType INTERNATIONAL_ISDN_NUMBER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.25");
+  private static final AttributeType LDAP_SYNTAXES_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.16");
+  private static final AttributeType L_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.7");
+  private static final AttributeType MATCHING_RULES_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.21.4");
+  private static final AttributeType MATCHING_RULE_USE_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.21.8");
+  private static final AttributeType MEMBER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.31");
+  private static final AttributeType MODIFIERS_NAME_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.18.4");
+  private static final AttributeType MODIFY_TIMESTAMP_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.18.2");
+  private static final AttributeType NAME_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.41");
+  private static final AttributeType NAME_FORMS_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.21.7");
+  private static final AttributeType NAMING_CONTEXTS_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.5");
+  private static final AttributeType OBJECT_CLASSES_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.21.6");
+  private static final AttributeType OBJECT_CLASS_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.0");
+  private static final AttributeType OU_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.11");
+  private static final AttributeType OWNER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.32");
+  private static final AttributeType O_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.10");
+  private static final AttributeType PHYSICAL_DELIVERY_OFFICE_NAME_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.19");
+  private static final AttributeType POSTAL_ADDRESS_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.16");
+  private static final AttributeType POSTAL_CODE_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.17");
+  private static final AttributeType POST_OFFICE_BOX_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.18");
+  private static final AttributeType PREFERRED_DELIVERY_METHOD_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.28");
+  private static final AttributeType REGISTERED_ADDRESS_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.26");
+  private static final AttributeType ROLE_OCCUPANT_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.33");
+  private static final AttributeType SEARCH_GUIDE_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.14");
+  private static final AttributeType SEE_ALSO_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.34");
+  private static final AttributeType SERIAL_NUMBER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.5");
+  private static final AttributeType SN_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.4");
+  private static final AttributeType STREET_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.9");
+  private static final AttributeType STRUCTURAL_OBJECT_CLASS_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.21.9");
+  private static final AttributeType ST_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.8");
+  private static final AttributeType SUBSCHEMA_SUBENTRY_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.18.10");
+  private static final AttributeType SUPPORTED_AUTH_PASSWORD_SCHEMES_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.4.1.4203.1.3.3");
+  private static final AttributeType SUPPORTED_CONTROL_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.13");
+  private static final AttributeType SUPPORTED_EXTENSION_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.7");
+  private static final AttributeType SUPPORTED_FEATURES_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.4.1.4203.1.3.5");
+  private static final AttributeType SUPPORTED_LDAP_VERSION_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.15");
+  private static final AttributeType SUPPORTED_SASL_MECHANISMS_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.4.1.1466.101.120.14");
+  private static final AttributeType TELEPHONE_NUMBER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.20");
+  private static final AttributeType TELETEX_TERMINAL_IDENTIFIER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.22");
+  private static final AttributeType TELEX_NUMBER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.21");
+  private static final AttributeType TITLE_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.12");
+  private static final AttributeType UID_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("0.9.2342.19200300.100.1.1");
+  private static final AttributeType UNIQUE_MEMBER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.50");
+  private static final AttributeType USER_PASSWORD_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.35");
+  private static final AttributeType VENDOR_NAME_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.1.4");
+  private static final AttributeType VENDOR_VERSION_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("1.3.6.1.1.5");
+  private static final AttributeType X121_ADDRESS_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.24");
+  private static final AttributeType X500_UNIQUE_IDENTIFIER_ATTRIBUTE_TYPE = CoreSchemaImpl
+      .getInstance().getAttributeType("2.5.4.45");
 
   // Core Object Classes
-  private static final ObjectClass ALIAS_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.1");
-  private static final ObjectClass APPLICATION_PROCESS_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.11");
-  private static final ObjectClass AUTH_PASSWORD_OBJECT_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("1.3.6.1.4.1.4203.1.4.7");
-  private static final ObjectClass COUNTRY_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.2");
-  private static final ObjectClass DC_OBJECT_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("1.3.6.1.4.1.1466.344");
-  private static final ObjectClass DEVICE_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.14");
-  private static final ObjectClass EXTENSIBLE_OBJECT_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("1.3.6.1.4.1.1466.101.120.111");
-  private static final ObjectClass GROUP_OF_NAMES_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.9");
-  private static final ObjectClass GROUP_OF_UNIQUE_NAMES_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.17");
-  private static final ObjectClass LOCALITY_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.3");
-  private static final ObjectClass ORGANIZATIONAL_PERSON_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.7");
-  private static final ObjectClass ORGANIZATIONAL_ROLE_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.8");
-  private static final ObjectClass ORGANIZATIONAL_UNIT_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.5");
-  private static final ObjectClass ORGANIZATION_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.4");
-  private static final ObjectClass PERSON_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.6");
-  private static final ObjectClass RESIDENTIAL_PERSON_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.10");
-  private static final ObjectClass SUBSCHEMA_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.20.1");
-  private static final ObjectClass TOP_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("2.5.6.0");
-  private static final ObjectClass UID_OBJECT_OBJECT_CLASS =
-    CoreSchemaImpl.getInstance().getObjectClass("1.3.6.1.1.3.1");
-
-
-
-  // Prevent instantiation
-  private CoreSchema()
-  {
-    // Nothing to do.
-  }
+  private static final ObjectClass ALIAS_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.1");
+  private static final ObjectClass APPLICATION_PROCESS_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.11");
+  private static final ObjectClass AUTH_PASSWORD_OBJECT_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("1.3.6.1.4.1.4203.1.4.7");
+  private static final ObjectClass COUNTRY_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.2");
+  private static final ObjectClass DC_OBJECT_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("1.3.6.1.4.1.1466.344");
+  private static final ObjectClass DEVICE_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.14");
+  private static final ObjectClass EXTENSIBLE_OBJECT_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("1.3.6.1.4.1.1466.101.120.111");
+  private static final ObjectClass GROUP_OF_NAMES_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.9");
+  private static final ObjectClass GROUP_OF_UNIQUE_NAMES_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.17");
+  private static final ObjectClass LOCALITY_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.3");
+  private static final ObjectClass ORGANIZATIONAL_PERSON_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.7");
+  private static final ObjectClass ORGANIZATIONAL_ROLE_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.8");
+  private static final ObjectClass ORGANIZATIONAL_UNIT_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.5");
+  private static final ObjectClass ORGANIZATION_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.4");
+  private static final ObjectClass PERSON_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.6");
+  private static final ObjectClass RESIDENTIAL_PERSON_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.10");
+  private static final ObjectClass SUBSCHEMA_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.20.1");
+  private static final ObjectClass TOP_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("2.5.6.0");
+  private static final ObjectClass UID_OBJECT_OBJECT_CLASS = CoreSchemaImpl
+      .getInstance().getObjectClass("1.3.6.1.1.3.1");
 
 
 
   /**
-   * Returns a reference to the singleton core schema.
+   * Returns a reference to the {@code aliasedObjectName} Attribute Type which
+   * has the OID {@code 2.5.4.1}.
    *
-   * @return The core schema.
+   * @return A reference to the {@code aliasedObjectName} Attribute Type.
    */
-  public static Schema getInstance()
+  public static AttributeType getAliasedObjectNameAttributeType()
   {
-    return CoreSchemaImpl.getInstance();
+    return ALIASED_OBJECT_NAME_ATTRIBUTE_TYPE;
   }
 
 
 
   /**
-   * Returns a reference to the {@code Attribute Type Description Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.3}.
+   * Returns a reference to the {@code alias} Object Class which has the OID
+   * {@code 2.5.6.1}.
+   *
+   * @return A reference to the {@code alias} Object Class.
+   */
+  public static ObjectClass getAliasObjectClass()
+  {
+    return ALIAS_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code altServer} Attribute Type which has the
+   * OID {@code 1.3.6.1.4.1.1466.101.120.6}.
+   *
+   * @return A reference to the {@code altServer} Attribute Type.
+   */
+  public static AttributeType getAltServerAttributeType()
+  {
+    return ALT_SERVER_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code applicationProcess} Object Class which
+   * has the OID {@code 2.5.6.11}.
+   *
+   * @return A reference to the {@code applicationProcess} Object Class.
+   */
+  public static ObjectClass getApplicationProcessObjectClass()
+  {
+    return APPLICATION_PROCESS_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Attribute Type Description Syntax} which
+   * has the OID {@code 1.3.6.1.4.1.1466.115.121.1.3}.
    *
    * @return A reference to the {@code Attribute Type Description Syntax}.
    */
@@ -444,8 +472,21 @@
 
 
   /**
-   * Returns a reference to the {@code Authentication Password Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.4203.1.1.2}.
+   * Returns a reference to the {@code attributeTypes} Attribute Type which has
+   * the OID {@code 2.5.21.5}.
+   *
+   * @return A reference to the {@code attributeTypes} Attribute Type.
+   */
+  public static AttributeType getAttributeTypesAttributeType()
+  {
+    return ATTRIBUTE_TYPES_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Authentication Password Syntax} which has
+   * the OID {@code 1.3.6.1.4.1.4203.1.1.2}.
    *
    * @return A reference to the {@code Authentication Password Syntax}.
    */
@@ -457,534 +498,14 @@
 
 
   /**
-   * Returns a reference to the {@code Binary Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.5}.
+   * Returns a reference to the {@code authPassword} Attribute Type which has
+   * the OID {@code 1.3.6.1.4.1.4203.1.3.4}.
    *
-   * @return A reference to the {@code Binary Syntax}.
+   * @return A reference to the {@code authPassword} Attribute Type.
    */
-  public static Syntax getBinarySyntax()
+  public static AttributeType getAuthPasswordAttributeType()
   {
-    return BINARY_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Bit String Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.6}.
-   *
-   * @return A reference to the {@code Bit String Syntax}.
-   */
-  public static Syntax getBitStringSyntax()
-  {
-    return BIT_STRING_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Boolean Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.7}.
-   *
-   * @return A reference to the {@code Boolean Syntax}.
-   */
-  public static Syntax getBooleanSyntax()
-  {
-    return BOOLEAN_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Certificate List Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.9}.
-   *
-   * @return A reference to the {@code Certificate List Syntax}.
-   */
-  public static Syntax getCertificateListSyntax()
-  {
-    return CERTIFICATE_LIST_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Certificate Pair Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.10}.
-   *
-   * @return A reference to the {@code Certificate Pair Syntax}.
-   */
-  public static Syntax getCertificatePairSyntax()
-  {
-    return CERTIFICATE_PAIR_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Certificate Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.8}.
-   *
-   * @return A reference to the {@code Certificate Syntax}.
-   */
-  public static Syntax getCertificateSyntax()
-  {
-    return CERTIFICATE_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Country String Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.11}.
-   *
-   * @return A reference to the {@code Country String Syntax}.
-   */
-  public static Syntax getCountryStringSyntax()
-  {
-    return COUNTRY_STRING_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Delivery Method Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.14}.
-   *
-   * @return A reference to the {@code Delivery Method Syntax}.
-   */
-  public static Syntax getDeliveryMethodSyntax()
-  {
-    return DELIVERY_METHOD_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Directory String Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.15}.
-   *
-   * @return A reference to the {@code Directory String Syntax}.
-   */
-  public static Syntax getDirectoryStringSyntax()
-  {
-    return DIRECTORY_STRING_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code DIT Content Rule Description Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.16}.
-   *
-   * @return A reference to the {@code DIT Content Rule Description Syntax}.
-   */
-  public static Syntax getDITContentRuleDescriptionSyntax()
-  {
-    return DIT_CONTENT_RULE_DESCRIPTION_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code DIT Structure Rule Description Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.17}.
-   *
-   * @return A reference to the {@code DIT Structure Rule Description Syntax}.
-   */
-  public static Syntax getDITStructureRuleDescriptionSyntax()
-  {
-    return DIT_STRUCTURE_RULE_DESCRIPTION_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code DN Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.12}.
-   *
-   * @return A reference to the {@code DN Syntax}.
-   */
-  public static Syntax getDNSyntax()
-  {
-    return DN_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Enhanced Guide Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.21}.
-   *
-   * @return A reference to the {@code Enhanced Guide Syntax}.
-   */
-  public static Syntax getEnhancedGuideSyntax()
-  {
-    return ENHANCED_GUIDE_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Facsimile Telephone Number Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.22}.
-   *
-   * @return A reference to the {@code Facsimile Telephone Number Syntax}.
-   */
-  public static Syntax getFacsimileTelephoneNumberSyntax()
-  {
-    return FACSIMILE_TELEPHONE_NUMBER_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Fax Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.23}.
-   *
-   * @return A reference to the {@code Fax Syntax}.
-   */
-  public static Syntax getFaxSyntax()
-  {
-    return FAX_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Generalized Time Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.24}.
-   *
-   * @return A reference to the {@code Generalized Time Syntax}.
-   */
-  public static Syntax getGeneralizedTimeSyntax()
-  {
-    return GENERALIZED_TIME_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Guide Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.25}.
-   *
-   * @return A reference to the {@code Guide Syntax}.
-   */
-  public static Syntax getGuideSyntax()
-  {
-    return GUIDE_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code IA5 String Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.26}.
-   *
-   * @return A reference to the {@code IA5 String Syntax}.
-   */
-  public static Syntax getIA5StringSyntax()
-  {
-    return IA5_STRING_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Integer Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.27}.
-   *
-   * @return A reference to the {@code Integer Syntax}.
-   */
-  public static Syntax getIntegerSyntax()
-  {
-    return INTEGER_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code JPEG Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.28}.
-   *
-   * @return A reference to the {@code JPEG Syntax}.
-   */
-  public static Syntax getJPEGSyntax()
-  {
-    return JPEG_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code LDAP Syntax Description Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.54}.
-   *
-   * @return A reference to the {@code LDAP Syntax Description Syntax}.
-   */
-  public static Syntax getLDAPSyntaxDescriptionSyntax()
-  {
-    return LDAP_SYNTAX_DESCRIPTION_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Matching Rule Description Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.30}.
-   *
-   * @return A reference to the {@code Matching Rule Description Syntax}.
-   */
-  public static Syntax getMatchingRuleDescriptionSyntax()
-  {
-    return MATCHING_RULE_DESCRIPTION_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Matching Rule Use Description Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.31}.
-   *
-   * @return A reference to the {@code Matching Rule Use Description Syntax}.
-   */
-  public static Syntax getMatchingRuleUseDescriptionSyntax()
-  {
-    return MATCHING_RULE_USE_DESCRIPTION_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Name and Optional UID Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.34}.
-   *
-   * @return A reference to the {@code Name and Optional UID Syntax}.
-   */
-  public static Syntax getNameAndOptionalUIDSyntax()
-  {
-    return NAME_AND_OPTIONAL_UID_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Name Form Description Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.35}.
-   *
-   * @return A reference to the {@code Name Form Description Syntax}.
-   */
-  public static Syntax getNameFormDescriptionSyntax()
-  {
-    return NAME_FORM_DESCRIPTION_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Numeric String Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.36}.
-   *
-   * @return A reference to the {@code Numeric String Syntax}.
-   */
-  public static Syntax getNumericStringSyntax()
-  {
-    return NUMERIC_STRING_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Object Class Description Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.37}.
-   *
-   * @return A reference to the {@code Object Class Description Syntax}.
-   */
-  public static Syntax getObjectClassDescriptionSyntax()
-  {
-    return OBJECT_CLASS_DESCRIPTION_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Octet String Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.40}.
-   *
-   * @return A reference to the {@code Octet String Syntax}.
-   */
-  public static Syntax getOctetStringSyntax()
-  {
-    return OCTET_STRING_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code OID Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.38}.
-   *
-   * @return A reference to the {@code OID Syntax}.
-   */
-  public static Syntax getOIDSyntax()
-  {
-    return OID_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Other Mailbox Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.39}.
-   *
-   * @return A reference to the {@code Other Mailbox Syntax}.
-   */
-  public static Syntax getOtherMailboxSyntax()
-  {
-    return OTHER_MAILBOX_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Postal Address Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.41}.
-   *
-   * @return A reference to the {@code Postal Address Syntax}.
-   */
-  public static Syntax getPostalAddressSyntax()
-  {
-    return POSTAL_ADDRESS_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Presentation Address Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.43}.
-   *
-   * @return A reference to the {@code Presentation Address Syntax}.
-   */
-  public static Syntax getPresentationAddressSyntax()
-  {
-    return PRESENTATION_ADDRESS_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Printable String Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.44}.
-   *
-   * @return A reference to the {@code Printable String Syntax}.
-   */
-  public static Syntax getPrintableStringSyntax()
-  {
-    return PRINTABLE_STRING_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Protocol Information Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.42}.
-   *
-   * @return A reference to the {@code Protocol Information Syntax}.
-   */
-  public static Syntax getProtocolInformationSyntax()
-  {
-    return PROTOCOL_INFORMATION_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Substring Assertion Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.58}.
-   *
-   * @return A reference to the {@code Substring Assertion Syntax}.
-   */
-  public static Syntax getSubstringAssertionSyntax()
-  {
-    return SUBSTRING_ASSERTION_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Supported Algorithm Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.49}.
-   *
-   * @return A reference to the {@code Supported Algorithm Syntax}.
-   */
-  public static Syntax getSupportedAlgorithmSyntax()
-  {
-    return SUPPORTED_ALGORITHM_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Telephone Number Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.50}.
-   *
-   * @return A reference to the {@code Telephone Number Syntax}.
-   */
-  public static Syntax getTelephoneNumberSyntax()
-  {
-    return TELEPHONE_NUMBER_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Teletex Terminal Identifier Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.51}.
-   *
-   * @return A reference to the {@code Teletex Terminal Identifier Syntax}.
-   */
-  public static Syntax getTeletexTerminalIdentifierSyntax()
-  {
-    return TELETEX_TERMINAL_IDENTIFIER_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code Telex Number Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.52}.
-   *
-   * @return A reference to the {@code Telex Number Syntax}.
-   */
-  public static Syntax getTelexNumberSyntax()
-  {
-    return TELEX_NUMBER_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code UTC Time Syntax}
-   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.53}.
-   *
-   * @return A reference to the {@code UTC Time Syntax}.
-   */
-  public static Syntax getUTCTimeSyntax()
-  {
-    return UTC_TIME_SYNTAX;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code UUID Syntax}
-   * which has the OID {@code 1.3.6.1.1.16.1}.
-   *
-   * @return A reference to the {@code UUID Syntax}.
-   */
-  public static Syntax getUUIDSyntax()
-  {
-    return UUID_SYNTAX;
+    return AUTH_PASSWORD_ATTRIBUTE_TYPE;
   }
 
 
@@ -1003,8 +524,34 @@
 
 
   /**
-   * Returns a reference to the {@code bitStringMatch} Matching Rule
-   * which has the OID {@code 2.5.13.16}.
+   * Returns a reference to the {@code authPasswordObject} Object Class which
+   * has the OID {@code 1.3.6.1.4.1.4203.1.4.7}.
+   *
+   * @return A reference to the {@code authPasswordObject} Object Class.
+   */
+  public static ObjectClass getAuthPasswordObjectObjectClass()
+  {
+    return AUTH_PASSWORD_OBJECT_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Binary Syntax} which has the OID {@code
+   * 1.3.6.1.4.1.1466.115.121.1.5}.
+   *
+   * @return A reference to the {@code Binary Syntax}.
+   */
+  public static Syntax getBinarySyntax()
+  {
+    return BINARY_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code bitStringMatch} Matching Rule which has
+   * the OID {@code 2.5.13.16}.
    *
    * @return A reference to the {@code bitStringMatch} Matching Rule.
    */
@@ -1016,8 +563,21 @@
 
 
   /**
-   * Returns a reference to the {@code booleanMatch} Matching Rule
-   * which has the OID {@code 2.5.13.13}.
+   * Returns a reference to the {@code Bit String Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.6}.
+   *
+   * @return A reference to the {@code Bit String Syntax}.
+   */
+  public static Syntax getBitStringSyntax()
+  {
+    return BIT_STRING_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code booleanMatch} Matching Rule which has the
+   * OID {@code 2.5.13.13}.
    *
    * @return A reference to the {@code booleanMatch} Matching Rule.
    */
@@ -1029,8 +589,34 @@
 
 
   /**
-   * Returns a reference to the {@code caseExactIA5Match} Matching Rule
-   * which has the OID {@code 1.3.6.1.4.1.1466.109.114.1}.
+   * Returns a reference to the {@code Boolean Syntax} which has the OID {@code
+   * 1.3.6.1.4.1.1466.115.121.1.7}.
+   *
+   * @return A reference to the {@code Boolean Syntax}.
+   */
+  public static Syntax getBooleanSyntax()
+  {
+    return BOOLEAN_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code businessCategory} Attribute Type which
+   * has the OID {@code 2.5.4.15}.
+   *
+   * @return A reference to the {@code businessCategory} Attribute Type.
+   */
+  public static AttributeType getBusinessCategoryAttributeType()
+  {
+    return BUSINESS_CATEGORY_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code caseExactIA5Match} Matching Rule which
+   * has the OID {@code 1.3.6.1.4.1.1466.109.114.1}.
    *
    * @return A reference to the {@code caseExactIA5Match} Matching Rule.
    */
@@ -1042,8 +628,8 @@
 
 
   /**
-   * Returns a reference to the {@code caseExactMatch} Matching Rule
-   * which has the OID {@code 2.5.13.5}.
+   * Returns a reference to the {@code caseExactMatch} Matching Rule which has
+   * the OID {@code 2.5.13.5}.
    *
    * @return A reference to the {@code caseExactMatch} Matching Rule.
    */
@@ -1081,8 +667,8 @@
 
 
   /**
-   * Returns a reference to the {@code caseIgnoreIA5Match} Matching Rule
-   * which has the OID {@code 1.3.6.1.4.1.1466.109.114.2}.
+   * Returns a reference to the {@code caseIgnoreIA5Match} Matching Rule which
+   * has the OID {@code 1.3.6.1.4.1.1466.109.114.2}.
    *
    * @return A reference to the {@code caseIgnoreIA5Match} Matching Rule.
    */
@@ -1094,10 +680,11 @@
 
 
   /**
-   * Returns a reference to the {@code caseIgnoreIA5SubstringsMatch} Matching Rule
-   * which has the OID {@code 1.3.6.1.4.1.1466.109.114.3}.
+   * Returns a reference to the {@code caseIgnoreIA5SubstringsMatch} Matching
+   * Rule which has the OID {@code 1.3.6.1.4.1.1466.109.114.3}.
    *
-   * @return A reference to the {@code caseIgnoreIA5SubstringsMatch} Matching Rule.
+   * @return A reference to the {@code caseIgnoreIA5SubstringsMatch} Matching
+   *         Rule.
    */
   public static MatchingRule getCaseIgnoreIA5SubstringsMatchingRule()
   {
@@ -1107,8 +694,8 @@
 
 
   /**
-   * Returns a reference to the {@code caseIgnoreListMatch} Matching Rule
-   * which has the OID {@code 2.5.13.11}.
+   * Returns a reference to the {@code caseIgnoreListMatch} Matching Rule which
+   * has the OID {@code 2.5.13.11}.
    *
    * @return A reference to the {@code caseIgnoreListMatch} Matching Rule.
    */
@@ -1120,10 +707,11 @@
 
 
   /**
-   * Returns a reference to the {@code caseIgnoreListSubstringsMatch} Matching Rule
-   * which has the OID {@code 2.5.13.12}.
+   * Returns a reference to the {@code caseIgnoreListSubstringsMatch} Matching
+   * Rule which has the OID {@code 2.5.13.12}.
    *
-   * @return A reference to the {@code caseIgnoreListSubstringsMatch} Matching Rule.
+   * @return A reference to the {@code caseIgnoreListSubstringsMatch} Matching
+   *         Rule.
    */
   public static MatchingRule getCaseIgnoreListSubstringsMatchingRule()
   {
@@ -1133,8 +721,8 @@
 
 
   /**
-   * Returns a reference to the {@code caseIgnoreMatch} Matching Rule
-   * which has the OID {@code 2.5.13.2}.
+   * Returns a reference to the {@code caseIgnoreMatch} Matching Rule which has
+   * the OID {@code 2.5.13.2}.
    *
    * @return A reference to the {@code caseIgnoreMatch} Matching Rule.
    */
@@ -1172,10 +760,206 @@
 
 
   /**
-   * Returns a reference to the {@code directoryStringFirstComponentMatch} Matching Rule
-   * which has the OID {@code 2.5.13.31}.
+   * Returns a reference to the {@code c} Attribute Type which has the OID
+   * {@code 2.5.4.6}.
    *
-   * @return A reference to the {@code directoryStringFirstComponentMatch} Matching Rule.
+   * @return A reference to the {@code c} Attribute Type.
+   */
+  public static AttributeType getCAttributeType()
+  {
+    return C_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Certificate List Syntax} which has the
+   * OID {@code 1.3.6.1.4.1.1466.115.121.1.9}.
+   *
+   * @return A reference to the {@code Certificate List Syntax}.
+   */
+  public static Syntax getCertificateListSyntax()
+  {
+    return CERTIFICATE_LIST_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Certificate Pair Syntax} which has the
+   * OID {@code 1.3.6.1.4.1.1466.115.121.1.10}.
+   *
+   * @return A reference to the {@code Certificate Pair Syntax}.
+   */
+  public static Syntax getCertificatePairSyntax()
+  {
+    return CERTIFICATE_PAIR_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Certificate Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.8}.
+   *
+   * @return A reference to the {@code Certificate Syntax}.
+   */
+  public static Syntax getCertificateSyntax()
+  {
+    return CERTIFICATE_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code cn} Attribute Type which has the OID
+   * {@code 2.5.4.3}.
+   *
+   * @return A reference to the {@code cn} Attribute Type.
+   */
+  public static AttributeType getCNAttributeType()
+  {
+    return CN_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code country} Object Class which has the OID
+   * {@code 2.5.6.2}.
+   *
+   * @return A reference to the {@code country} Object Class.
+   */
+  public static ObjectClass getCountryObjectClass()
+  {
+    return COUNTRY_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Country String Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.11}.
+   *
+   * @return A reference to the {@code Country String Syntax}.
+   */
+  public static Syntax getCountryStringSyntax()
+  {
+    return COUNTRY_STRING_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code createTimestamp} Attribute Type which has
+   * the OID {@code 2.5.18.1}.
+   *
+   * @return A reference to the {@code createTimestamp} Attribute Type.
+   */
+  public static AttributeType getCreateTimestampAttributeType()
+  {
+    return CREATE_TIMESTAMP_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code creatorsName} Attribute Type which has
+   * the OID {@code 2.5.18.3}.
+   *
+   * @return A reference to the {@code creatorsName} Attribute Type.
+   */
+  public static AttributeType getCreatorsNameAttributeType()
+  {
+    return CREATORS_NAME_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code dc} Attribute Type which has the OID
+   * {@code 0.9.2342.19200300.100.1.25}.
+   *
+   * @return A reference to the {@code dc} Attribute Type.
+   */
+  public static AttributeType getDCAttributeType()
+  {
+    return DC_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code dcObject} Object Class which has the OID
+   * {@code 1.3.6.1.4.1.1466.344}.
+   *
+   * @return A reference to the {@code dcObject} Object Class.
+   */
+  public static ObjectClass getDCObjectObjectClass()
+  {
+    return DC_OBJECT_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Delivery Method Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.14}.
+   *
+   * @return A reference to the {@code Delivery Method Syntax}.
+   */
+  public static Syntax getDeliveryMethodSyntax()
+  {
+    return DELIVERY_METHOD_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code description} Attribute Type which has the
+   * OID {@code 2.5.4.13}.
+   *
+   * @return A reference to the {@code description} Attribute Type.
+   */
+  public static AttributeType getDescriptionAttributeType()
+  {
+    return DESCRIPTION_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code destinationIndicator} Attribute Type
+   * which has the OID {@code 2.5.4.27}.
+   *
+   * @return A reference to the {@code destinationIndicator} Attribute Type.
+   */
+  public static AttributeType getDestinationIndicatorAttributeType()
+  {
+    return DESTINATION_INDICATOR_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code device} Object Class which has the OID
+   * {@code 2.5.6.14}.
+   *
+   * @return A reference to the {@code device} Object Class.
+   */
+  public static ObjectClass getDeviceObjectClass()
+  {
+    return DEVICE_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code directoryStringFirstComponentMatch}
+   * Matching Rule which has the OID {@code 2.5.13.31}.
+   *
+   * @return A reference to the {@code directoryStringFirstComponentMatch}
+   *         Matching Rule.
    */
   public static MatchingRule getDirectoryStringFirstComponentMatchingRule()
   {
@@ -1185,6 +969,32 @@
 
 
   /**
+   * Returns a reference to the {@code Directory String Syntax} which has the
+   * OID {@code 1.3.6.1.4.1.1466.115.121.1.15}.
+   *
+   * @return A reference to the {@code Directory String Syntax}.
+   */
+  public static Syntax getDirectoryStringSyntax()
+  {
+    return DIRECTORY_STRING_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code distinguishedName} Attribute Type which
+   * has the OID {@code 2.5.4.49}.
+   *
+   * @return A reference to the {@code distinguishedName} Attribute Type.
+   */
+  public static AttributeType getDistinguishedNameAttributeType()
+  {
+    return DISTINGUISHED_NAME_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
    * Returns a reference to the {@code distinguishedNameMatch} Matching Rule
    * which has the OID {@code 2.5.13.1}.
    *
@@ -1198,8 +1008,177 @@
 
 
   /**
-   * Returns a reference to the {@code generalizedTimeMatch} Matching Rule
-   * which has the OID {@code 2.5.13.27}.
+   * Returns a reference to the {@code DIT Content Rule Description Syntax}
+   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.16}.
+   *
+   * @return A reference to the {@code DIT Content Rule Description Syntax}.
+   */
+  public static Syntax getDITContentRuleDescriptionSyntax()
+  {
+    return DIT_CONTENT_RULE_DESCRIPTION_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code ditContentRules} Attribute Type which has
+   * the OID {@code 2.5.21.2}.
+   *
+   * @return A reference to the {@code ditContentRules} Attribute Type.
+   */
+  public static AttributeType getDITContentRulesAttributeType()
+  {
+    return DIT_CONTENT_RULES_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code DIT Structure Rule Description Syntax}
+   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.17}.
+   *
+   * @return A reference to the {@code DIT Structure Rule Description Syntax}.
+   */
+  public static Syntax getDITStructureRuleDescriptionSyntax()
+  {
+    return DIT_STRUCTURE_RULE_DESCRIPTION_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code ditStructureRules} Attribute Type which
+   * has the OID {@code 2.5.21.1}.
+   *
+   * @return A reference to the {@code ditStructureRules} Attribute Type.
+   */
+  public static AttributeType getDITStructureRulesAttributeType()
+  {
+    return DIT_STRUCTURE_RULES_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code dnQualifier} Attribute Type which has the
+   * OID {@code 2.5.4.46}.
+   *
+   * @return A reference to the {@code dnQualifier} Attribute Type.
+   */
+  public static AttributeType getDNQualifierAttributeType()
+  {
+    return DN_QUALIFIER_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code DN Syntax} which has the OID {@code
+   * 1.3.6.1.4.1.1466.115.121.1.12}.
+   *
+   * @return A reference to the {@code DN Syntax}.
+   */
+  public static Syntax getDNSyntax()
+  {
+    return DN_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Enhanced Guide Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.21}.
+   *
+   * @return A reference to the {@code Enhanced Guide Syntax}.
+   */
+  public static Syntax getEnhancedGuideSyntax()
+  {
+    return ENHANCED_GUIDE_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code enhancedSearchGuide} Attribute Type which
+   * has the OID {@code 2.5.4.47}.
+   *
+   * @return A reference to the {@code enhancedSearchGuide} Attribute Type.
+   */
+  public static AttributeType getEnhancedSearchGuideAttributeType()
+  {
+    return ENHANCED_SEARCH_GUIDE_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code entryUUID} Attribute Type which has the
+   * OID {@code 1.3.6.1.1.16.4}.
+   *
+   * @return A reference to the {@code entryUUID} Attribute Type.
+   */
+  public static AttributeType getEntryUUIDAttributeType()
+  {
+    return ENTRY_UUID_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code extensibleObject} Object Class which has
+   * the OID {@code 1.3.6.1.4.1.1466.101.120.111}.
+   *
+   * @return A reference to the {@code extensibleObject} Object Class.
+   */
+  public static ObjectClass getExtensibleObjectObjectClass()
+  {
+    return EXTENSIBLE_OBJECT_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code facsimileTelephoneNumber} Attribute Type
+   * which has the OID {@code 2.5.4.23}.
+   *
+   * @return A reference to the {@code facsimileTelephoneNumber} Attribute Type.
+   */
+  public static AttributeType getFacsimileTelephoneNumberAttributeType()
+  {
+    return FACSIMILE_TELEPHONE_NUMBER_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Facsimile Telephone Number Syntax} which
+   * has the OID {@code 1.3.6.1.4.1.1466.115.121.1.22}.
+   *
+   * @return A reference to the {@code Facsimile Telephone Number Syntax}.
+   */
+  public static Syntax getFacsimileTelephoneNumberSyntax()
+  {
+    return FACSIMILE_TELEPHONE_NUMBER_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Fax Syntax} which has the OID {@code
+   * 1.3.6.1.4.1.1466.115.121.1.23}.
+   *
+   * @return A reference to the {@code Fax Syntax}.
+   */
+  public static Syntax getFaxSyntax()
+  {
+    return FAX_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code generalizedTimeMatch} Matching Rule which
+   * has the OID {@code 2.5.13.27}.
    *
    * @return A reference to the {@code generalizedTimeMatch} Matching Rule.
    */
@@ -1211,10 +1190,11 @@
 
 
   /**
-   * Returns a reference to the {@code generalizedTimeOrderingMatch} Matching Rule
-   * which has the OID {@code 2.5.13.28}.
+   * Returns a reference to the {@code generalizedTimeOrderingMatch} Matching
+   * Rule which has the OID {@code 2.5.13.28}.
    *
-   * @return A reference to the {@code generalizedTimeOrderingMatch} Matching Rule.
+   * @return A reference to the {@code generalizedTimeOrderingMatch} Matching
+   *         Rule.
    */
   public static MatchingRule getGeneralizedTimeOrderingMatchingRule()
   {
@@ -1224,10 +1204,153 @@
 
 
   /**
+   * Returns a reference to the {@code Generalized Time Syntax} which has the
+   * OID {@code 1.3.6.1.4.1.1466.115.121.1.24}.
+   *
+   * @return A reference to the {@code Generalized Time Syntax}.
+   */
+  public static Syntax getGeneralizedTimeSyntax()
+  {
+    return GENERALIZED_TIME_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code generationQualifier} Attribute Type which
+   * has the OID {@code 2.5.4.44}.
+   *
+   * @return A reference to the {@code generationQualifier} Attribute Type.
+   */
+  public static AttributeType getGenerationQualifierAttributeType()
+  {
+    return GENERATION_QUALIFIER_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code givenName} Attribute Type which has the
+   * OID {@code 2.5.4.42}.
+   *
+   * @return A reference to the {@code givenName} Attribute Type.
+   */
+  public static AttributeType getGivenNameAttributeType()
+  {
+    return GIVEN_NAME_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code governingStructureRule} Attribute Type
+   * which has the OID {@code 2.5.21.10}.
+   *
+   * @return A reference to the {@code governingStructureRule} Attribute Type.
+   */
+  public static AttributeType getGoverningStructureRuleAttributeType()
+  {
+    return GOVERNING_STRUCTURE_RULE_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code groupOfNames} Object Class which has the
+   * OID {@code 2.5.6.9}.
+   *
+   * @return A reference to the {@code groupOfNames} Object Class.
+   */
+  public static ObjectClass getGroupOfNamesObjectClass()
+  {
+    return GROUP_OF_NAMES_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code groupOfUniqueNames} Object Class which
+   * has the OID {@code 2.5.6.17}.
+   *
+   * @return A reference to the {@code groupOfUniqueNames} Object Class.
+   */
+  public static ObjectClass getGroupOfUniqueNamesObjectClass()
+  {
+    return GROUP_OF_UNIQUE_NAMES_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Guide Syntax} which has the OID {@code
+   * 1.3.6.1.4.1.1466.115.121.1.25}.
+   *
+   * @return A reference to the {@code Guide Syntax}.
+   */
+  public static Syntax getGuideSyntax()
+  {
+    return GUIDE_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code houseIdentifier} Attribute Type which has
+   * the OID {@code 2.5.4.51}.
+   *
+   * @return A reference to the {@code houseIdentifier} Attribute Type.
+   */
+  public static AttributeType getHouseIdentifierAttributeType()
+  {
+    return HOUSE_IDENTIFIER_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code IA5 String Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.26}.
+   *
+   * @return A reference to the {@code IA5 String Syntax}.
+   */
+  public static Syntax getIA5StringSyntax()
+  {
+    return IA5_STRING_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code initials} Attribute Type which has the
+   * OID {@code 2.5.4.43}.
+   *
+   * @return A reference to the {@code initials} Attribute Type.
+   */
+  public static AttributeType getInitialsAttributeType()
+  {
+    return INITIALS_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the singleton core schema.
+   *
+   * @return The core schema.
+   */
+  public static Schema getInstance()
+  {
+    return CoreSchemaImpl.getInstance();
+  }
+
+
+
+  /**
    * Returns a reference to the {@code integerFirstComponentMatch} Matching Rule
    * which has the OID {@code 2.5.13.29}.
    *
-   * @return A reference to the {@code integerFirstComponentMatch} Matching Rule.
+   * @return A reference to the {@code integerFirstComponentMatch} Matching
+   *         Rule.
    */
   public static MatchingRule getIntegerFirstComponentMatchingRule()
   {
@@ -1237,8 +1360,8 @@
 
 
   /**
-   * Returns a reference to the {@code integerMatch} Matching Rule
-   * which has the OID {@code 2.5.13.14}.
+   * Returns a reference to the {@code integerMatch} Matching Rule which has the
+   * OID {@code 2.5.13.14}.
    *
    * @return A reference to the {@code integerMatch} Matching Rule.
    */
@@ -1250,8 +1373,8 @@
 
 
   /**
-   * Returns a reference to the {@code integerOrderingMatch} Matching Rule
-   * which has the OID {@code 2.5.13.15}.
+   * Returns a reference to the {@code integerOrderingMatch} Matching Rule which
+   * has the OID {@code 2.5.13.15}.
    *
    * @return A reference to the {@code integerOrderingMatch} Matching Rule.
    */
@@ -1263,8 +1386,47 @@
 
 
   /**
-   * Returns a reference to the {@code keywordMatch} Matching Rule
-   * which has the OID {@code 2.5.13.33}.
+   * Returns a reference to the {@code Integer Syntax} which has the OID {@code
+   * 1.3.6.1.4.1.1466.115.121.1.27}.
+   *
+   * @return A reference to the {@code Integer Syntax}.
+   */
+  public static Syntax getIntegerSyntax()
+  {
+    return INTEGER_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code internationalISDNNumber} Attribute Type
+   * which has the OID {@code 2.5.4.25}.
+   *
+   * @return A reference to the {@code internationalISDNNumber} Attribute Type.
+   */
+  public static AttributeType getInternationalISDNNumberAttributeType()
+  {
+    return INTERNATIONAL_ISDN_NUMBER_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code JPEG Syntax} which has the OID {@code
+   * 1.3.6.1.4.1.1466.115.121.1.28}.
+   *
+   * @return A reference to the {@code JPEG Syntax}.
+   */
+  public static Syntax getJPEGSyntax()
+  {
+    return JPEG_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code keywordMatch} Matching Rule which has the
+   * OID {@code 2.5.13.33}.
    *
    * @return A reference to the {@code keywordMatch} Matching Rule.
    */
@@ -1276,8 +1438,216 @@
 
 
   /**
-   * Returns a reference to the {@code numericStringMatch} Matching Rule
-   * which has the OID {@code 2.5.13.8}.
+   * Returns a reference to the {@code l} Attribute Type which has the OID
+   * {@code 2.5.4.7}.
+   *
+   * @return A reference to the {@code l} Attribute Type.
+   */
+  public static AttributeType getLAttributeType()
+  {
+    return L_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code LDAP Syntax Description Syntax} which has
+   * the OID {@code 1.3.6.1.4.1.1466.115.121.1.54}.
+   *
+   * @return A reference to the {@code LDAP Syntax Description Syntax}.
+   */
+  public static Syntax getLDAPSyntaxDescriptionSyntax()
+  {
+    return LDAP_SYNTAX_DESCRIPTION_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code ldapSyntaxes} Attribute Type which has
+   * the OID {@code 1.3.6.1.4.1.1466.101.120.16}.
+   *
+   * @return A reference to the {@code ldapSyntaxes} Attribute Type.
+   */
+  public static AttributeType getLDAPSyntaxesAttributeType()
+  {
+    return LDAP_SYNTAXES_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code locality} Object Class which has the OID
+   * {@code 2.5.6.3}.
+   *
+   * @return A reference to the {@code locality} Object Class.
+   */
+  public static ObjectClass getLocalityObjectClass()
+  {
+    return LOCALITY_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Matching Rule Description Syntax} which
+   * has the OID {@code 1.3.6.1.4.1.1466.115.121.1.30}.
+   *
+   * @return A reference to the {@code Matching Rule Description Syntax}.
+   */
+  public static Syntax getMatchingRuleDescriptionSyntax()
+  {
+    return MATCHING_RULE_DESCRIPTION_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code matchingRules} Attribute Type which has
+   * the OID {@code 2.5.21.4}.
+   *
+   * @return A reference to the {@code matchingRules} Attribute Type.
+   */
+  public static AttributeType getMatchingRulesAttributeType()
+  {
+    return MATCHING_RULES_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code matchingRuleUse} Attribute Type which has
+   * the OID {@code 2.5.21.8}.
+   *
+   * @return A reference to the {@code matchingRuleUse} Attribute Type.
+   */
+  public static AttributeType getMatchingRuleUseAttributeType()
+  {
+    return MATCHING_RULE_USE_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Matching Rule Use Description Syntax}
+   * which has the OID {@code 1.3.6.1.4.1.1466.115.121.1.31}.
+   *
+   * @return A reference to the {@code Matching Rule Use Description Syntax}.
+   */
+  public static Syntax getMatchingRuleUseDescriptionSyntax()
+  {
+    return MATCHING_RULE_USE_DESCRIPTION_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code member} Attribute Type which has the OID
+   * {@code 2.5.4.31}.
+   *
+   * @return A reference to the {@code member} Attribute Type.
+   */
+  public static AttributeType getMemberAttributeType()
+  {
+    return MEMBER_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code modifiersName} Attribute Type which has
+   * the OID {@code 2.5.18.4}.
+   *
+   * @return A reference to the {@code modifiersName} Attribute Type.
+   */
+  public static AttributeType getModifiersNameAttributeType()
+  {
+    return MODIFIERS_NAME_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code modifyTimestamp} Attribute Type which has
+   * the OID {@code 2.5.18.2}.
+   *
+   * @return A reference to the {@code modifyTimestamp} Attribute Type.
+   */
+  public static AttributeType getModifyTimestampAttributeType()
+  {
+    return MODIFY_TIMESTAMP_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Name and Optional UID Syntax} which has
+   * the OID {@code 1.3.6.1.4.1.1466.115.121.1.34}.
+   *
+   * @return A reference to the {@code Name and Optional UID Syntax}.
+   */
+  public static Syntax getNameAndOptionalUIDSyntax()
+  {
+    return NAME_AND_OPTIONAL_UID_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code name} Attribute Type which has the OID
+   * {@code 2.5.4.41}.
+   *
+   * @return A reference to the {@code name} Attribute Type.
+   */
+  public static AttributeType getNameAttributeType()
+  {
+    return NAME_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Name Form Description Syntax} which has
+   * the OID {@code 1.3.6.1.4.1.1466.115.121.1.35}.
+   *
+   * @return A reference to the {@code Name Form Description Syntax}.
+   */
+  public static Syntax getNameFormDescriptionSyntax()
+  {
+    return NAME_FORM_DESCRIPTION_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code nameForms} Attribute Type which has the
+   * OID {@code 2.5.21.7}.
+   *
+   * @return A reference to the {@code nameForms} Attribute Type.
+   */
+  public static AttributeType getNameFormsAttributeType()
+  {
+    return NAME_FORMS_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code namingContexts} Attribute Type which has
+   * the OID {@code 1.3.6.1.4.1.1466.101.120.5}.
+   *
+   * @return A reference to the {@code namingContexts} Attribute Type.
+   */
+  public static AttributeType getNamingContextsAttributeType()
+  {
+    return NAMING_CONTEXTS_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code numericStringMatch} Matching Rule which
+   * has the OID {@code 2.5.13.8}.
    *
    * @return A reference to the {@code numericStringMatch} Matching Rule.
    */
@@ -1292,7 +1662,8 @@
    * Returns a reference to the {@code numericStringOrderingMatch} Matching Rule
    * which has the OID {@code 2.5.13.9}.
    *
-   * @return A reference to the {@code numericStringOrderingMatch} Matching Rule.
+   * @return A reference to the {@code numericStringOrderingMatch} Matching
+   *         Rule.
    */
   public static MatchingRule getNumericStringOrderingMatchingRule()
   {
@@ -1302,10 +1673,11 @@
 
 
   /**
-   * Returns a reference to the {@code numericStringSubstringsMatch} Matching Rule
-   * which has the OID {@code 2.5.13.10}.
+   * Returns a reference to the {@code numericStringSubstringsMatch} Matching
+   * Rule which has the OID {@code 2.5.13.10}.
    *
-   * @return A reference to the {@code numericStringSubstringsMatch} Matching Rule.
+   * @return A reference to the {@code numericStringSubstringsMatch} Matching
+   *         Rule.
    */
   public static MatchingRule getNumericStringSubstringsMatchingRule()
   {
@@ -1315,10 +1687,76 @@
 
 
   /**
-   * Returns a reference to the {@code objectIdentifierFirstComponentMatch} Matching Rule
-   * which has the OID {@code 2.5.13.30}.
+   * Returns a reference to the {@code Numeric String Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.36}.
    *
-   * @return A reference to the {@code objectIdentifierFirstComponentMatch} Matching Rule.
+   * @return A reference to the {@code Numeric String Syntax}.
+   */
+  public static Syntax getNumericStringSyntax()
+  {
+    return NUMERIC_STRING_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code o} Attribute Type which has the OID
+   * {@code 2.5.4.10}.
+   *
+   * @return A reference to the {@code o} Attribute Type.
+   */
+  public static AttributeType getOAttributeType()
+  {
+    return O_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code objectClass} Attribute Type which has the
+   * OID {@code 2.5.4.0}.
+   *
+   * @return A reference to the {@code objectClass} Attribute Type.
+   */
+  public static AttributeType getObjectClassAttributeType()
+  {
+    return OBJECT_CLASS_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Object Class Description Syntax} which
+   * has the OID {@code 1.3.6.1.4.1.1466.115.121.1.37}.
+   *
+   * @return A reference to the {@code Object Class Description Syntax}.
+   */
+  public static Syntax getObjectClassDescriptionSyntax()
+  {
+    return OBJECT_CLASS_DESCRIPTION_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code objectClasses} Attribute Type which has
+   * the OID {@code 2.5.21.6}.
+   *
+   * @return A reference to the {@code objectClasses} Attribute Type.
+   */
+  public static AttributeType getObjectClassesAttributeType()
+  {
+    return OBJECT_CLASSES_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code objectIdentifierFirstComponentMatch}
+   * Matching Rule which has the OID {@code 2.5.13.30}.
+   *
+   * @return A reference to the {@code objectIdentifierFirstComponentMatch}
+   *         Matching Rule.
    */
   public static MatchingRule getObjectIdentifierFirstComponentMatchingRule()
   {
@@ -1341,8 +1779,8 @@
 
 
   /**
-   * Returns a reference to the {@code octetStringMatch} Matching Rule
-   * which has the OID {@code 2.5.13.17}.
+   * Returns a reference to the {@code octetStringMatch} Matching Rule which has
+   * the OID {@code 2.5.13.17}.
    *
    * @return A reference to the {@code octetStringMatch} Matching Rule.
    */
@@ -1370,7 +1808,8 @@
    * Returns a reference to the {@code octetStringSubstringsMatch} Matching Rule
    * which has the OID {@code 2.5.13.19}.
    *
-   * @return A reference to the {@code octetStringSubstringsMatch} Matching Rule.
+   * @return A reference to the {@code octetStringSubstringsMatch} Matching
+   *         Rule.
    */
   public static MatchingRule getOctetStringSubstringsMatchingRule()
   {
@@ -1380,593 +1819,99 @@
 
 
   /**
-   * Returns a reference to the {@code presentationAddressMatch} Matching Rule
-   * which has the OID {@code 2.5.13.22}.
+   * Returns a reference to the {@code Octet String Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.40}.
    *
-   * @return A reference to the {@code presentationAddressMatch} Matching Rule.
+   * @return A reference to the {@code Octet String Syntax}.
    */
-  public static MatchingRule getPresentationAddressMatchingRule()
+  public static Syntax getOctetStringSyntax()
   {
-    return PRESENTATION_ADDRESS_MATCHING_RULE;
+    return OCTET_STRING_SYNTAX;
   }
 
 
 
   /**
-   * Returns a reference to the {@code protocolInformationMatch} Matching Rule
-   * which has the OID {@code 2.5.13.24}.
+   * Returns a reference to the {@code OID Syntax} which has the OID {@code
+   * 1.3.6.1.4.1.1466.115.121.1.38}.
    *
-   * @return A reference to the {@code protocolInformationMatch} Matching Rule.
+   * @return A reference to the {@code OID Syntax}.
    */
-  public static MatchingRule getProtocolInformationMatchingRule()
+  public static Syntax getOIDSyntax()
   {
-    return PROTOCOL_INFORMATION_MATCHING_RULE;
+    return OID_SYNTAX;
   }
 
 
 
   /**
-   * Returns a reference to the {@code telephoneNumberMatch} Matching Rule
-   * which has the OID {@code 2.5.13.20}.
+   * Returns a reference to the {@code organizationalPerson} Object Class which
+   * has the OID {@code 2.5.6.7}.
    *
-   * @return A reference to the {@code telephoneNumberMatch} Matching Rule.
+   * @return A reference to the {@code organizationalPerson} Object Class.
    */
-  public static MatchingRule getTelephoneNumberMatchingRule()
+  public static ObjectClass getOrganizationalPersonObjectClass()
   {
-    return TELEPHONE_NUMBER_MATCHING_RULE;
+    return ORGANIZATIONAL_PERSON_OBJECT_CLASS;
   }
 
 
 
   /**
-   * Returns a reference to the {@code telephoneNumberSubstringsMatch} Matching Rule
-   * which has the OID {@code 2.5.13.21}.
+   * Returns a reference to the {@code organizationalRole} Object Class which
+   * has the OID {@code 2.5.6.8}.
    *
-   * @return A reference to the {@code telephoneNumberSubstringsMatch} Matching Rule.
+   * @return A reference to the {@code organizationalRole} Object Class.
    */
-  public static MatchingRule getTelephoneNumberSubstringsMatchingRule()
+  public static ObjectClass getOrganizationalRoleObjectClass()
   {
-    return TELEPHONE_NUMBER_SUBSTRINGS_MATCHING_RULE;
+    return ORGANIZATIONAL_ROLE_OBJECT_CLASS;
   }
 
 
 
   /**
-   * Returns a reference to the {@code uniqueMemberMatch} Matching Rule
-   * which has the OID {@code 2.5.13.23}.
+   * Returns a reference to the {@code organizationalUnit} Object Class which
+   * has the OID {@code 2.5.6.5}.
    *
-   * @return A reference to the {@code uniqueMemberMatch} Matching Rule.
+   * @return A reference to the {@code organizationalUnit} Object Class.
    */
-  public static MatchingRule getUniqueMemberMatchingRule()
+  public static ObjectClass getOrganizationalUnitObjectClass()
   {
-    return UNIQUE_MEMBER_MATCHING_RULE;
+    return ORGANIZATIONAL_UNIT_OBJECT_CLASS;
   }
 
 
 
   /**
-   * Returns a reference to the {@code uuidMatch} Matching Rule
-   * which has the OID {@code 1.3.6.1.1.16.2}.
+   * Returns a reference to the {@code organization} Object Class which has the
+   * OID {@code 2.5.6.4}.
    *
-   * @return A reference to the {@code uuidMatch} Matching Rule.
+   * @return A reference to the {@code organization} Object Class.
    */
-  public static MatchingRule getUUIDMatchingRule()
+  public static ObjectClass getOrganizationObjectClass()
   {
-    return UUID_MATCHING_RULE;
+    return ORGANIZATION_OBJECT_CLASS;
   }
 
 
 
   /**
-   * Returns a reference to the {@code uuidOrderingMatch} Matching Rule
-   * which has the OID {@code 1.3.6.1.1.16.3}.
+   * Returns a reference to the {@code Other Mailbox Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.39}.
    *
-   * @return A reference to the {@code uuidOrderingMatch} Matching Rule.
+   * @return A reference to the {@code Other Mailbox Syntax}.
    */
-  public static MatchingRule getUUIDOrderingMatchingRule()
+  public static Syntax getOtherMailboxSyntax()
   {
-    return UUID_ORDERING_MATCHING_RULE;
+    return OTHER_MAILBOX_SYNTAX;
   }
 
 
 
   /**
-   * Returns a reference to the {@code wordMatch} Matching Rule
-   * which has the OID {@code 2.5.13.32}.
-   *
-   * @return A reference to the {@code wordMatch} Matching Rule.
-   */
-  public static MatchingRule getWordMatchingRule()
-  {
-    return WORD_MATCHING_RULE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code aliasedObjectName} Attribute Type
-   * which has the OID {@code 2.5.4.1}.
-   *
-   * @return A reference to the {@code aliasedObjectName} Attribute Type.
-   */
-  public static AttributeType getAliasedObjectNameAttributeType()
-  {
-    return ALIASED_OBJECT_NAME_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code altServer} Attribute Type
-   * which has the OID {@code 1.3.6.1.4.1.1466.101.120.6}.
-   *
-   * @return A reference to the {@code altServer} Attribute Type.
-   */
-  public static AttributeType getAltServerAttributeType()
-  {
-    return ALT_SERVER_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code attributeTypes} Attribute Type
-   * which has the OID {@code 2.5.21.5}.
-   *
-   * @return A reference to the {@code attributeTypes} Attribute Type.
-   */
-  public static AttributeType getAttributeTypesAttributeType()
-  {
-    return ATTRIBUTE_TYPES_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code authPassword} Attribute Type
-   * which has the OID {@code 1.3.6.1.4.1.4203.1.3.4}.
-   *
-   * @return A reference to the {@code authPassword} Attribute Type.
-   */
-  public static AttributeType getAuthPasswordAttributeType()
-  {
-    return AUTH_PASSWORD_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code businessCategory} Attribute Type
-   * which has the OID {@code 2.5.4.15}.
-   *
-   * @return A reference to the {@code businessCategory} Attribute Type.
-   */
-  public static AttributeType getBusinessCategoryAttributeType()
-  {
-    return BUSINESS_CATEGORY_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code cn} Attribute Type
-   * which has the OID {@code 2.5.4.3}.
-   *
-   * @return A reference to the {@code cn} Attribute Type.
-   */
-  public static AttributeType getCNAttributeType()
-  {
-    return CN_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code createTimestamp} Attribute Type
-   * which has the OID {@code 2.5.18.1}.
-   *
-   * @return A reference to the {@code createTimestamp} Attribute Type.
-   */
-  public static AttributeType getCreateTimestampAttributeType()
-  {
-    return CREATE_TIMESTAMP_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code creatorsName} Attribute Type
-   * which has the OID {@code 2.5.18.3}.
-   *
-   * @return A reference to the {@code creatorsName} Attribute Type.
-   */
-  public static AttributeType getCreatorsNameAttributeType()
-  {
-    return CREATORS_NAME_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code c} Attribute Type
-   * which has the OID {@code 2.5.4.6}.
-   *
-   * @return A reference to the {@code c} Attribute Type.
-   */
-  public static AttributeType getCAttributeType()
-  {
-    return C_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code dc} Attribute Type
-   * which has the OID {@code 0.9.2342.19200300.100.1.25}.
-   *
-   * @return A reference to the {@code dc} Attribute Type.
-   */
-  public static AttributeType getDCAttributeType()
-  {
-    return DC_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code description} Attribute Type
-   * which has the OID {@code 2.5.4.13}.
-   *
-   * @return A reference to the {@code description} Attribute Type.
-   */
-  public static AttributeType getDescriptionAttributeType()
-  {
-    return DESCRIPTION_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code destinationIndicator} Attribute Type
-   * which has the OID {@code 2.5.4.27}.
-   *
-   * @return A reference to the {@code destinationIndicator} Attribute Type.
-   */
-  public static AttributeType getDestinationIndicatorAttributeType()
-  {
-    return DESTINATION_INDICATOR_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code distinguishedName} Attribute Type
-   * which has the OID {@code 2.5.4.49}.
-   *
-   * @return A reference to the {@code distinguishedName} Attribute Type.
-   */
-  public static AttributeType getDistinguishedNameAttributeType()
-  {
-    return DISTINGUISHED_NAME_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code ditContentRules} Attribute Type
-   * which has the OID {@code 2.5.21.2}.
-   *
-   * @return A reference to the {@code ditContentRules} Attribute Type.
-   */
-  public static AttributeType getDITContentRulesAttributeType()
-  {
-    return DIT_CONTENT_RULES_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code ditStructureRules} Attribute Type
-   * which has the OID {@code 2.5.21.1}.
-   *
-   * @return A reference to the {@code ditStructureRules} Attribute Type.
-   */
-  public static AttributeType getDITStructureRulesAttributeType()
-  {
-    return DIT_STRUCTURE_RULES_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code dnQualifier} Attribute Type
-   * which has the OID {@code 2.5.4.46}.
-   *
-   * @return A reference to the {@code dnQualifier} Attribute Type.
-   */
-  public static AttributeType getDNQualifierAttributeType()
-  {
-    return DN_QUALIFIER_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code enhancedSearchGuide} Attribute Type
-   * which has the OID {@code 2.5.4.47}.
-   *
-   * @return A reference to the {@code enhancedSearchGuide} Attribute Type.
-   */
-  public static AttributeType getEnhancedSearchGuideAttributeType()
-  {
-    return ENHANCED_SEARCH_GUIDE_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code entryUUID} Attribute Type
-   * which has the OID {@code 1.3.6.1.1.16.4}.
-   *
-   * @return A reference to the {@code entryUUID} Attribute Type.
-   */
-  public static AttributeType getEntryUUIDAttributeType()
-  {
-    return ENTRY_UUID_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code facsimileTelephoneNumber} Attribute Type
-   * which has the OID {@code 2.5.4.23}.
-   *
-   * @return A reference to the {@code facsimileTelephoneNumber} Attribute Type.
-   */
-  public static AttributeType getFacsimileTelephoneNumberAttributeType()
-  {
-    return FACSIMILE_TELEPHONE_NUMBER_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code generationQualifier} Attribute Type
-   * which has the OID {@code 2.5.4.44}.
-   *
-   * @return A reference to the {@code generationQualifier} Attribute Type.
-   */
-  public static AttributeType getGenerationQualifierAttributeType()
-  {
-    return GENERATION_QUALIFIER_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code givenName} Attribute Type
-   * which has the OID {@code 2.5.4.42}.
-   *
-   * @return A reference to the {@code givenName} Attribute Type.
-   */
-  public static AttributeType getGivenNameAttributeType()
-  {
-    return GIVEN_NAME_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code governingStructureRule} Attribute Type
-   * which has the OID {@code 2.5.21.10}.
-   *
-   * @return A reference to the {@code governingStructureRule} Attribute Type.
-   */
-  public static AttributeType getGoverningStructureRuleAttributeType()
-  {
-    return GOVERNING_STRUCTURE_RULE_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code houseIdentifier} Attribute Type
-   * which has the OID {@code 2.5.4.51}.
-   *
-   * @return A reference to the {@code houseIdentifier} Attribute Type.
-   */
-  public static AttributeType getHouseIdentifierAttributeType()
-  {
-    return HOUSE_IDENTIFIER_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code initials} Attribute Type
-   * which has the OID {@code 2.5.4.43}.
-   *
-   * @return A reference to the {@code initials} Attribute Type.
-   */
-  public static AttributeType getInitialsAttributeType()
-  {
-    return INITIALS_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code internationalISDNNumber} Attribute Type
-   * which has the OID {@code 2.5.4.25}.
-   *
-   * @return A reference to the {@code internationalISDNNumber} Attribute Type.
-   */
-  public static AttributeType getInternationalISDNNumberAttributeType()
-  {
-    return INTERNATIONAL_ISDN_NUMBER_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code ldapSyntaxes} Attribute Type
-   * which has the OID {@code 1.3.6.1.4.1.1466.101.120.16}.
-   *
-   * @return A reference to the {@code ldapSyntaxes} Attribute Type.
-   */
-  public static AttributeType getLDAPSyntaxesAttributeType()
-  {
-    return LDAP_SYNTAXES_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code l} Attribute Type
-   * which has the OID {@code 2.5.4.7}.
-   *
-   * @return A reference to the {@code l} Attribute Type.
-   */
-  public static AttributeType getLAttributeType()
-  {
-    return L_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code matchingRules} Attribute Type
-   * which has the OID {@code 2.5.21.4}.
-   *
-   * @return A reference to the {@code matchingRules} Attribute Type.
-   */
-  public static AttributeType getMatchingRulesAttributeType()
-  {
-    return MATCHING_RULES_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code matchingRuleUse} Attribute Type
-   * which has the OID {@code 2.5.21.8}.
-   *
-   * @return A reference to the {@code matchingRuleUse} Attribute Type.
-   */
-  public static AttributeType getMatchingRuleUseAttributeType()
-  {
-    return MATCHING_RULE_USE_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code member} Attribute Type
-   * which has the OID {@code 2.5.4.31}.
-   *
-   * @return A reference to the {@code member} Attribute Type.
-   */
-  public static AttributeType getMemberAttributeType()
-  {
-    return MEMBER_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code modifiersName} Attribute Type
-   * which has the OID {@code 2.5.18.4}.
-   *
-   * @return A reference to the {@code modifiersName} Attribute Type.
-   */
-  public static AttributeType getModifiersNameAttributeType()
-  {
-    return MODIFIERS_NAME_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code modifyTimestamp} Attribute Type
-   * which has the OID {@code 2.5.18.2}.
-   *
-   * @return A reference to the {@code modifyTimestamp} Attribute Type.
-   */
-  public static AttributeType getModifyTimestampAttributeType()
-  {
-    return MODIFY_TIMESTAMP_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code name} Attribute Type
-   * which has the OID {@code 2.5.4.41}.
-   *
-   * @return A reference to the {@code name} Attribute Type.
-   */
-  public static AttributeType getNameAttributeType()
-  {
-    return NAME_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code nameForms} Attribute Type
-   * which has the OID {@code 2.5.21.7}.
-   *
-   * @return A reference to the {@code nameForms} Attribute Type.
-   */
-  public static AttributeType getNameFormsAttributeType()
-  {
-    return NAME_FORMS_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code namingContexts} Attribute Type
-   * which has the OID {@code 1.3.6.1.4.1.1466.101.120.5}.
-   *
-   * @return A reference to the {@code namingContexts} Attribute Type.
-   */
-  public static AttributeType getNamingContextsAttributeType()
-  {
-    return NAMING_CONTEXTS_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code objectClasses} Attribute Type
-   * which has the OID {@code 2.5.21.6}.
-   *
-   * @return A reference to the {@code objectClasses} Attribute Type.
-   */
-  public static AttributeType getObjectClassesAttributeType()
-  {
-    return OBJECT_CLASSES_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code objectClass} Attribute Type
-   * which has the OID {@code 2.5.4.0}.
-   *
-   * @return A reference to the {@code objectClass} Attribute Type.
-   */
-  public static AttributeType getObjectClassAttributeType()
-  {
-    return OBJECT_CLASS_ATTRIBUTE_TYPE;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code ou} Attribute Type
-   * which has the OID {@code 2.5.4.11}.
+   * Returns a reference to the {@code ou} Attribute Type which has the OID
+   * {@code 2.5.4.11}.
    *
    * @return A reference to the {@code ou} Attribute Type.
    */
@@ -1978,8 +1923,8 @@
 
 
   /**
-   * Returns a reference to the {@code owner} Attribute Type
-   * which has the OID {@code 2.5.4.32}.
+   * Returns a reference to the {@code owner} Attribute Type which has the OID
+   * {@code 2.5.4.32}.
    *
    * @return A reference to the {@code owner} Attribute Type.
    */
@@ -1991,23 +1936,24 @@
 
 
   /**
-   * Returns a reference to the {@code o} Attribute Type
-   * which has the OID {@code 2.5.4.10}.
+   * Returns a reference to the {@code person} Object Class which has the OID
+   * {@code 2.5.6.6}.
    *
-   * @return A reference to the {@code o} Attribute Type.
+   * @return A reference to the {@code person} Object Class.
    */
-  public static AttributeType getOAttributeType()
+  public static ObjectClass getPersonObjectClass()
   {
-    return O_ATTRIBUTE_TYPE;
+    return PERSON_OBJECT_CLASS;
   }
 
 
 
   /**
-   * Returns a reference to the {@code physicalDeliveryOfficeName} Attribute Type
-   * which has the OID {@code 2.5.4.19}.
+   * Returns a reference to the {@code physicalDeliveryOfficeName} Attribute
+   * Type which has the OID {@code 2.5.4.19}.
    *
-   * @return A reference to the {@code physicalDeliveryOfficeName} Attribute Type.
+   * @return A reference to the {@code physicalDeliveryOfficeName} Attribute
+   *         Type.
    */
   public static AttributeType getPhysicalDeliveryOfficeNameAttributeType()
   {
@@ -2017,8 +1963,8 @@
 
 
   /**
-   * Returns a reference to the {@code postalAddress} Attribute Type
-   * which has the OID {@code 2.5.4.16}.
+   * Returns a reference to the {@code postalAddress} Attribute Type which has
+   * the OID {@code 2.5.4.16}.
    *
    * @return A reference to the {@code postalAddress} Attribute Type.
    */
@@ -2030,8 +1976,21 @@
 
 
   /**
-   * Returns a reference to the {@code postalCode} Attribute Type
-   * which has the OID {@code 2.5.4.17}.
+   * Returns a reference to the {@code Postal Address Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.41}.
+   *
+   * @return A reference to the {@code Postal Address Syntax}.
+   */
+  public static Syntax getPostalAddressSyntax()
+  {
+    return POSTAL_ADDRESS_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code postalCode} Attribute Type which has the
+   * OID {@code 2.5.4.17}.
    *
    * @return A reference to the {@code postalCode} Attribute Type.
    */
@@ -2043,8 +2002,8 @@
 
 
   /**
-   * Returns a reference to the {@code postOfficeBox} Attribute Type
-   * which has the OID {@code 2.5.4.18}.
+   * Returns a reference to the {@code postOfficeBox} Attribute Type which has
+   * the OID {@code 2.5.4.18}.
    *
    * @return A reference to the {@code postOfficeBox} Attribute Type.
    */
@@ -2069,8 +2028,73 @@
 
 
   /**
-   * Returns a reference to the {@code registeredAddress} Attribute Type
-   * which has the OID {@code 2.5.4.26}.
+   * Returns a reference to the {@code presentationAddressMatch} Matching Rule
+   * which has the OID {@code 2.5.13.22}.
+   *
+   * @return A reference to the {@code presentationAddressMatch} Matching Rule.
+   */
+  public static MatchingRule getPresentationAddressMatchingRule()
+  {
+    return PRESENTATION_ADDRESS_MATCHING_RULE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Presentation Address Syntax} which has
+   * the OID {@code 1.3.6.1.4.1.1466.115.121.1.43}.
+   *
+   * @return A reference to the {@code Presentation Address Syntax}.
+   */
+  public static Syntax getPresentationAddressSyntax()
+  {
+    return PRESENTATION_ADDRESS_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Printable String Syntax} which has the
+   * OID {@code 1.3.6.1.4.1.1466.115.121.1.44}.
+   *
+   * @return A reference to the {@code Printable String Syntax}.
+   */
+  public static Syntax getPrintableStringSyntax()
+  {
+    return PRINTABLE_STRING_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code protocolInformationMatch} Matching Rule
+   * which has the OID {@code 2.5.13.24}.
+   *
+   * @return A reference to the {@code protocolInformationMatch} Matching Rule.
+   */
+  public static MatchingRule getProtocolInformationMatchingRule()
+  {
+    return PROTOCOL_INFORMATION_MATCHING_RULE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Protocol Information Syntax} which has
+   * the OID {@code 1.3.6.1.4.1.1466.115.121.1.42}.
+   *
+   * @return A reference to the {@code Protocol Information Syntax}.
+   */
+  public static Syntax getProtocolInformationSyntax()
+  {
+    return PROTOCOL_INFORMATION_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code registeredAddress} Attribute Type which
+   * has the OID {@code 2.5.4.26}.
    *
    * @return A reference to the {@code registeredAddress} Attribute Type.
    */
@@ -2082,8 +2106,21 @@
 
 
   /**
-   * Returns a reference to the {@code roleOccupant} Attribute Type
-   * which has the OID {@code 2.5.4.33}.
+   * Returns a reference to the {@code residentialPerson} Object Class which has
+   * the OID {@code 2.5.6.10}.
+   *
+   * @return A reference to the {@code residentialPerson} Object Class.
+   */
+  public static ObjectClass getResidentialPersonObjectClass()
+  {
+    return RESIDENTIAL_PERSON_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code roleOccupant} Attribute Type which has
+   * the OID {@code 2.5.4.33}.
    *
    * @return A reference to the {@code roleOccupant} Attribute Type.
    */
@@ -2095,8 +2132,8 @@
 
 
   /**
-   * Returns a reference to the {@code searchGuide} Attribute Type
-   * which has the OID {@code 2.5.4.14}.
+   * Returns a reference to the {@code searchGuide} Attribute Type which has the
+   * OID {@code 2.5.4.14}.
    *
    * @return A reference to the {@code searchGuide} Attribute Type.
    */
@@ -2108,8 +2145,8 @@
 
 
   /**
-   * Returns a reference to the {@code seeAlso} Attribute Type
-   * which has the OID {@code 2.5.4.34}.
+   * Returns a reference to the {@code seeAlso} Attribute Type which has the OID
+   * {@code 2.5.4.34}.
    *
    * @return A reference to the {@code seeAlso} Attribute Type.
    */
@@ -2121,8 +2158,8 @@
 
 
   /**
-   * Returns a reference to the {@code serialNumber} Attribute Type
-   * which has the OID {@code 2.5.4.5}.
+   * Returns a reference to the {@code serialNumber} Attribute Type which has
+   * the OID {@code 2.5.4.5}.
    *
    * @return A reference to the {@code serialNumber} Attribute Type.
    */
@@ -2134,8 +2171,8 @@
 
 
   /**
-   * Returns a reference to the {@code sn} Attribute Type
-   * which has the OID {@code 2.5.4.4}.
+   * Returns a reference to the {@code sn} Attribute Type which has the OID
+   * {@code 2.5.4.4}.
    *
    * @return A reference to the {@code sn} Attribute Type.
    */
@@ -2147,8 +2184,21 @@
 
 
   /**
-   * Returns a reference to the {@code street} Attribute Type
-   * which has the OID {@code 2.5.4.9}.
+   * Returns a reference to the {@code st} Attribute Type which has the OID
+   * {@code 2.5.4.8}.
+   *
+   * @return A reference to the {@code st} Attribute Type.
+   */
+  public static AttributeType getSTAttributeType()
+  {
+    return ST_ATTRIBUTE_TYPE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code street} Attribute Type which has the OID
+   * {@code 2.5.4.9}.
    *
    * @return A reference to the {@code street} Attribute Type.
    */
@@ -2173,21 +2223,21 @@
 
 
   /**
-   * Returns a reference to the {@code st} Attribute Type
-   * which has the OID {@code 2.5.4.8}.
+   * Returns a reference to the {@code subschema} Object Class which has the OID
+   * {@code 2.5.20.1}.
    *
-   * @return A reference to the {@code st} Attribute Type.
+   * @return A reference to the {@code subschema} Object Class.
    */
-  public static AttributeType getSTAttributeType()
+  public static ObjectClass getSubschemaObjectClass()
   {
-    return ST_ATTRIBUTE_TYPE;
+    return SUBSCHEMA_OBJECT_CLASS;
   }
 
 
 
   /**
-   * Returns a reference to the {@code subschemaSubentry} Attribute Type
-   * which has the OID {@code 2.5.18.10}.
+   * Returns a reference to the {@code subschemaSubentry} Attribute Type which
+   * has the OID {@code 2.5.18.10}.
    *
    * @return A reference to the {@code subschemaSubentry} Attribute Type.
    */
@@ -2199,10 +2249,37 @@
 
 
   /**
-   * Returns a reference to the {@code supportedAuthPasswordSchemes} Attribute Type
-   * which has the OID {@code 1.3.6.1.4.1.4203.1.3.3}.
+   * Returns a reference to the {@code Substring Assertion Syntax} which has the
+   * OID {@code 1.3.6.1.4.1.1466.115.121.1.58}.
    *
-   * @return A reference to the {@code supportedAuthPasswordSchemes} Attribute Type.
+   * @return A reference to the {@code Substring Assertion Syntax}.
+   */
+  public static Syntax getSubstringAssertionSyntax()
+  {
+    return SUBSTRING_ASSERTION_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Supported Algorithm Syntax} which has the
+   * OID {@code 1.3.6.1.4.1.1466.115.121.1.49}.
+   *
+   * @return A reference to the {@code Supported Algorithm Syntax}.
+   */
+  public static Syntax getSupportedAlgorithmSyntax()
+  {
+    return SUPPORTED_ALGORITHM_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code supportedAuthPasswordSchemes} Attribute
+   * Type which has the OID {@code 1.3.6.1.4.1.4203.1.3.3}.
+   *
+   * @return A reference to the {@code supportedAuthPasswordSchemes} Attribute
+   *         Type.
    */
   public static AttributeType getSupportedAuthPasswordSchemesAttributeType()
   {
@@ -2212,8 +2289,8 @@
 
 
   /**
-   * Returns a reference to the {@code supportedControl} Attribute Type
-   * which has the OID {@code 1.3.6.1.4.1.1466.101.120.13}.
+   * Returns a reference to the {@code supportedControl} Attribute Type which
+   * has the OID {@code 1.3.6.1.4.1.1466.101.120.13}.
    *
    * @return A reference to the {@code supportedControl} Attribute Type.
    */
@@ -2225,8 +2302,8 @@
 
 
   /**
-   * Returns a reference to the {@code supportedExtension} Attribute Type
-   * which has the OID {@code 1.3.6.1.4.1.1466.101.120.7}.
+   * Returns a reference to the {@code supportedExtension} Attribute Type which
+   * has the OID {@code 1.3.6.1.4.1.1466.101.120.7}.
    *
    * @return A reference to the {@code supportedExtension} Attribute Type.
    */
@@ -2238,8 +2315,8 @@
 
 
   /**
-   * Returns a reference to the {@code supportedFeatures} Attribute Type
-   * which has the OID {@code 1.3.6.1.4.1.4203.1.3.5}.
+   * Returns a reference to the {@code supportedFeatures} Attribute Type which
+   * has the OID {@code 1.3.6.1.4.1.4203.1.3.5}.
    *
    * @return A reference to the {@code supportedFeatures} Attribute Type.
    */
@@ -2277,8 +2354,8 @@
 
 
   /**
-   * Returns a reference to the {@code telephoneNumber} Attribute Type
-   * which has the OID {@code 2.5.4.20}.
+   * Returns a reference to the {@code telephoneNumber} Attribute Type which has
+   * the OID {@code 2.5.4.20}.
    *
    * @return A reference to the {@code telephoneNumber} Attribute Type.
    */
@@ -2290,10 +2367,51 @@
 
 
   /**
+   * Returns a reference to the {@code telephoneNumberMatch} Matching Rule which
+   * has the OID {@code 2.5.13.20}.
+   *
+   * @return A reference to the {@code telephoneNumberMatch} Matching Rule.
+   */
+  public static MatchingRule getTelephoneNumberMatchingRule()
+  {
+    return TELEPHONE_NUMBER_MATCHING_RULE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code telephoneNumberSubstringsMatch} Matching
+   * Rule which has the OID {@code 2.5.13.21}.
+   *
+   * @return A reference to the {@code telephoneNumberSubstringsMatch} Matching
+   *         Rule.
+   */
+  public static MatchingRule getTelephoneNumberSubstringsMatchingRule()
+  {
+    return TELEPHONE_NUMBER_SUBSTRINGS_MATCHING_RULE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code Telephone Number Syntax} which has the
+   * OID {@code 1.3.6.1.4.1.1466.115.121.1.50}.
+   *
+   * @return A reference to the {@code Telephone Number Syntax}.
+   */
+  public static Syntax getTelephoneNumberSyntax()
+  {
+    return TELEPHONE_NUMBER_SYNTAX;
+  }
+
+
+
+  /**
    * Returns a reference to the {@code teletexTerminalIdentifier} Attribute Type
    * which has the OID {@code 2.5.4.22}.
    *
-   * @return A reference to the {@code teletexTerminalIdentifier} Attribute Type.
+   * @return A reference to the {@code teletexTerminalIdentifier} Attribute
+   *         Type.
    */
   public static AttributeType getTeletexTerminalIdentifierAttributeType()
   {
@@ -2303,8 +2421,21 @@
 
 
   /**
-   * Returns a reference to the {@code telexNumber} Attribute Type
-   * which has the OID {@code 2.5.4.21}.
+   * Returns a reference to the {@code Teletex Terminal Identifier Syntax} which
+   * has the OID {@code 1.3.6.1.4.1.1466.115.121.1.51}.
+   *
+   * @return A reference to the {@code Teletex Terminal Identifier Syntax}.
+   */
+  public static Syntax getTeletexTerminalIdentifierSyntax()
+  {
+    return TELETEX_TERMINAL_IDENTIFIER_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code telexNumber} Attribute Type which has the
+   * OID {@code 2.5.4.21}.
    *
    * @return A reference to the {@code telexNumber} Attribute Type.
    */
@@ -2316,8 +2447,21 @@
 
 
   /**
-   * Returns a reference to the {@code title} Attribute Type
-   * which has the OID {@code 2.5.4.12}.
+   * Returns a reference to the {@code Telex Number Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.52}.
+   *
+   * @return A reference to the {@code Telex Number Syntax}.
+   */
+  public static Syntax getTelexNumberSyntax()
+  {
+    return TELEX_NUMBER_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code title} Attribute Type which has the OID
+   * {@code 2.5.4.12}.
    *
    * @return A reference to the {@code title} Attribute Type.
    */
@@ -2329,8 +2473,21 @@
 
 
   /**
-   * Returns a reference to the {@code uid} Attribute Type
-   * which has the OID {@code 0.9.2342.19200300.100.1.1}.
+   * Returns a reference to the {@code top} Object Class which has the OID
+   * {@code 2.5.6.0}.
+   *
+   * @return A reference to the {@code top} Object Class.
+   */
+  public static ObjectClass getTopObjectClass()
+  {
+    return TOP_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code uid} Attribute Type which has the OID
+   * {@code 0.9.2342.19200300.100.1.1}.
    *
    * @return A reference to the {@code uid} Attribute Type.
    */
@@ -2342,8 +2499,21 @@
 
 
   /**
-   * Returns a reference to the {@code uniqueMember} Attribute Type
-   * which has the OID {@code 2.5.4.50}.
+   * Returns a reference to the {@code uidObject} Object Class which has the OID
+   * {@code 1.3.6.1.1.3.1}.
+   *
+   * @return A reference to the {@code uidObject} Object Class.
+   */
+  public static ObjectClass getUIDObjectObjectClass()
+  {
+    return UID_OBJECT_OBJECT_CLASS;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code uniqueMember} Attribute Type which has
+   * the OID {@code 2.5.4.50}.
    *
    * @return A reference to the {@code uniqueMember} Attribute Type.
    */
@@ -2355,8 +2525,21 @@
 
 
   /**
-   * Returns a reference to the {@code userPassword} Attribute Type
-   * which has the OID {@code 2.5.4.35}.
+   * Returns a reference to the {@code uniqueMemberMatch} Matching Rule which
+   * has the OID {@code 2.5.13.23}.
+   *
+   * @return A reference to the {@code uniqueMemberMatch} Matching Rule.
+   */
+  public static MatchingRule getUniqueMemberMatchingRule()
+  {
+    return UNIQUE_MEMBER_MATCHING_RULE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code userPassword} Attribute Type which has
+   * the OID {@code 2.5.4.35}.
    *
    * @return A reference to the {@code userPassword} Attribute Type.
    */
@@ -2368,8 +2551,60 @@
 
 
   /**
-   * Returns a reference to the {@code vendorName} Attribute Type
-   * which has the OID {@code 1.3.6.1.1.4}.
+   * Returns a reference to the {@code UTC Time Syntax} which has the OID
+   * {@code 1.3.6.1.4.1.1466.115.121.1.53}.
+   *
+   * @return A reference to the {@code UTC Time Syntax}.
+   */
+  public static Syntax getUTCTimeSyntax()
+  {
+    return UTC_TIME_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code uuidMatch} Matching Rule which has the
+   * OID {@code 1.3.6.1.1.16.2}.
+   *
+   * @return A reference to the {@code uuidMatch} Matching Rule.
+   */
+  public static MatchingRule getUUIDMatchingRule()
+  {
+    return UUID_MATCHING_RULE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code uuidOrderingMatch} Matching Rule which
+   * has the OID {@code 1.3.6.1.1.16.3}.
+   *
+   * @return A reference to the {@code uuidOrderingMatch} Matching Rule.
+   */
+  public static MatchingRule getUUIDOrderingMatchingRule()
+  {
+    return UUID_ORDERING_MATCHING_RULE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code UUID Syntax} which has the OID {@code
+   * 1.3.6.1.1.16.1}.
+   *
+   * @return A reference to the {@code UUID Syntax}.
+   */
+  public static Syntax getUUIDSyntax()
+  {
+    return UUID_SYNTAX;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code vendorName} Attribute Type which has the
+   * OID {@code 1.3.6.1.1.4}.
    *
    * @return A reference to the {@code vendorName} Attribute Type.
    */
@@ -2381,8 +2616,8 @@
 
 
   /**
-   * Returns a reference to the {@code vendorVersion} Attribute Type
-   * which has the OID {@code 1.3.6.1.1.5}.
+   * Returns a reference to the {@code vendorVersion} Attribute Type which has
+   * the OID {@code 1.3.6.1.1.5}.
    *
    * @return A reference to the {@code vendorVersion} Attribute Type.
    */
@@ -2394,8 +2629,21 @@
 
 
   /**
-   * Returns a reference to the {@code x121Address} Attribute Type
-   * which has the OID {@code 2.5.4.24}.
+   * Returns a reference to the {@code wordMatch} Matching Rule which has the
+   * OID {@code 2.5.13.32}.
+   *
+   * @return A reference to the {@code wordMatch} Matching Rule.
+   */
+  public static MatchingRule getWordMatchingRule()
+  {
+    return WORD_MATCHING_RULE;
+  }
+
+
+
+  /**
+   * Returns a reference to the {@code x121Address} Attribute Type which has the
+   * OID {@code 2.5.4.24}.
    *
    * @return A reference to the {@code x121Address} Attribute Type.
    */
@@ -2419,248 +2667,9 @@
 
 
 
-  /**
-   * Returns a reference to the {@code alias} Object Class
-   * which has the OID {@code 2.5.6.1}.
-   *
-   * @return A reference to the {@code alias} Object Class.
-   */
-  public static ObjectClass getAliasObjectClass()
+  // Prevent instantiation
+  private CoreSchema()
   {
-    return ALIAS_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code applicationProcess} Object Class
-   * which has the OID {@code 2.5.6.11}.
-   *
-   * @return A reference to the {@code applicationProcess} Object Class.
-   */
-  public static ObjectClass getApplicationProcessObjectClass()
-  {
-    return APPLICATION_PROCESS_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code authPasswordObject} Object Class
-   * which has the OID {@code 1.3.6.1.4.1.4203.1.4.7}.
-   *
-   * @return A reference to the {@code authPasswordObject} Object Class.
-   */
-  public static ObjectClass getAuthPasswordObjectObjectClass()
-  {
-    return AUTH_PASSWORD_OBJECT_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code country} Object Class
-   * which has the OID {@code 2.5.6.2}.
-   *
-   * @return A reference to the {@code country} Object Class.
-   */
-  public static ObjectClass getCountryObjectClass()
-  {
-    return COUNTRY_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code dcObject} Object Class
-   * which has the OID {@code 1.3.6.1.4.1.1466.344}.
-   *
-   * @return A reference to the {@code dcObject} Object Class.
-   */
-  public static ObjectClass getDCObjectObjectClass()
-  {
-    return DC_OBJECT_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code device} Object Class
-   * which has the OID {@code 2.5.6.14}.
-   *
-   * @return A reference to the {@code device} Object Class.
-   */
-  public static ObjectClass getDeviceObjectClass()
-  {
-    return DEVICE_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code extensibleObject} Object Class
-   * which has the OID {@code 1.3.6.1.4.1.1466.101.120.111}.
-   *
-   * @return A reference to the {@code extensibleObject} Object Class.
-   */
-  public static ObjectClass getExtensibleObjectObjectClass()
-  {
-    return EXTENSIBLE_OBJECT_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code groupOfNames} Object Class
-   * which has the OID {@code 2.5.6.9}.
-   *
-   * @return A reference to the {@code groupOfNames} Object Class.
-   */
-  public static ObjectClass getGroupOfNamesObjectClass()
-  {
-    return GROUP_OF_NAMES_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code groupOfUniqueNames} Object Class
-   * which has the OID {@code 2.5.6.17}.
-   *
-   * @return A reference to the {@code groupOfUniqueNames} Object Class.
-   */
-  public static ObjectClass getGroupOfUniqueNamesObjectClass()
-  {
-    return GROUP_OF_UNIQUE_NAMES_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code locality} Object Class
-   * which has the OID {@code 2.5.6.3}.
-   *
-   * @return A reference to the {@code locality} Object Class.
-   */
-  public static ObjectClass getLocalityObjectClass()
-  {
-    return LOCALITY_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code organizationalPerson} Object Class
-   * which has the OID {@code 2.5.6.7}.
-   *
-   * @return A reference to the {@code organizationalPerson} Object Class.
-   */
-  public static ObjectClass getOrganizationalPersonObjectClass()
-  {
-    return ORGANIZATIONAL_PERSON_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code organizationalRole} Object Class
-   * which has the OID {@code 2.5.6.8}.
-   *
-   * @return A reference to the {@code organizationalRole} Object Class.
-   */
-  public static ObjectClass getOrganizationalRoleObjectClass()
-  {
-    return ORGANIZATIONAL_ROLE_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code organizationalUnit} Object Class
-   * which has the OID {@code 2.5.6.5}.
-   *
-   * @return A reference to the {@code organizationalUnit} Object Class.
-   */
-  public static ObjectClass getOrganizationalUnitObjectClass()
-  {
-    return ORGANIZATIONAL_UNIT_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code organization} Object Class
-   * which has the OID {@code 2.5.6.4}.
-   *
-   * @return A reference to the {@code organization} Object Class.
-   */
-  public static ObjectClass getOrganizationObjectClass()
-  {
-    return ORGANIZATION_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code person} Object Class
-   * which has the OID {@code 2.5.6.6}.
-   *
-   * @return A reference to the {@code person} Object Class.
-   */
-  public static ObjectClass getPersonObjectClass()
-  {
-    return PERSON_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code residentialPerson} Object Class
-   * which has the OID {@code 2.5.6.10}.
-   *
-   * @return A reference to the {@code residentialPerson} Object Class.
-   */
-  public static ObjectClass getResidentialPersonObjectClass()
-  {
-    return RESIDENTIAL_PERSON_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code subschema} Object Class
-   * which has the OID {@code 2.5.20.1}.
-   *
-   * @return A reference to the {@code subschema} Object Class.
-   */
-  public static ObjectClass getSubschemaObjectClass()
-  {
-    return SUBSCHEMA_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code top} Object Class
-   * which has the OID {@code 2.5.6.0}.
-   *
-   * @return A reference to the {@code top} Object Class.
-   */
-  public static ObjectClass getTopObjectClass()
-  {
-    return TOP_OBJECT_CLASS;
-  }
-
-
-
-  /**
-   * Returns a reference to the {@code uidObject} Object Class
-   * which has the OID {@code 1.3.6.1.1.3.1}.
-   *
-   * @return A reference to the {@code uidObject} Object Class.
-   */
-  public static ObjectClass getUIDObjectObjectClass()
-  {
-    return UID_OBJECT_OBJECT_CLASS;
+    // Nothing to do.
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/CoreSchemaImpl.java b/sdk/src/org/opends/sdk/schema/CoreSchemaImpl.java
index 8f39528..775be20 100644
--- a/sdk/src/org/opends/sdk/schema/CoreSchemaImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CoreSchemaImpl.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 package org.opends.sdk.schema;
 
@@ -37,8 +37,7 @@
 final class CoreSchemaImpl
 {
   private static final Map<String, List<String>> X500_ORIGIN = Collections
-      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
-          .singletonList("X.500"));
+      .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections.singletonList("X.500"));
 
   private static final Map<String, List<String>> RFC2252_ORIGIN = Collections
       .singletonMap(SCHEMA_PROPERTY_ORIGIN, Collections
@@ -74,8 +73,7 @@
 
   private static final String EMPTY_STRING = "".intern();
 
-  private static final Set<String> EMPTY_STRING_SET = Collections
-      .emptySet();
+  private static final Set<String> EMPTY_STRING_SET = Collections.emptySet();
 
   private static final Schema SINGLETON;
 
@@ -105,56 +103,50 @@
 
 
 
-  private static void addRFC3045(SchemaBuilder builder)
+  private static void addRFC3045(final SchemaBuilder builder)
   {
     builder.addAttributeType("1.3.6.1.1.4", Collections
         .singletonList("vendorName"), EMPTY_STRING, false, null,
-        EMR_CASE_EXACT_IA5_OID, null, null, null,
-        SYNTAX_DIRECTORY_STRING_OID, true, false, true,
-        AttributeUsage.DSA_OPERATION, RFC3045_ORIGIN, false);
+        EMR_CASE_EXACT_IA5_OID, null, null, null, SYNTAX_DIRECTORY_STRING_OID,
+        true, false, true, AttributeUsage.DSA_OPERATION, RFC3045_ORIGIN, false);
 
     builder.addAttributeType("1.3.6.1.1.5", Collections
         .singletonList("vendorVersion"), EMPTY_STRING, false, null,
-        EMR_CASE_EXACT_IA5_OID, null, null, null,
-        SYNTAX_DIRECTORY_STRING_OID, true, false, true,
-        AttributeUsage.DSA_OPERATION, RFC3045_ORIGIN, false);
+        EMR_CASE_EXACT_IA5_OID, null, null, null, SYNTAX_DIRECTORY_STRING_OID,
+        true, false, true, AttributeUsage.DSA_OPERATION, RFC3045_ORIGIN, false);
   }
 
 
 
-  private static void addRFC3112(SchemaBuilder builder)
+  private static void addRFC3112(final SchemaBuilder builder)
   {
     builder.addSyntax(SYNTAX_AUTH_PASSWORD_OID,
         SYNTAX_AUTH_PASSWORD_DESCRIPTION, RFC3112_ORIGIN,
         new AuthPasswordSyntaxImpl(), false);
     builder.addMatchingRule(EMR_AUTH_PASSWORD_EXACT_OID, Collections
         .singletonList(EMR_AUTH_PASSWORD_EXACT_NAME),
-        EMR_AUTH_PASSWORD_EXACT_DESCRIPTION, false,
-        SYNTAX_AUTH_PASSWORD_OID, RFC3112_ORIGIN,
-        new AuthPasswordExactEqualityMatchingRuleImpl(), false);
+        EMR_AUTH_PASSWORD_EXACT_DESCRIPTION, false, SYNTAX_AUTH_PASSWORD_OID,
+        RFC3112_ORIGIN, new AuthPasswordExactEqualityMatchingRuleImpl(), false);
     builder.addAttributeType("1.3.6.1.4.1.4203.1.3.3", Collections
         .singletonList("supportedAuthPasswordSchemes"),
         "supported password storage schemes", false, null,
-        EMR_CASE_EXACT_IA5_OID, null, null, null,
-        SYNTAX_IA5_STRING_OID, false, false, false,
-        AttributeUsage.DSA_OPERATION, RFC3112_ORIGIN, false);
+        EMR_CASE_EXACT_IA5_OID, null, null, null, SYNTAX_IA5_STRING_OID, false,
+        false, false, AttributeUsage.DSA_OPERATION, RFC3112_ORIGIN, false);
     builder.addAttributeType("1.3.6.1.4.1.4203.1.3.4", Collections
-        .singletonList("authPassword"),
-        "password authentication information", false, null,
-        EMR_AUTH_PASSWORD_EXACT_OID, null, null, null,
+        .singletonList("authPassword"), "password authentication information",
+        false, null, EMR_AUTH_PASSWORD_EXACT_OID, null, null, null,
         SYNTAX_AUTH_PASSWORD_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC3112_ORIGIN, false);
     builder.addObjectClass("1.3.6.1.4.1.4203.1.4.7", Collections
         .singletonList("authPasswordObject"),
-        "authentication password mix in class", false,
-        EMPTY_STRING_SET, EMPTY_STRING_SET, Collections
-            .singleton("authPassword"), ObjectClassType.AUXILIARY,
-        RFC3112_ORIGIN, false);
+        "authentication password mix in class", false, EMPTY_STRING_SET,
+        EMPTY_STRING_SET, Collections.singleton("authPassword"),
+        ObjectClassType.AUXILIARY, RFC3112_ORIGIN, false);
   }
 
 
 
-  private static void addRFC4519(SchemaBuilder builder)
+  private static void addRFC4519(final SchemaBuilder builder)
   {
     builder.addAttributeType("2.5.4.15", Collections
         .singletonList("businessCategory"), EMPTY_STRING, false, null,
@@ -162,21 +154,24 @@
         SYNTAX_DIRECTORY_STRING_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("2.5.4.6", Arrays.asList("c",
-        "countryName"), EMPTY_STRING, false, "name", null, null, null,
-        null, SYNTAX_COUNTRY_STRING_OID, true, false, false,
+    builder.addAttributeType("2.5.4.41", Collections.singletonList("name"),
+        EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null,
+        SMR_CASE_IGNORE_OID, null, SYNTAX_DIRECTORY_STRING_OID, false, false,
+        false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+
+    builder.addAttributeType("2.5.4.6", Arrays.asList("c", "countryName"),
+        EMPTY_STRING, false, "name", null, null, null, null,
+        SYNTAX_COUNTRY_STRING_OID, true, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("2.5.4.3", Arrays.asList("cn",
-        "commonName"), EMPTY_STRING, false, "name", null, null, null,
-        null, null, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+    builder.addAttributeType("2.5.4.3", Arrays.asList("cn", "commonName"),
+        EMPTY_STRING, false, "name", null, null, null, null, null, false,
+        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("0.9.2342.19200300.100.1.25", Arrays
-        .asList("dc", "domainComponent"), EMPTY_STRING, false, null,
-        EMR_CASE_IGNORE_IA5_OID, null, SMR_CASE_IGNORE_IA5_OID, null,
-        SYNTAX_IA5_STRING_OID, true, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+    builder.addAttributeType("0.9.2342.19200300.100.1.25", Arrays.asList("dc",
+        "domainComponent"), EMPTY_STRING, false, null, EMR_CASE_IGNORE_IA5_OID,
+        null, SMR_CASE_IGNORE_IA5_OID, null, SYNTAX_IA5_STRING_OID, true,
+        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.13", Collections
         .singletonList("description"), EMPTY_STRING, false, null,
@@ -185,42 +180,40 @@
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.27", Collections
-        .singletonList("destinationIndicator"), EMPTY_STRING, false,
-        null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
+        .singletonList("destinationIndicator"), EMPTY_STRING, false, null,
+        EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
         SYNTAX_PRINTABLE_STRING_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.49", Collections
         .singletonList("distinguishedName"), EMPTY_STRING, false, null,
-        EMR_DN_OID, null, null, null, SYNTAX_DN_OID, false, false,
-        false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+        EMR_DN_OID, null, null, null, SYNTAX_DN_OID, false, false, false,
+        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.46", Collections
         .singletonList("dnQualifier"), EMPTY_STRING, false, null,
-        EMR_CASE_IGNORE_OID, OMR_CASE_IGNORE_OID, SMR_CASE_IGNORE_OID,
-        null, SYNTAX_PRINTABLE_STRING_OID, false, false, false,
+        EMR_CASE_IGNORE_OID, OMR_CASE_IGNORE_OID, SMR_CASE_IGNORE_OID, null,
+        SYNTAX_PRINTABLE_STRING_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.47", Collections
-        .singletonList("enhancedSearchGuide"), EMPTY_STRING, false,
-        null, null, null, null, null, SYNTAX_ENHANCED_GUIDE_OID, false,
-        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
-        false);
-
-    builder.addAttributeType("2.5.4.23", Collections
-        .singletonList("facsimileTelephoneNumber"), EMPTY_STRING,
-        false, null, null, null, null, null, SYNTAX_FAXNUMBER_OID,
-        false, false, false, AttributeUsage.USER_APPLICATIONS,
-        RFC4519_ORIGIN, false);
-
-    builder.addAttributeType("2.5.4.44", Collections
-        .singletonList("generationQualifier"), EMPTY_STRING, false,
-        "name", null, null, null, null, null, false, false, false,
+        .singletonList("enhancedSearchGuide"), EMPTY_STRING, false, null, null,
+        null, null, null, SYNTAX_ENHANCED_GUIDE_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("2.5.4.42", Collections
-        .singletonList("givenName"), EMPTY_STRING, false, "name", null,
-        null, null, null, null, false, false, false,
+    builder.addAttributeType("2.5.4.23", Collections
+        .singletonList("facsimileTelephoneNumber"), EMPTY_STRING, false, null,
+        null, null, null, null, SYNTAX_FAXNUMBER_OID, false, false, false,
+        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+
+    builder.addAttributeType("2.5.4.44", Collections
+        .singletonList("generationQualifier"), EMPTY_STRING, false, "name",
+        null, null, null, null, null, false, false, false,
+        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+
+    builder.addAttributeType("2.5.4.42",
+        Collections.singletonList("givenName"), EMPTY_STRING, false, "name",
+        null, null, null, null, null, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.51", Collections
@@ -229,36 +222,27 @@
         SYNTAX_DIRECTORY_STRING_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("2.5.4.43", Collections
-        .singletonList("initials"), EMPTY_STRING, false, "name", null,
-        null, null, null, null, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+    builder.addAttributeType("2.5.4.43", Collections.singletonList("initials"),
+        EMPTY_STRING, false, "name", null, null, null, null, null, false,
+        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.25", Collections
-        .singletonList("internationalISDNNumber"), EMPTY_STRING, false,
-        null, EMR_NUMERIC_STRING_OID, null, SMR_NUMERIC_STRING_OID,
-        null, SYNTAX_NUMERIC_STRING_OID, false, false, false,
+        .singletonList("internationalISDNNumber"), EMPTY_STRING, false, null,
+        EMR_NUMERIC_STRING_OID, null, SMR_NUMERIC_STRING_OID, null,
+        SYNTAX_NUMERIC_STRING_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("2.5.4.7", Arrays.asList("l",
-        "localityName"), EMPTY_STRING, false, "name", null, null, null,
-        null, null, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+    builder.addAttributeType("2.5.4.7", Arrays.asList("l", "localityName"),
+        EMPTY_STRING, false, "name", null, null, null, null, null, false,
+        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("2.5.4.31", Collections
-        .singletonList("member"), EMPTY_STRING, false,
-        "distinguishedName", null, null, null, null, null, false,
-        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
+    builder.addAttributeType("2.5.4.31", Collections.singletonList("member"),
+        EMPTY_STRING, false, "distinguishedName", null, null, null, null, null,
+        false, false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
         false);
 
-    builder.addAttributeType("2.5.4.41", Collections
-        .singletonList("name"), EMPTY_STRING, false, null,
-        EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
-        SYNTAX_DIRECTORY_STRING_OID, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
-
-    builder.addAttributeType("2.5.4.10", Arrays.asList("o",
-        "organizationName"), EMPTY_STRING, false, null,
+    builder.addAttributeType("2.5.4.10",
+        Arrays.asList("o", "organizationName"), EMPTY_STRING, false, null,
         EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
         SYNTAX_DIRECTORY_STRING_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
@@ -269,16 +253,15 @@
         SYNTAX_DIRECTORY_STRING_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("2.5.4.32", Collections
-        .singletonList("owner"), EMPTY_STRING, false,
-        "distinguishedName", null, null, null, null, null, false,
-        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
+    builder.addAttributeType("2.5.4.32", Collections.singletonList("owner"),
+        EMPTY_STRING, false, "distinguishedName", null, null, null, null, null,
+        false, false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
         false);
 
     builder.addAttributeType("2.5.4.19", Collections
-        .singletonList("physicalDeliveryOfficeName"), EMPTY_STRING,
-        false, null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID,
-        null, SYNTAX_DIRECTORY_STRING_OID, false, false, false,
+        .singletonList("physicalDeliveryOfficeName"), EMPTY_STRING, false,
+        null, EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
+        SYNTAX_DIRECTORY_STRING_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.16", Collections
@@ -300,32 +283,29 @@
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.28", Collections
-        .singletonList("preferredDeliveryMethod"), EMPTY_STRING, false,
-        null, null, null, null, null, SYNTAX_DELIVERY_METHOD_OID, true,
-        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
-        false);
+        .singletonList("preferredDeliveryMethod"), EMPTY_STRING, false, null,
+        null, null, null, null, SYNTAX_DELIVERY_METHOD_OID, true, false, false,
+        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.26", Collections
         .singletonList("registeredAddress"), EMPTY_STRING, false,
-        "postalAddress", null, null, null, null,
-        SYNTAX_POSTAL_ADDRESS_OID, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+        "postalAddress", null, null, null, null, SYNTAX_POSTAL_ADDRESS_OID,
+        false, false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
+        false);
 
     builder.addAttributeType("2.5.4.33", Collections
         .singletonList("roleOccupant"), EMPTY_STRING, false,
-        "distinguishedName", null, null, null, null, null, false,
-        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
-        false);
-
-    builder.addAttributeType("2.5.4.14", Collections
-        .singletonList("searchGuide"), EMPTY_STRING, false, null, null,
-        null, null, null, SYNTAX_GUIDE_OID, false, false, false,
+        "distinguishedName", null, null, null, null, null, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("2.5.4.34", Collections
-        .singletonList("seeAlso"), EMPTY_STRING, false,
-        "distinguishedName", null, null, null, null, null, false,
-        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
+    builder.addAttributeType("2.5.4.14", Collections
+        .singletonList("searchGuide"), EMPTY_STRING, false, null, null, null,
+        null, null, SYNTAX_GUIDE_OID, false, false, false,
+        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+
+    builder.addAttributeType("2.5.4.34", Collections.singletonList("seeAlso"),
+        EMPTY_STRING, false, "distinguishedName", null, null, null, null, null,
+        false, false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
         false);
 
     builder.addAttributeType("2.5.4.5", Collections
@@ -335,48 +315,44 @@
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.4", Arrays.asList("sn", "surname"),
-        EMPTY_STRING, false, "name", null, null, null, null, null,
-        false, false, false, AttributeUsage.USER_APPLICATIONS,
-        RFC4519_ORIGIN, false);
+        EMPTY_STRING, false, "name", null, null, null, null, null, false,
+        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.8", Arrays.asList("st",
-        "stateOrProvinceName"), EMPTY_STRING, false, "name", null,
-        null, null, null, null, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+        "stateOrProvinceName"), EMPTY_STRING, false, "name", null, null, null,
+        null, null, false, false, false, AttributeUsage.USER_APPLICATIONS,
+        RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("2.5.4.9", Arrays.asList("street",
-        "streetAddress"), EMPTY_STRING, false, null,
+    builder.addAttributeType("2.5.4.9", Arrays
+        .asList("street", "streetAddress"), EMPTY_STRING, false, null,
         EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
         SYNTAX_DIRECTORY_STRING_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.20", Collections
         .singletonList("telephoneNumber"), EMPTY_STRING, false, null,
-        EMR_TELEPHONE_OID, null, SMR_TELEPHONE_OID, null,
-        SYNTAX_TELEPHONE_OID, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+        EMR_TELEPHONE_OID, null, SMR_TELEPHONE_OID, null, SYNTAX_TELEPHONE_OID,
+        false, false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN,
+        false);
 
     builder.addAttributeType("2.5.4.22", Collections
-        .singletonList("teletexTerminalIdentifier"), EMPTY_STRING,
-        false, null, null, null, null, null,
-        SYNTAX_TELETEX_TERM_ID_OID, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+        .singletonList("teletexTerminalIdentifier"), EMPTY_STRING, false, null,
+        null, null, null, null, SYNTAX_TELETEX_TERM_ID_OID, false, false,
+        false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.21", Collections
-        .singletonList("telexNumber"), EMPTY_STRING, false, null, null,
-        null, null, null, SYNTAX_TELEX_OID, false, false, false,
+        .singletonList("telexNumber"), EMPTY_STRING, false, null, null, null,
+        null, null, SYNTAX_TELEX_OID, false, false, false,
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("2.5.4.12", Collections
-        .singletonList("title"), EMPTY_STRING, false, "name", null,
-        null, null, null, null, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+    builder.addAttributeType("2.5.4.12", Collections.singletonList("title"),
+        EMPTY_STRING, false, "name", null, null, null, null, null, false,
+        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
-    builder.addAttributeType("0.9.2342.19200300.100.1.1", Arrays
-        .asList("uid", "userid"), EMPTY_STRING, false, null,
-        EMR_CASE_IGNORE_OID, null, SMR_CASE_IGNORE_OID, null,
-        SYNTAX_DIRECTORY_STRING_OID, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+    builder.addAttributeType("0.9.2342.19200300.100.1.1", Arrays.asList("uid",
+        "userid"), EMPTY_STRING, false, null, EMR_CASE_IGNORE_OID, null,
+        SMR_CASE_IGNORE_OID, null, SYNTAX_DIRECTORY_STRING_OID, false, false,
+        false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.50", Collections
         .singletonList("uniqueMember"), EMPTY_STRING, false, null,
@@ -386,9 +362,8 @@
 
     builder.addAttributeType("2.5.4.35", Collections
         .singletonList("userPassword"), EMPTY_STRING, false, null,
-        EMR_OCTET_STRING_OID, null, null, null,
-        SYNTAX_OCTET_STRING_OID, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+        EMR_OCTET_STRING_OID, null, null, null, SYNTAX_OCTET_STRING_OID, false,
+        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.24", Collections
         .singletonList("x121Address"), EMPTY_STRING, false, null,
@@ -397,10 +372,9 @@
         AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.45", Collections
-        .singletonList("x500UniqueIdentifier"), EMPTY_STRING, false,
-        null, EMR_BIT_STRING_OID, null, null, null,
-        SYNTAX_BIT_STRING_OID, false, false, false,
-        AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
+        .singletonList("x500UniqueIdentifier"), EMPTY_STRING, false, null,
+        EMR_BIT_STRING_OID, null, null, null, SYNTAX_BIT_STRING_OID, false,
+        false, false, AttributeUsage.USER_APPLICATIONS, RFC4519_ORIGIN, false);
 
     Set<String> attrs = new HashSet<String>();
     attrs.add("seeAlso");
@@ -409,25 +383,23 @@
     attrs.add("description");
 
     builder.addObjectClass("2.5.6.11", Collections
-        .singletonList("applicationProcess"), EMPTY_STRING, false,
-        Collections.singleton(TOP_OBJECTCLASS_NAME), Collections
-            .singleton("cn"), attrs, ObjectClassType.STRUCTURAL,
-        RFC4519_ORIGIN, false);
+        .singletonList("applicationProcess"), EMPTY_STRING, false, Collections
+        .singleton(TOP_OBJECTCLASS_NAME), Collections.singleton("cn"), attrs,
+        ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
 
     attrs = new HashSet<String>();
     attrs.add("searchGuide");
     attrs.add("description");
 
-    builder.addObjectClass("2.5.6.2", Collections
-        .singletonList("country"), EMPTY_STRING, false, Collections
-        .singleton(TOP_OBJECTCLASS_NAME), Collections.singleton("c"),
-        attrs, ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
+    builder.addObjectClass("2.5.6.2", Collections.singletonList("country"),
+        EMPTY_STRING, false, Collections.singleton(TOP_OBJECTCLASS_NAME),
+        Collections.singleton("c"), attrs, ObjectClassType.STRUCTURAL,
+        RFC4519_ORIGIN, false);
 
     builder.addObjectClass("1.3.6.1.4.1.1466.344", Collections
         .singletonList("dcObject"), EMPTY_STRING, false, Collections
         .singleton(TOP_OBJECTCLASS_NAME), Collections.singleton("dc"),
-        EMPTY_STRING_SET, ObjectClassType.AUXILIARY, RFC4519_ORIGIN,
-        false);
+        EMPTY_STRING_SET, ObjectClassType.AUXILIARY, RFC4519_ORIGIN, false);
 
     attrs = new HashSet<String>();
     attrs.add("serialNumber");
@@ -438,10 +410,10 @@
     attrs.add("l");
     attrs.add("description");
 
-    builder.addObjectClass("2.5.6.14", Collections
-        .singletonList("device"), EMPTY_STRING, false, Collections
-        .singleton(TOP_OBJECTCLASS_NAME), Collections.singleton("cn"),
-        attrs, ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
+    builder.addObjectClass("2.5.6.14", Collections.singletonList("device"),
+        EMPTY_STRING, false, Collections.singleton(TOP_OBJECTCLASS_NAME),
+        Collections.singleton("cn"), attrs, ObjectClassType.STRUCTURAL,
+        RFC4519_ORIGIN, false);
 
     Set<String> must = new HashSet<String>();
     must.add("member");
@@ -455,8 +427,8 @@
     attrs.add("o");
     attrs.add("description");
 
-    builder.addObjectClass("2.5.6.9", Collections
-        .singletonList("groupOfNames"), EMPTY_STRING, false,
+    builder.addObjectClass("2.5.6.9",
+        Collections.singletonList("groupOfNames"), EMPTY_STRING, false,
         Collections.singleton(TOP_OBJECTCLASS_NAME), must, attrs,
         ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
 
@@ -469,8 +441,8 @@
     attrs.add("description");
 
     builder.addObjectClass("2.5.6.17", Collections
-        .singletonList("groupOfUniqueNames"), EMPTY_STRING, false,
-        Collections.singleton(TOP_OBJECTCLASS_NAME), must, attrs,
+        .singletonList("groupOfUniqueNames"), EMPTY_STRING, false, Collections
+        .singleton(TOP_OBJECTCLASS_NAME), must, attrs,
         ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
 
     attrs = new HashSet<String>();
@@ -481,10 +453,10 @@
     attrs.add("l");
     attrs.add("description");
 
-    builder.addObjectClass("2.5.6.3", Collections
-        .singletonList("locality"), EMPTY_STRING, false, Collections
-        .singleton(TOP_OBJECTCLASS_NAME), EMPTY_STRING_SET, attrs,
-        ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
+    builder.addObjectClass("2.5.6.3", Collections.singletonList("locality"),
+        EMPTY_STRING, false, Collections.singleton(TOP_OBJECTCLASS_NAME),
+        EMPTY_STRING_SET, attrs, ObjectClassType.STRUCTURAL, RFC4519_ORIGIN,
+        false);
 
     attrs = new HashSet<String>();
     attrs.add("userPassword");
@@ -509,10 +481,10 @@
     attrs.add("l");
     attrs.add("description");
 
-    builder.addObjectClass("2.5.6.4", Collections
-        .singletonList("organization"), EMPTY_STRING, false,
-        Collections.singleton(TOP_OBJECTCLASS_NAME), Collections
-            .singleton("o"), attrs, ObjectClassType.STRUCTURAL,
+    builder.addObjectClass("2.5.6.4",
+        Collections.singletonList("organization"), EMPTY_STRING, false,
+        Collections.singleton(TOP_OBJECTCLASS_NAME),
+        Collections.singleton("o"), attrs, ObjectClassType.STRUCTURAL,
         RFC4519_ORIGIN, false);
 
     attrs = new HashSet<String>();
@@ -564,10 +536,9 @@
     attrs.add("description");
 
     builder.addObjectClass("2.5.6.8", Collections
-        .singletonList("organizationalRole"), EMPTY_STRING, false,
-        Collections.singleton(TOP_OBJECTCLASS_NAME), Collections
-            .singleton("cn"), attrs, ObjectClassType.STRUCTURAL,
-        RFC4519_ORIGIN, false);
+        .singletonList("organizationalRole"), EMPTY_STRING, false, Collections
+        .singleton(TOP_OBJECTCLASS_NAME), Collections.singleton("cn"), attrs,
+        ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
 
     attrs = new HashSet<String>();
     attrs.add("businessCategory");
@@ -593,10 +564,9 @@
     attrs.add("x121Address");
 
     builder.addObjectClass("2.5.6.5", Collections
-        .singletonList("organizationalUnit"), EMPTY_STRING, false,
-        Collections.singleton(TOP_OBJECTCLASS_NAME), Collections
-            .singleton("ou"), attrs, ObjectClassType.STRUCTURAL,
-        RFC4519_ORIGIN, false);
+        .singletonList("organizationalUnit"), EMPTY_STRING, false, Collections
+        .singleton(TOP_OBJECTCLASS_NAME), Collections.singleton("ou"), attrs,
+        ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
 
     must = new HashSet<String>();
     must.add("sn");
@@ -609,10 +579,9 @@
     attrs.add("seeAlso");
     attrs.add("description");
 
-    builder.addObjectClass("2.5.6.6", Collections
-        .singletonList("person"), EMPTY_STRING, false, Collections
-        .singleton(TOP_OBJECTCLASS_NAME), must, attrs,
-        ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
+    builder.addObjectClass("2.5.6.6", Collections.singletonList("person"),
+        EMPTY_STRING, false, Collections.singleton(TOP_OBJECTCLASS_NAME), must,
+        attrs, ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
 
     attrs = new HashSet<String>();
     attrs.add("businessCategory");
@@ -635,104 +604,92 @@
     attrs.add("l");
 
     builder.addObjectClass("2.5.6.10", Collections
-        .singletonList("residentialPerson"), EMPTY_STRING, false,
-        Collections.singleton("person"), Collections.singleton("l"),
-        attrs, ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
+        .singletonList("residentialPerson"), EMPTY_STRING, false, Collections
+        .singleton("person"), Collections.singleton("l"), attrs,
+        ObjectClassType.STRUCTURAL, RFC4519_ORIGIN, false);
 
     builder.addObjectClass("1.3.6.1.1.3.1", Collections
         .singletonList("uidObject"), EMPTY_STRING, false, Collections
-        .singleton(TOP_OBJECTCLASS_NAME), Collections.singleton("uid"),
-        attrs, ObjectClassType.AUXILIARY, RFC4519_ORIGIN, false);
+        .singleton(TOP_OBJECTCLASS_NAME), Collections.singleton("uid"), attrs,
+        ObjectClassType.AUXILIARY, RFC4519_ORIGIN, false);
   }
 
 
 
-  private static void addRFC4530(SchemaBuilder builder)
+  private static void addRFC4530(final SchemaBuilder builder)
   {
-    builder.addSyntax(SYNTAX_UUID_OID, SYNTAX_UUID_DESCRIPTION,
-        RFC4530_ORIGIN, new UUIDSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_UUID_OID, SYNTAX_UUID_DESCRIPTION, RFC4530_ORIGIN,
+        new UUIDSyntaxImpl(), false);
     builder.addMatchingRule(EMR_UUID_OID, Collections
-        .singletonList(EMR_UUID_NAME), EMPTY_STRING, false,
-        SYNTAX_UUID_OID, RFC4530_ORIGIN,
-        new UUIDEqualityMatchingRuleImpl(), false);
+        .singletonList(EMR_UUID_NAME), EMPTY_STRING, false, SYNTAX_UUID_OID,
+        RFC4530_ORIGIN, new UUIDEqualityMatchingRuleImpl(), false);
     builder.addMatchingRule(OMR_UUID_OID, Collections
-        .singletonList(OMR_UUID_NAME), EMPTY_STRING, false,
-        SYNTAX_UUID_OID, RFC4530_ORIGIN,
-        new UUIDOrderingMatchingRuleImpl(), false);
+        .singletonList(OMR_UUID_NAME), EMPTY_STRING, false, SYNTAX_UUID_OID,
+        RFC4530_ORIGIN, new UUIDOrderingMatchingRuleImpl(), false);
     builder.addAttributeType("1.3.6.1.1.16.4", Collections
         .singletonList("entryUUID"), "UUID of the entry", false, null,
-        EMR_UUID_OID, OMR_UUID_OID, null, null, SYNTAX_UUID_OID, true,
-        false, true, AttributeUsage.DIRECTORY_OPERATION,
-        RFC4530_ORIGIN, false);
+        EMR_UUID_OID, OMR_UUID_OID, null, null, SYNTAX_UUID_OID, true, false,
+        true, AttributeUsage.DIRECTORY_OPERATION, RFC4530_ORIGIN, false);
   }
 
 
 
-  private static void addSunProprietary(SchemaBuilder builder)
+  private static void addSunProprietary(final SchemaBuilder builder)
   {
     builder.addSyntax(SYNTAX_USER_PASSWORD_OID,
         SYNTAX_USER_PASSWORD_DESCRIPTION, OPENDS_ORIGIN,
         new UserPasswordSyntaxImpl(), false);
     builder.addMatchingRule(EMR_USER_PASSWORD_EXACT_OID, Collections
         .singletonList(EMR_USER_PASSWORD_EXACT_NAME),
-        EMR_USER_PASSWORD_EXACT_DESCRIPTION, false,
-        SYNTAX_USER_PASSWORD_OID, OPENDS_ORIGIN,
-        new UserPasswordExactEqualityMatchingRuleImpl(), false);
+        EMR_USER_PASSWORD_EXACT_DESCRIPTION, false, SYNTAX_USER_PASSWORD_OID,
+        OPENDS_ORIGIN, new UserPasswordExactEqualityMatchingRuleImpl(), false);
     builder.addMatchingRule(AMR_DOUBLE_METAPHONE_OID, Collections
         .singletonList(AMR_DOUBLE_METAPHONE_NAME),
-        AMR_DOUBLE_METAPHONE_DESCRIPTION, false,
-        SYNTAX_DIRECTORY_STRING_OID, OPENDS_ORIGIN,
-        new DoubleMetaphoneApproximateMatchingRuleImpl(), false);
+        AMR_DOUBLE_METAPHONE_DESCRIPTION, false, SYNTAX_DIRECTORY_STRING_OID,
+        OPENDS_ORIGIN, new DoubleMetaphoneApproximateMatchingRuleImpl(), false);
 
   }
 
 
 
-  private static void defaultAttributeTypes(SchemaBuilder builder)
+  private static void defaultAttributeTypes(final SchemaBuilder builder)
   {
     builder.addAttributeType("2.5.4.0", Collections
-        .singletonList("objectClass"), EMPTY_STRING, false, null,
-        EMR_OID_NAME, null, null, null, SYNTAX_OID_OID, false, false,
-        false, AttributeUsage.USER_APPLICATIONS, RFC4512_ORIGIN, false);
+        .singletonList("objectClass"), EMPTY_STRING, false, null, EMR_OID_NAME,
+        null, null, null, SYNTAX_OID_OID, false, false, false,
+        AttributeUsage.USER_APPLICATIONS, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("2.5.4.1", Collections
         .singletonList("aliasedObjectName"), EMPTY_STRING, false, null,
-        EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true, false,
-        false, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN,
-        false);
+        EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true, false, false,
+        AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("2.5.18.1", Collections
         .singletonList("createTimestamp"), EMPTY_STRING, false, null,
-        EMR_GENERALIZED_TIME_NAME, OMR_GENERALIZED_TIME_NAME, null,
-        null, SYNTAX_GENERALIZED_TIME_OID, true, false, true,
+        EMR_GENERALIZED_TIME_NAME, OMR_GENERALIZED_TIME_NAME, null, null,
+        SYNTAX_GENERALIZED_TIME_OID, true, false, true,
         AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("2.5.18.2", Collections
         .singletonList("modifyTimestamp"), EMPTY_STRING, false, null,
-        EMR_GENERALIZED_TIME_NAME, OMR_GENERALIZED_TIME_NAME, null,
-        null, SYNTAX_GENERALIZED_TIME_OID, true, false, true,
+        EMR_GENERALIZED_TIME_NAME, OMR_GENERALIZED_TIME_NAME, null, null,
+        SYNTAX_GENERALIZED_TIME_OID, true, false, true,
         AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
 
-    builder
-        .addAttributeType("2.5.18.3", Collections
-            .singletonList("creatorsName"), EMPTY_STRING, false, null,
-            EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true, false,
-            true, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN,
-            false);
+    builder.addAttributeType("2.5.18.3", Collections
+        .singletonList("creatorsName"), EMPTY_STRING, false, null, EMR_DN_NAME,
+        null, null, null, SYNTAX_DN_OID, true, false, true,
+        AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
 
-    builder
-        .addAttributeType("2.5.18.4", Collections
-            .singletonList("modifiersName"), EMPTY_STRING, false, null,
-            EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true, false,
-            true, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN,
-            false);
+    builder.addAttributeType("2.5.18.4", Collections
+        .singletonList("modifiersName"), EMPTY_STRING, false, null,
+        EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true, false, true,
+        AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
 
-    builder
-        .addAttributeType("2.5.18.10", Collections
-            .singletonList("subschemaSubentry"), EMPTY_STRING, false,
-            null, EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true,
-            false, true, AttributeUsage.DIRECTORY_OPERATION,
-            RFC4512_ORIGIN, false);
+    builder.addAttributeType("2.5.18.10", Collections
+        .singletonList("subschemaSubentry"), EMPTY_STRING, false, null,
+        EMR_DN_NAME, null, null, null, SYNTAX_DN_OID, true, false, true,
+        AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("2.5.21.5", Collections
         .singletonList("attributeTypes"), EMPTY_STRING, false, null,
@@ -742,9 +699,9 @@
 
     builder.addAttributeType("2.5.21.6", Collections
         .singletonList("objectClasses"), EMPTY_STRING, false, null,
-        EMR_OID_FIRST_COMPONENT_NAME, null, null, null,
-        SYNTAX_OBJECTCLASS_OID, false, false, false,
-        AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
+        EMR_OID_FIRST_COMPONENT_NAME, null, null, null, SYNTAX_OBJECTCLASS_OID,
+        false, false, false, AttributeUsage.DIRECTORY_OPERATION,
+        RFC4512_ORIGIN, false);
 
     builder.addAttributeType("2.5.21.4", Collections
         .singletonList("matchingRules"), EMPTY_STRING, false, null,
@@ -759,58 +716,55 @@
         AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("2.5.21.9", Collections
-        .singletonList("structuralObjectClass"), EMPTY_STRING, false,
-        null, EMR_OID_NAME, null, null, null, SYNTAX_OID_OID, true,
-        false, true, AttributeUsage.DIRECTORY_OPERATION,
-        RFC4512_ORIGIN, false);
+        .singletonList("structuralObjectClass"), EMPTY_STRING, false, null,
+        EMR_OID_NAME, null, null, null, SYNTAX_OID_OID, true, false, true,
+        AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("2.5.21.10", Collections
-        .singletonList("governingStructureRule"), EMPTY_STRING, false,
-        null, EMR_INTEGER_NAME, null, null, null, SYNTAX_INTEGER_OID,
-        true, false, true, AttributeUsage.DIRECTORY_OPERATION,
-        RFC4512_ORIGIN, false);
+        .singletonList("governingStructureRule"), EMPTY_STRING, false, null,
+        EMR_INTEGER_NAME, null, null, null, SYNTAX_INTEGER_OID, true, false,
+        true, AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("1.3.6.1.4.1.1466.101.120.5", Collections
-        .singletonList("namingContexts"), EMPTY_STRING, false, null,
-        null, null, null, null, SYNTAX_DN_OID, false, false, false,
+        .singletonList("namingContexts"), EMPTY_STRING, false, null, null,
+        null, null, null, SYNTAX_DN_OID, false, false, false,
         AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("1.3.6.1.4.1.1466.101.120.6", Collections
-        .singletonList("altServer"), EMPTY_STRING, false, null, null,
-        null, null, null, SYNTAX_IA5_STRING_OID, false, false, false,
+        .singletonList("altServer"), EMPTY_STRING, false, null, null, null,
+        null, null, SYNTAX_IA5_STRING_OID, false, false, false,
         AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("1.3.6.1.4.1.1466.101.120.7", Collections
-        .singletonList("supportedExtension"), EMPTY_STRING, false,
-        null, null, null, null, null, SYNTAX_OID_OID, false, false,
-        false, AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
+        .singletonList("supportedExtension"), EMPTY_STRING, false, null, null,
+        null, null, null, SYNTAX_OID_OID, false, false, false,
+        AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("1.3.6.1.4.1.1466.101.120.13", Collections
-        .singletonList("supportedControl"), EMPTY_STRING, false, null,
-        null, null, null, null, SYNTAX_OID_OID, false, false, false,
+        .singletonList("supportedControl"), EMPTY_STRING, false, null, null,
+        null, null, null, SYNTAX_OID_OID, false, false, false,
         AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("1.3.6.1.4.1.1466.101.120.14", Collections
-        .singletonList("supportedSASLMechanisms"), EMPTY_STRING, false,
-        null, null, null, null, null, SYNTAX_DIRECTORY_STRING_OID,
-        false, false, false, AttributeUsage.DSA_OPERATION,
-        RFC4512_ORIGIN, false);
+        .singletonList("supportedSASLMechanisms"), EMPTY_STRING, false, null,
+        null, null, null, null, SYNTAX_DIRECTORY_STRING_OID, false, false,
+        false, AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("1.3.6.1.4.1.4203.1.3.5", Collections
         .singletonList("supportedFeatures"), EMPTY_STRING, false, null,
-        EMR_OID_NAME, null, null, null, SYNTAX_OID_OID, false, false,
-        false, AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
+        EMR_OID_NAME, null, null, null, SYNTAX_OID_OID, false, false, false,
+        AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("1.3.6.1.4.1.1466.101.120.15", Collections
-        .singletonList("supportedLDAPVersion"), EMPTY_STRING, false,
-        null, null, null, null, null, SYNTAX_INTEGER_OID, false, false,
-        false, AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
+        .singletonList("supportedLDAPVersion"), EMPTY_STRING, false, null,
+        null, null, null, null, SYNTAX_INTEGER_OID, false, false, false,
+        AttributeUsage.DSA_OPERATION, RFC4512_ORIGIN, false);
 
     builder.addAttributeType("1.3.6.1.4.1.1466.101.120.16", Collections
         .singletonList("ldapSyntaxes"), EMPTY_STRING, false, null,
-        EMR_OID_FIRST_COMPONENT_NAME, null, null, null,
-        SYNTAX_LDAP_SYNTAX_OID, false, false, false,
-        AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
+        EMR_OID_FIRST_COMPONENT_NAME, null, null, null, SYNTAX_LDAP_SYNTAX_OID,
+        false, false, false, AttributeUsage.DIRECTORY_OPERATION,
+        RFC4512_ORIGIN, false);
 
     builder.addAttributeType("2.5.21.1", Collections
         .singletonList("ditStructureRules"), EMPTY_STRING, false, null,
@@ -818,11 +772,11 @@
         SYNTAX_DIT_STRUCTURE_RULE_OID, false, false, false,
         AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
 
-    builder.addAttributeType("2.5.21.7", Collections
-        .singletonList("nameForms"), EMPTY_STRING, false, null,
-        EMR_OID_FIRST_COMPONENT_NAME, null, null, null,
-        SYNTAX_NAME_FORM_OID, false, false, false,
-        AttributeUsage.DIRECTORY_OPERATION, RFC4512_ORIGIN, false);
+    builder.addAttributeType("2.5.21.7",
+        Collections.singletonList("nameForms"), EMPTY_STRING, false, null,
+        EMR_OID_FIRST_COMPONENT_NAME, null, null, null, SYNTAX_NAME_FORM_OID,
+        false, false, false, AttributeUsage.DIRECTORY_OPERATION,
+        RFC4512_ORIGIN, false);
 
     builder.addAttributeType("2.5.21.2", Collections
         .singletonList("ditContentRules"), EMPTY_STRING, false, null,
@@ -833,7 +787,7 @@
 
 
 
-  private static void defaultMatchingRules(SchemaBuilder builder)
+  private static void defaultMatchingRules(final SchemaBuilder builder)
   {
     builder.addMatchingRule(EMR_BIT_STRING_OID, Collections
         .singletonList(EMR_BIT_STRING_NAME), EMPTY_STRING, false,
@@ -892,15 +846,11 @@
         SYNTAX_SUBSTRING_ASSERTION_OID, RFC4512_ORIGIN,
         new CaseIgnoreSubstringMatchingRuleImpl(), false);
     builder.addMatchingRule(EMR_DIRECTORY_STRING_FIRST_COMPONENT_OID,
-        Collections
-            .singletonList(EMR_DIRECTORY_STRING_FIRST_COMPONENT_NAME),
-        EMPTY_STRING, false, SYNTAX_DIRECTORY_STRING_OID,
-        RFC4512_ORIGIN,
-        new DirectoryStringFirstComponentEqualityMatchingRuleImpl(),
-        false);
-    builder.addMatchingRule(EMR_DN_OID, Collections
-        .singletonList(EMR_DN_NAME), EMPTY_STRING, false,
-        SYNTAX_DN_OID, RFC4512_ORIGIN,
+        Collections.singletonList(EMR_DIRECTORY_STRING_FIRST_COMPONENT_NAME),
+        EMPTY_STRING, false, SYNTAX_DIRECTORY_STRING_OID, RFC4512_ORIGIN,
+        new DirectoryStringFirstComponentEqualityMatchingRuleImpl(), false);
+    builder.addMatchingRule(EMR_DN_OID, Collections.singletonList(EMR_DN_NAME),
+        EMPTY_STRING, false, SYNTAX_DN_OID, RFC4512_ORIGIN,
         new DistinguishedNameEqualityMatchingRuleImpl(), false);
     builder.addMatchingRule(EMR_GENERALIZED_TIME_OID, Collections
         .singletonList(EMR_GENERALIZED_TIME_NAME), EMPTY_STRING, false,
@@ -910,9 +860,9 @@
         .singletonList(OMR_GENERALIZED_TIME_NAME), EMPTY_STRING, false,
         SYNTAX_GENERALIZED_TIME_OID, RFC4512_ORIGIN,
         new GeneralizedTimeOrderingMatchingRuleImpl(), false);
-    builder.addMatchingRule(EMR_INTEGER_FIRST_COMPONENT_OID,
-        Collections.singletonList(EMR_INTEGER_FIRST_COMPONENT_NAME),
-        EMPTY_STRING, false, SYNTAX_INTEGER_OID, RFC4512_ORIGIN,
+    builder.addMatchingRule(EMR_INTEGER_FIRST_COMPONENT_OID, Collections
+        .singletonList(EMR_INTEGER_FIRST_COMPONENT_NAME), EMPTY_STRING, false,
+        SYNTAX_INTEGER_OID, RFC4512_ORIGIN,
         new IntegerFirstComponentEqualityMatchingRuleImpl(), false);
     builder.addMatchingRule(EMR_INTEGER_OID, Collections
         .singletonList(EMR_INTEGER_NAME), EMPTY_STRING, false,
@@ -939,14 +889,12 @@
         SYNTAX_SUBSTRING_ASSERTION_OID, RFC4512_ORIGIN,
         new NumericStringSubstringMatchingRuleImpl(), false);
     builder.addMatchingRule(EMR_OID_FIRST_COMPONENT_OID, Collections
-        .singletonList(EMR_OID_FIRST_COMPONENT_NAME), EMPTY_STRING,
-        false, SYNTAX_OID_OID, RFC4512_ORIGIN,
-        new ObjectIdentifierFirstComponentEqualityMatchingRuleImpl(),
-        false);
-    builder.addMatchingRule(EMR_OID_OID, Collections
-        .singletonList(EMR_OID_NAME), EMPTY_STRING, false,
+        .singletonList(EMR_OID_FIRST_COMPONENT_NAME), EMPTY_STRING, false,
         SYNTAX_OID_OID, RFC4512_ORIGIN,
-        new ObjectIdentifierEqualityMatchingRuleImpl(), false);
+        new ObjectIdentifierFirstComponentEqualityMatchingRuleImpl(), false);
+    builder.addMatchingRule(EMR_OID_OID, Collections
+        .singletonList(EMR_OID_NAME), EMPTY_STRING, false, SYNTAX_OID_OID,
+        RFC4512_ORIGIN, new ObjectIdentifierEqualityMatchingRuleImpl(), false);
     builder.addMatchingRule(EMR_OCTET_STRING_OID, Collections
         .singletonList(EMR_OCTET_STRING_NAME), EMPTY_STRING, false,
         SYNTAX_OCTET_STRING_OID, RFC4512_ORIGIN,
@@ -962,13 +910,13 @@
         new OctetStringSubstringMatchingRuleImpl(), false);
     // Depreciated in RFC 4512
     builder.addMatchingRule(EMR_PROTOCOL_INFORMATION_OID, Collections
-        .singletonList(EMR_PROTOCOL_INFORMATION_NAME), EMPTY_STRING,
-        false, SYNTAX_PROTOCOL_INFORMATION_OID, RFC2252_ORIGIN,
+        .singletonList(EMR_PROTOCOL_INFORMATION_NAME), EMPTY_STRING, false,
+        SYNTAX_PROTOCOL_INFORMATION_OID, RFC2252_ORIGIN,
         new ProtocolInformationEqualityMatchingRuleImpl(), false);
     // Depreciated in RFC 4512
     builder.addMatchingRule(EMR_PRESENTATION_ADDRESS_OID, Collections
-        .singletonList(EMR_PRESENTATION_ADDRESS_NAME), EMPTY_STRING,
-        false, SYNTAX_PRESENTATION_ADDRESS_OID, RFC2252_ORIGIN,
+        .singletonList(EMR_PRESENTATION_ADDRESS_NAME), EMPTY_STRING, false,
+        SYNTAX_PRESENTATION_ADDRESS_OID, RFC2252_ORIGIN,
         new PresentationAddressEqualityMatchingRuleImpl(), false);
     builder.addMatchingRule(EMR_TELEPHONE_OID, Collections
         .singletonList(EMR_TELEPHONE_NAME), EMPTY_STRING, false,
@@ -990,26 +938,22 @@
 
 
 
-  private static void defaultObjectClasses(SchemaBuilder builder)
+  private static void defaultObjectClasses(final SchemaBuilder builder)
   {
     builder.addObjectClass(TOP_OBJECTCLASS_OID, Collections
-        .singletonList(TOP_OBJECTCLASS_NAME),
-        TOP_OBJECTCLASS_DESCRIPTION, false, EMPTY_STRING_SET,
-        Collections.singleton("objectClass"), EMPTY_STRING_SET,
-        ObjectClassType.ABSTRACT, RFC4512_ORIGIN, false);
+        .singletonList(TOP_OBJECTCLASS_NAME), TOP_OBJECTCLASS_DESCRIPTION,
+        false, EMPTY_STRING_SET, Collections.singleton("objectClass"),
+        EMPTY_STRING_SET, ObjectClassType.ABSTRACT, RFC4512_ORIGIN, false);
 
-    builder.addObjectClass("2.5.6.1", Collections
-        .singletonList("alias"), EMPTY_STRING, false, Collections
-        .singleton("top"), Collections.singleton("aliasedObjectName"),
-        EMPTY_STRING_SET, ObjectClassType.STRUCTURAL, RFC4512_ORIGIN,
-        false);
+    builder.addObjectClass("2.5.6.1", Collections.singletonList("alias"),
+        EMPTY_STRING, false, Collections.singleton("top"), Collections
+            .singleton("aliasedObjectName"), EMPTY_STRING_SET,
+        ObjectClassType.STRUCTURAL, RFC4512_ORIGIN, false);
 
-    builder.addObjectClass(EXTENSIBLE_OBJECT_OBJECTCLASS_OID,
-        Collections.singletonList(EXTENSIBLE_OBJECT_OBJECTCLASS_NAME),
-        EMPTY_STRING, false, Collections
-            .singleton(TOP_OBJECTCLASS_NAME), EMPTY_STRING_SET,
-        EMPTY_STRING_SET, ObjectClassType.AUXILIARY, RFC4512_ORIGIN,
-        false);
+    builder.addObjectClass(EXTENSIBLE_OBJECT_OBJECTCLASS_OID, Collections
+        .singletonList(EXTENSIBLE_OBJECT_OBJECTCLASS_NAME), EMPTY_STRING,
+        false, Collections.singleton(TOP_OBJECTCLASS_NAME), EMPTY_STRING_SET,
+        EMPTY_STRING_SET, ObjectClassType.AUXILIARY, RFC4512_ORIGIN, false);
 
     final Set<String> subschemaAttrs = new HashSet<String>();
     subschemaAttrs.add("dITStructureRules");
@@ -1020,16 +964,15 @@
     subschemaAttrs.add("matchingRules");
     subschemaAttrs.add("matchingRuleUse");
 
-    builder.addObjectClass("2.5.20.1", Collections
-        .singletonList("subschema"), EMPTY_STRING, false, Collections
-        .singleton(TOP_OBJECTCLASS_NAME), EMPTY_STRING_SET,
-        subschemaAttrs, ObjectClassType.AUXILIARY, RFC4512_ORIGIN,
-        false);
+    builder.addObjectClass("2.5.20.1", Collections.singletonList("subschema"),
+        EMPTY_STRING, false, Collections.singleton(TOP_OBJECTCLASS_NAME),
+        EMPTY_STRING_SET, subschemaAttrs, ObjectClassType.AUXILIARY,
+        RFC4512_ORIGIN, false);
   }
 
 
 
-  private static void defaultSyntaxes(SchemaBuilder builder)
+  private static void defaultSyntaxes(final SchemaBuilder builder)
   {
     // All RFC 4512 / 4517
     builder.addSyntax(SYNTAX_ATTRIBUTE_TYPE_OID,
@@ -1037,18 +980,16 @@
         new AttributeTypeSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_BINARY_OID, SYNTAX_BINARY_DESCRIPTION,
         RFC4512_ORIGIN, new BinarySyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_BIT_STRING_OID,
-        SYNTAX_BIT_STRING_DESCRIPTION, RFC4512_ORIGIN,
-        new BitStringSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_BIT_STRING_OID, SYNTAX_BIT_STRING_DESCRIPTION,
+        RFC4512_ORIGIN, new BitStringSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_BOOLEAN_OID, SYNTAX_BOOLEAN_DESCRIPTION,
         RFC4512_ORIGIN, new BooleanSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_CERTLIST_OID, SYNTAX_CERTLIST_DESCRIPTION,
         RFC4512_ORIGIN, new CertificateListSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_CERTPAIR_OID, SYNTAX_CERTPAIR_DESCRIPTION,
         RFC4512_ORIGIN, new CertificatePairSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_CERTIFICATE_OID,
-        SYNTAX_CERTIFICATE_DESCRIPTION, RFC4512_ORIGIN,
-        new CertificateSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_CERTIFICATE_OID, SYNTAX_CERTIFICATE_DESCRIPTION,
+        RFC4512_ORIGIN, new CertificateSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_COUNTRY_STRING_OID,
         SYNTAX_COUNTRY_STRING_DESCRIPTION, RFC4512_ORIGIN,
         new CountryStringSyntaxImpl(), false);
@@ -1064,54 +1005,48 @@
     builder.addSyntax(SYNTAX_DIT_STRUCTURE_RULE_OID,
         SYNTAX_DIT_STRUCTURE_RULE_DESCRIPTION, RFC4512_ORIGIN,
         new DITStructureRuleSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_DN_OID, SYNTAX_DN_DESCRIPTION,
-        RFC4512_ORIGIN, new DistinguishedNameSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_DN_OID, SYNTAX_DN_DESCRIPTION, RFC4512_ORIGIN,
+        new DistinguishedNameSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_ENHANCED_GUIDE_OID,
         SYNTAX_ENHANCED_GUIDE_DESCRIPTION, RFC4512_ORIGIN,
         new EnhancedGuideSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_FAXNUMBER_OID,
-        SYNTAX_FAXNUMBER_DESCRIPTION, RFC4512_ORIGIN,
-        new FacsimileNumberSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_FAX_OID, SYNTAX_FAX_DESCRIPTION,
-        RFC4512_ORIGIN, new FaxSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_FAXNUMBER_OID, SYNTAX_FAXNUMBER_DESCRIPTION,
+        RFC4512_ORIGIN, new FacsimileNumberSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_FAX_OID, SYNTAX_FAX_DESCRIPTION, RFC4512_ORIGIN,
+        new FaxSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_GENERALIZED_TIME_OID,
         SYNTAX_GENERALIZED_TIME_DESCRIPTION, RFC4512_ORIGIN,
         new GeneralizedTimeSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_GUIDE_OID, SYNTAX_GUIDE_DESCRIPTION,
         RFC4512_ORIGIN, new GuideSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_IA5_STRING_OID,
-        SYNTAX_IA5_STRING_DESCRIPTION, RFC4512_ORIGIN,
-        new IA5StringSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_IA5_STRING_OID, SYNTAX_IA5_STRING_DESCRIPTION,
+        RFC4512_ORIGIN, new IA5StringSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_INTEGER_OID, SYNTAX_INTEGER_DESCRIPTION,
         RFC4512_ORIGIN, new IntegerSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_JPEG_OID, SYNTAX_JPEG_DESCRIPTION,
-        RFC4512_ORIGIN, new JPEGSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_JPEG_OID, SYNTAX_JPEG_DESCRIPTION, RFC4512_ORIGIN,
+        new JPEGSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_MATCHING_RULE_OID,
         SYNTAX_MATCHING_RULE_DESCRIPTION, RFC4512_ORIGIN,
         new MatchingRuleSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_MATCHING_RULE_USE_OID,
         SYNTAX_MATCHING_RULE_USE_DESCRIPTION, RFC4512_ORIGIN,
         new MatchingRuleUseSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_LDAP_SYNTAX_OID,
-        SYNTAX_LDAP_SYNTAX_DESCRIPTION, RFC4512_ORIGIN,
-        new LDAPSyntaxDescriptionSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_LDAP_SYNTAX_OID, SYNTAX_LDAP_SYNTAX_DESCRIPTION,
+        RFC4512_ORIGIN, new LDAPSyntaxDescriptionSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_NAME_AND_OPTIONAL_UID_OID,
         SYNTAX_NAME_AND_OPTIONAL_UID_DESCRIPTION, RFC4517_ORIGIN,
         new NameAndOptionalUIDSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_NAME_FORM_OID,
-        SYNTAX_NAME_FORM_DESCRIPTION, RFC4512_ORIGIN,
-        new NameFormSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_NAME_FORM_OID, SYNTAX_NAME_FORM_DESCRIPTION,
+        RFC4512_ORIGIN, new NameFormSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_NUMERIC_STRING_OID,
         SYNTAX_NUMERIC_STRING_DESCRIPTION, RFC4512_ORIGIN,
         new NumericStringSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_OBJECTCLASS_OID,
-        SYNTAX_OBJECTCLASS_DESCRIPTION, RFC4512_ORIGIN,
-        new ObjectClassSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_OCTET_STRING_OID,
-        SYNTAX_OCTET_STRING_DESCRIPTION, RFC4512_ORIGIN,
-        new OctetStringSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_OID_OID, SYNTAX_OID_DESCRIPTION,
-        RFC4512_ORIGIN, new OIDSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_OBJECTCLASS_OID, SYNTAX_OBJECTCLASS_DESCRIPTION,
+        RFC4512_ORIGIN, new ObjectClassSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_OCTET_STRING_OID, SYNTAX_OCTET_STRING_DESCRIPTION,
+        RFC4512_ORIGIN, new OctetStringSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_OID_OID, SYNTAX_OID_DESCRIPTION, RFC4512_ORIGIN,
+        new OIDSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_OTHER_MAILBOX_OID,
         SYNTAX_OTHER_MAILBOX_DESCRIPTION, RFC4512_ORIGIN,
         new OtherMailboxSyntaxImpl(), false);
@@ -1135,9 +1070,8 @@
     builder.addSyntax(SYNTAX_SUPPORTED_ALGORITHM_OID,
         SYNTAX_SUPPORTED_ALGORITHM_DESCRIPTION, RFC4512_ORIGIN,
         new SupportedAlgorithmSyntaxImpl(), false);
-    builder.addSyntax(SYNTAX_TELEPHONE_OID,
-        SYNTAX_TELEPHONE_DESCRIPTION, RFC4512_ORIGIN,
-        new TelephoneNumberSyntaxImpl(), false);
+    builder.addSyntax(SYNTAX_TELEPHONE_OID, SYNTAX_TELEPHONE_DESCRIPTION,
+        RFC4512_ORIGIN, new TelephoneNumberSyntaxImpl(), false);
     builder.addSyntax(SYNTAX_TELETEX_TERM_ID_OID,
         SYNTAX_TELETEX_TERM_ID_DESCRIPTION, RFC4512_ORIGIN,
         new TeletexTerminalIdentifierSyntaxImpl(), false);
@@ -1146,4 +1080,11 @@
     builder.addSyntax(SYNTAX_UTC_TIME_OID, SYNTAX_UTC_TIME_DESCRIPTION,
         RFC4512_ORIGIN, new UTCTimeSyntaxImpl(), false);
   }
+
+
+
+  private CoreSchemaImpl()
+  {
+    // Prevent instantiation.
+  }
 }
diff --git a/sdk/src/org/opends/sdk/schema/CountryStringSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/CountryStringSyntaxImpl.java
index f43840d..a8969a1 100644
--- a/sdk/src/org/opends/sdk/schema/CountryStringSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/CountryStringSyntaxImpl.java
@@ -29,8 +29,9 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_COUNTRY_STRING_INVALID_LENGTH;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_COUNTRY_STRING_NOT_PRINTABLE;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
 import static org.opends.sdk.schema.SchemaConstants.*;
 
 import org.opends.sdk.ByteSequence;
@@ -38,13 +39,11 @@
 
 
 
-
 /**
- * This class defines the country string attribute syntax, which should
- * be a two-character ISO 3166 country code. However, for
- * maintainability, it will accept any value consisting entirely of two
- * printable characters. In most ways, it will behave like the directory
- * string attribute syntax.
+ * This class defines the country string attribute syntax, which should be a
+ * two-character ISO 3166 country code. However, for maintainability, it will
+ * accept any value consisting entirely of two printable characters. In most
+ * ways, it will behave like the directory string attribute syntax.
  */
 final class CountryStringSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -96,33 +95,31 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     final String stringValue = toLowerCase(value.toString());
     if (stringValue.length() != 2)
     {
-      invalidReason
-          .append(ERR_ATTR_SYNTAX_COUNTRY_STRING_INVALID_LENGTH
-              .get(stringValue));
+      invalidReason.append(ERR_ATTR_SYNTAX_COUNTRY_STRING_INVALID_LENGTH
+          .get(stringValue));
       return false;
     }
 
-    if (!PrintableStringSyntaxImpl.isPrintableCharacter(stringValue
-        .charAt(0))
+    if (!PrintableStringSyntaxImpl.isPrintableCharacter(stringValue.charAt(0))
         || !PrintableStringSyntaxImpl.isPrintableCharacter(stringValue
             .charAt(1)))
     {
diff --git a/sdk/src/org/opends/sdk/schema/DITContentRule.java b/sdk/src/org/opends/sdk/schema/DITContentRule.java
index ff44a5b..5949956 100644
--- a/sdk/src/org/opends/sdk/schema/DITContentRule.java
+++ b/sdk/src/org/opends/sdk/schema/DITContentRule.java
@@ -40,10 +40,10 @@
 
 
 /**
- * This class defines a DIT content rule, which defines the set of
- * allowed, required, and prohibited attributes for entries with a given
- * structural objectclass, and also indicates which auxiliary classes
- * that may be included in the entry.
+ * This class defines a DIT content rule, which defines the set of allowed,
+ * required, and prohibited attributes for entries with a given structural
+ * objectclass, and also indicates which auxiliary classes that may be included
+ * in the entry.
  */
 public final class DITContentRule extends SchemaElement
 {
@@ -75,22 +75,19 @@
 
   private ObjectClass structuralClass;
   private Set<ObjectClass> auxiliaryClasses = Collections.emptySet();
-  private Set<AttributeType> optionalAttributes =
-      Collections.emptySet();
-  private Set<AttributeType> prohibitedAttributes =
-      Collections.emptySet();
-  private Set<AttributeType> requiredAttributes =
-      Collections.emptySet();
+  private Set<AttributeType> optionalAttributes = Collections.emptySet();
+  private Set<AttributeType> prohibitedAttributes = Collections.emptySet();
+  private Set<AttributeType> requiredAttributes = Collections.emptySet();
 
 
 
-  DITContentRule(String structuralClassOID, List<String> names,
-      String description, boolean obsolete,
-      Set<String> auxiliaryClassOIDs,
-      Set<String> optionalAttributeOIDs,
-      Set<String> prohibitedAttributeOIDs,
-      Set<String> requiredAttributeOIDs,
-      Map<String, List<String>> extraProperties, String definition)
+  DITContentRule(final String structuralClassOID, final List<String> names,
+      final String description, final boolean obsolete,
+      final Set<String> auxiliaryClassOIDs,
+      final Set<String> optionalAttributeOIDs,
+      final Set<String> prohibitedAttributeOIDs,
+      final Set<String> requiredAttributeOIDs,
+      final Map<String, List<String>> extraProperties, final String definition)
   {
     super(description, extraProperties);
 
@@ -118,13 +115,13 @@
 
 
   /**
-   * Retrieves the set of auxiliary objectclasses that may be used for
-   * entries associated with this DIT content rule.
-   * 
-   * @return The set of auxiliary objectclasses that may be used for
-   *         entries associated with this DIT content rule.
+   * Returns an unmodifiable set containing the auxiliary objectclasses that may
+   * be used for entries associated with this DIT content rule.
+   *
+   * @return An unmodifiable set containing the auxiliary objectclasses that may
+   *         be used for entries associated with this DIT content rule.
    */
-  public Iterable<ObjectClass> getAuxiliaryClasses()
+  public Set<ObjectClass> getAuxiliaryClasses()
   {
     return auxiliaryClasses;
   }
@@ -132,11 +129,10 @@
 
 
   /**
-   * Retrieves the name or structural class OID for this schema
-   * definition. If it has one or more names, then the primary name will
-   * be returned. If it does not have any names, then the OID will be
-   * returned.
-   * 
+   * Returns the name or structural class OID for this schema definition. If it
+   * has one or more names, then the primary name will be returned. If it does
+   * not have any names, then the OID will be returned.
+   *
    * @return The name or OID for this schema definition.
    */
   public String getNameOrOID()
@@ -151,13 +147,13 @@
 
 
   /**
-   * Retrieves an iterable over the set of user-defined names that may
-   * be used to reference this schema definition.
-   * 
-   * @return Returns an iterable over the set of user-defined names that
+   * Returns an unmodifiable list containing the user-defined names that may be
+   * used to reference this schema definition.
+   *
+   * @return Returns an unmodifiable list containing the user-defined names that
    *         may be used to reference this schema definition.
    */
-  public Iterable<String> getNames()
+  public List<String> getNames()
   {
     return names;
   }
@@ -165,11 +161,13 @@
 
 
   /**
-   * Retrieves the set of optional attributes for this DIT content rule.
-   * 
-   * @return The set of optional attributes for this DIT content rule.
+   * Returns an unmodifiable set containing the optional attributes for this DIT
+   * content rule.
+   *
+   * @return An unmodifiable set containing the optional attributes for this DIT
+   *         content rule.
    */
-  public Iterable<AttributeType> getOptionalAttributes()
+  public Set<AttributeType> getOptionalAttributes()
   {
     return optionalAttributes;
   }
@@ -177,12 +175,13 @@
 
 
   /**
-   * Retrieves the set of prohibited attributes for this DIT content
-   * rule.
-   * 
-   * @return The set of prohibited attributes for this DIT content rule.
+   * Returns an unmodifiable set containing the prohibited attributes for this
+   * DIT content rule.
+   *
+   * @return An unmodifiable set containing the prohibited attributes for this
+   *         DIT content rule.
    */
-  public Iterable<AttributeType> getProhibitedAttributes()
+  public Set<AttributeType> getProhibitedAttributes()
   {
     return prohibitedAttributes;
   }
@@ -190,11 +189,13 @@
 
 
   /**
-   * Retrieves the set of required attributes for this DIT content rule.
-   * 
-   * @return The set of required attributes for this DIT content rule.
+   * Returns an unmodifiable set containing the required attributes for this DIT
+   * content rule.
+   *
+   * @return An unmodifiable set containing the required attributes for this DIT
+   *         content rule.
    */
-  public Iterable<AttributeType> getRequiredAttributes()
+  public Set<AttributeType> getRequiredAttributes()
   {
     return requiredAttributes;
   }
@@ -202,8 +203,8 @@
 
 
   /**
-   * Retrieves the structural objectclass for this DIT content rule.
-   * 
+   * Returns the structural objectclass for this DIT content rule.
+   *
    * @return The structural objectclass for this DIT content rule.
    */
   public ObjectClass getStructuralClass()
@@ -214,8 +215,8 @@
 
 
   /**
-   * Retrieves the structural class OID for this schema definition.
-   * 
+   * Returns the structural class OID for this schema definition.
+   *
    * @return The structural class OID for this schema definition.
    */
   public String getStructuralClassOID()
@@ -235,13 +236,13 @@
 
   /**
    * Indicates whether this schema definition has the specified name.
-   * 
+   *
    * @param name
    *          The name for which to make the determination.
-   * @return <code>true</code> if the specified name is assigned to this
-   *         schema definition, or <code>false</code> if not.
+   * @return <code>true</code> if the specified name is assigned to this schema
+   *         definition, or <code>false</code> if not.
    */
-  public boolean hasName(String name)
+  public boolean hasName(final String name)
   {
     for (final String n : names)
     {
@@ -258,14 +259,14 @@
   /**
    * Indicates whether this schema definition has the specified name or
    * structural class OID.
-   * 
+   *
    * @param value
    *          The value for which to make the determination.
-   * @return <code>true</code> if the provided value matches the OID or
-   *         one of the names assigned to this schema definition, or
-   *         <code>false</code> if not.
+   * @return <code>true</code> if the provided value matches the OID or one of
+   *         the names assigned to this schema definition, or <code>false</code>
+   *         if not.
    */
-  public boolean hasNameOrOID(String value)
+  public boolean hasNameOrOID(final String value)
   {
     return hasName(value) || structuralClassOID.equals(value);
   }
@@ -274,9 +275,9 @@
 
   /**
    * Indicates whether this schema definition is declared "obsolete".
-   * 
-   * @return <code>true</code> if this schema definition is declared
-   *         "obsolete", or <code>false</code> if not.
+   *
+   * @return <code>true</code> if this schema definition is declared "obsolete",
+   *         or <code>false</code> if not.
    */
   public boolean isObsolete()
   {
@@ -286,11 +287,11 @@
 
 
   /**
-   * Retrieves the string representation of this schema definition in
-   * the form specified in RFC 2252.
-   * 
-   * @return The string representation of this schema definition in the
-   *         form specified in RFC 2252.
+   * Returns the string representation of this schema definition in the form
+   * specified in RFC 2252.
+   *
+   * @return The string representation of this schema definition in the form
+   *         specified in RFC 2252.
    */
   @Override
   public String toString()
@@ -304,14 +305,14 @@
   {
     return new DITContentRule(structuralClassOID, names, description,
         isObsolete, auxiliaryClassOIDs, optionalAttributeOIDs,
-        prohibitedAttributeOIDs, requiredAttributeOIDs,
-        extraProperties, definition);
+        prohibitedAttributeOIDs, requiredAttributeOIDs, extraProperties,
+        definition);
   }
 
 
 
   @Override
-  void toStringContent(StringBuilder buffer)
+  void toStringContent(final StringBuilder buffer)
   {
     buffer.append(structuralClassOID);
 
@@ -380,8 +381,7 @@
 
     if (!requiredAttributeOIDs.isEmpty())
     {
-      final Iterator<String> iterator =
-          requiredAttributeOIDs.iterator();
+      final Iterator<String> iterator = requiredAttributeOIDs.iterator();
 
       final String firstName = iterator.next();
       if (iterator.hasNext())
@@ -406,8 +406,7 @@
 
     if (!optionalAttributeOIDs.isEmpty())
     {
-      final Iterator<String> iterator =
-          optionalAttributeOIDs.iterator();
+      final Iterator<String> iterator = optionalAttributeOIDs.iterator();
 
       final String firstName = iterator.next();
       if (iterator.hasNext())
@@ -432,8 +431,7 @@
 
     if (!prohibitedAttributeOIDs.isEmpty())
     {
-      final Iterator<String> iterator =
-          prohibitedAttributeOIDs.iterator();
+      final Iterator<String> iterator = prohibitedAttributeOIDs.iterator();
 
       final String firstName = iterator.next();
       if (iterator.hasNext())
@@ -460,7 +458,7 @@
 
 
   @Override
-  void validate(List<LocalizableMessage> warnings, Schema schema)
+  void validate(final List<LocalizableMessage> warnings, final Schema schema)
       throws SchemaException
   {
     // Get the objectclass with the specified OID. If it does not exist
@@ -473,26 +471,23 @@
       }
       catch (final UnknownSchemaElementException e)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_DCR_UNKNOWN_STRUCTURAL_CLASS.get(
-                definition, structuralClassOID);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_UNKNOWN_STRUCTURAL_CLASS
+            .get(definition, structuralClassOID);
         throw new SchemaException(message, e);
       }
       if (structuralClass.getObjectClassType() != ObjectClassType.STRUCTURAL)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_DCR_STRUCTURAL_CLASS_NOT_STRUCTURAL.get(
-                definition, structuralClass.getOID(), structuralClass
-                    .getNameOrOID(), structuralClass
-                    .getObjectClassType().toString());
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_STRUCTURAL_CLASS_NOT_STRUCTURAL
+            .get(definition, structuralClass.getOID(), structuralClass
+                .getNameOrOID(), structuralClass.getObjectClassType()
+                .toString());
         warnings.add(message);
       }
     }
 
     if (!auxiliaryClassOIDs.isEmpty())
     {
-      auxiliaryClasses =
-          new HashSet<ObjectClass>(auxiliaryClassOIDs.size());
+      auxiliaryClasses = new HashSet<ObjectClass>(auxiliaryClassOIDs.size());
       ObjectClass objectClass;
       for (final String oid : auxiliaryClassOIDs)
       {
@@ -503,18 +498,16 @@
         catch (final UnknownSchemaElementException e)
         {
           // This isn't good because it is an unknown auxiliary class.
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_DCR_UNKNOWN_AUXILIARY_CLASS.get(
-                  definition, oid);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_UNKNOWN_AUXILIARY_CLASS
+              .get(definition, oid);
           throw new SchemaException(message, e);
         }
         if (objectClass.getObjectClassType() != ObjectClassType.AUXILIARY)
         {
           // This isn't good because it isn't an auxiliary class.
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_DCR_AUXILIARY_CLASS_NOT_AUXILIARY.get(
-                  definition, structuralClass.getOID(), structuralClass
-                      .getObjectClassType().toString());
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_AUXILIARY_CLASS_NOT_AUXILIARY
+              .get(definition, structuralClass.getOID(), structuralClass
+                  .getObjectClassType().toString());
           throw new SchemaException(message);
         }
         auxiliaryClasses.add(objectClass);
@@ -523,8 +516,8 @@
 
     if (!requiredAttributeOIDs.isEmpty())
     {
-      requiredAttributes =
-          new HashSet<AttributeType>(requiredAttributeOIDs.size());
+      requiredAttributes = new HashSet<AttributeType>(requiredAttributeOIDs
+          .size());
       AttributeType attributeType;
       for (final String oid : requiredAttributeOIDs)
       {
@@ -537,9 +530,8 @@
           // This isn't good because it means that the DIT content rule
           // requires an attribute type that we don't know anything
           // about.
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_DCR_UNKNOWN_REQUIRED_ATTR.get(definition,
-                  oid);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_UNKNOWN_REQUIRED_ATTR
+              .get(definition, oid);
           throw new SchemaException(message, e);
         }
         requiredAttributes.add(attributeType);
@@ -548,8 +540,8 @@
 
     if (!optionalAttributeOIDs.isEmpty())
     {
-      optionalAttributes =
-          new HashSet<AttributeType>(optionalAttributeOIDs.size());
+      optionalAttributes = new HashSet<AttributeType>(optionalAttributeOIDs
+          .size());
       AttributeType attributeType;
       for (final String oid : optionalAttributeOIDs)
       {
@@ -562,9 +554,8 @@
           // This isn't good because it means that the DIT content rule
           // requires an attribute type that we don't know anything
           // about.
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_DCR_UNKNOWN_OPTIONAL_ATTR.get(definition,
-                  oid);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_UNKNOWN_OPTIONAL_ATTR
+              .get(definition, oid);
           throw new SchemaException(message, e);
         }
         optionalAttributes.add(attributeType);
@@ -573,8 +564,8 @@
 
     if (!prohibitedAttributeOIDs.isEmpty())
     {
-      prohibitedAttributes =
-          new HashSet<AttributeType>(prohibitedAttributeOIDs.size());
+      prohibitedAttributes = new HashSet<AttributeType>(prohibitedAttributeOIDs
+          .size());
       AttributeType attributeType;
       for (final String oid : prohibitedAttributeOIDs)
       {
@@ -587,9 +578,8 @@
           // This isn't good because it means that the DIT content rule
           // requires an attribute type that we don't know anything
           // about.
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_DCR_UNKNOWN_PROHIBITED_ATTR.get(
-                  definition, oid);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_UNKNOWN_PROHIBITED_ATTR
+              .get(definition, oid);
           throw new SchemaException(message, e);
         }
         prohibitedAttributes.add(attributeType);
@@ -602,10 +592,8 @@
     {
       if (structuralClass.isRequired(t))
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_DCR_PROHIBITED_REQUIRED_BY_STRUCTURAL.get(
-                definition, t.getNameOrOID(), structuralClass
-                    .getNameOrOID());
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_PROHIBITED_REQUIRED_BY_STRUCTURAL
+            .get(definition, t.getNameOrOID(), structuralClass.getNameOrOID());
         throw new SchemaException(message);
       }
 
@@ -613,12 +601,16 @@
       {
         if (oc.isRequired(t))
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_DCR_PROHIBITED_REQUIRED_BY_AUXILIARY.get(
-                  definition, t.getNameOrOID(), oc.getNameOrOID());
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_PROHIBITED_REQUIRED_BY_AUXILIARY
+              .get(definition, t.getNameOrOID(), oc.getNameOrOID());
           throw new SchemaException(message);
         }
       }
     }
+
+    auxiliaryClasses = Collections.unmodifiableSet(auxiliaryClasses);
+    optionalAttributes = Collections.unmodifiableSet(optionalAttributes);
+    prohibitedAttributes = Collections.unmodifiableSet(prohibitedAttributes);
+    requiredAttributes = Collections.unmodifiableSet(requiredAttributes);
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/DITContentRuleSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/DITContentRuleSyntaxImpl.java
index 2c77929..6d892bb 100644
--- a/sdk/src/org/opends/sdk/schema/DITContentRuleSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/DITContentRuleSyntaxImpl.java
@@ -29,8 +29,11 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_DCR_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_DCR_EXPECTED_OPEN_PARENTHESIS;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_ILLEGAL_TOKEN;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OID_FIRST_COMPONENT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_DIT_CONTENT_RULE_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DecodeException;
@@ -43,9 +46,9 @@
 
 
 /**
- * This class implements the DIT content rule description syntax, which
- * is used to hold DIT content rule definitions in the server schema.
- * The format of this syntax is defined in RFC 2252.
+ * This class implements the DIT content rule description syntax, which is used
+ * to hold DIT content rule definitions in the server schema. The format of this
+ * syntax is defined in RFC 2252.
  */
 final class DITContentRuleSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -75,8 +78,8 @@
   /**
    * {@inheritDoc}
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We'll use the decodeDITContentRule method to determine if the
     // value is acceptable.
@@ -93,7 +96,8 @@
       {
         // This means that the value was empty or contained only
         // whitespace. That is illegal.
-        final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_EMPTY_VALUE.get();
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_EMPTY_VALUE
+            .get();
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("DITConentRuleSyntax",
             "valueIsAcceptable", e);
@@ -105,9 +109,8 @@
       final char c = reader.read();
       if (c != '(')
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_DCR_EXPECTED_OPEN_PARENTHESIS.get(
-                definition, (reader.pos() - 1), String.valueOf(c));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DCR_EXPECTED_OPEN_PARENTHESIS
+            .get(definition, (reader.pos() - 1), String.valueOf(c));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("DITContentRuleSyntax",
             "valueIsAcceptable", e);
@@ -182,8 +185,8 @@
         }
         else
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
+              .get(tokenName);
           final DecodeException e = DecodeException.error(message);
           StaticUtils.DEBUG_LOG.throwing("DITContentRuleSyntax",
               "valueIsAcceptable", e);
diff --git a/sdk/src/org/opends/sdk/schema/DITStructureRule.java b/sdk/src/org/opends/sdk/schema/DITStructureRule.java
index 5761a50..2f35eac 100644
--- a/sdk/src/org/opends/sdk/schema/DITStructureRule.java
+++ b/sdk/src/org/opends/sdk/schema/DITStructureRule.java
@@ -29,7 +29,8 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_DSR_UNKNOWN_NAME_FORM;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_DSR_UNKNOWN_RULE_ID;
 
 import java.util.*;
 
@@ -40,8 +41,8 @@
 
 
 /**
- * This class defines a DIT structure rule, which is used to indicate
- * the types of children that entries may have.
+ * This class defines a DIT structure rule, which is used to indicate the types
+ * of children that entries may have.
  */
 public final class DITStructureRule extends SchemaElement
 {
@@ -68,10 +69,10 @@
 
 
 
-  DITStructureRule(Integer ruleID, List<String> names,
-      String description, boolean obsolete, String nameFormOID,
-      Set<Integer> superiorRuleIDs,
-      Map<String, List<String>> extraProperties, String definition)
+  DITStructureRule(final Integer ruleID, final List<String> names,
+      final String description, final boolean obsolete,
+      final String nameFormOID, final Set<Integer> superiorRuleIDs,
+      final Map<String, List<String>> extraProperties, final String definition)
   {
     super(description, extraProperties);
 
@@ -96,7 +97,7 @@
 
   /**
    * Retrieves the name form for this DIT structure rule.
-   * 
+   *
    * @return The name form for this DIT structure rule.
    */
   public NameForm getNameForm()
@@ -107,10 +108,10 @@
 
 
   /**
-   * Retrieves the name or rule ID for this schema definition. If it has
-   * one or more names, then the primary name will be returned. If it
-   * does not have any names, then the OID will be returned.
-   * 
+   * Retrieves the name or rule ID for this schema definition. If it has one or
+   * more names, then the primary name will be returned. If it does not have any
+   * names, then the OID will be returned.
+   *
    * @return The name or OID for this schema definition.
    */
   public String getNameOrRuleID()
@@ -125,13 +126,13 @@
 
 
   /**
-   * Retrieves an iterable over the set of user-defined names that may
-   * be used to reference this schema definition.
-   * 
-   * @return Returns an iterable over the set of user-defined names that
+   * Returns an unmodifiable list containing the user-defined names that may be
+   * used to reference this schema definition.
+   *
+   * @return Returns an unmodifiable list containing the user-defined names that
    *         may be used to reference this schema definition.
    */
-  public Iterable<String> getNames()
+  public List<String> getNames()
   {
     return names;
   }
@@ -140,7 +141,7 @@
 
   /**
    * Retrieves the rule ID for this DIT structure rule.
-   * 
+   *
    * @return The rule ID for this DIT structure rule.
    */
   public Integer getRuleID()
@@ -151,11 +152,13 @@
 
 
   /**
-   * Retrieves the set of superior rules for this DIT structure rule.
-   * 
-   * @return The set of superior rules for this DIT structure rule.
+   * Returns an unmodifiable set containing the superior rules for this DIT
+   * structure rule.
+   *
+   * @return An unmodifiable set containing the superior rules for this DIT
+   *         structure rule.
    */
-  public Iterable<DITStructureRule> getSuperiorRules()
+  public Set<DITStructureRule> getSuperiorRules()
   {
     return superiorRules;
   }
@@ -172,13 +175,13 @@
 
   /**
    * Indicates whether this schema definition has the specified name.
-   * 
+   *
    * @param name
    *          The name for which to make the determination.
-   * @return <code>true</code> if the specified name is assigned to this
-   *         schema definition, or <code>false</code> if not.
+   * @return <code>true</code> if the specified name is assigned to this schema
+   *         definition, or <code>false</code> if not.
    */
-  public boolean hasName(String name)
+  public boolean hasName(final String name)
   {
     for (final String n : names)
     {
@@ -194,9 +197,9 @@
 
   /**
    * Indicates whether this schema definition is declared "obsolete".
-   * 
-   * @return <code>true</code> if this schema definition is declared
-   *         "obsolete", or <code>false</code> if not.
+   *
+   * @return <code>true</code> if this schema definition is declared "obsolete",
+   *         or <code>false</code> if not.
    */
   public boolean isObsolete()
   {
@@ -206,11 +209,11 @@
 
 
   /**
-   * Retrieves the string representation of this schema definition in
-   * the form specified in RFC 2252.
-   * 
-   * @return The string representation of this schema definition in the
-   *         form specified in RFC 2252.
+   * Retrieves the string representation of this schema definition in the form
+   * specified in RFC 2252.
+   *
+   * @return The string representation of this schema definition in the form
+   *         specified in RFC 2252.
    */
   @Override
   public String toString()
@@ -229,7 +232,7 @@
 
 
   @Override
-  void toStringContent(StringBuilder buffer)
+  void toStringContent(final StringBuilder buffer)
   {
     buffer.append(ruleID);
 
@@ -303,7 +306,7 @@
 
 
   @Override
-  void validate(List<LocalizableMessage> warnings, Schema schema)
+  void validate(final List<LocalizableMessage> warnings, final Schema schema)
       throws SchemaException
   {
     try
@@ -312,16 +315,14 @@
     }
     catch (final UnknownSchemaElementException e)
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_DSR_UNKNOWN_NAME_FORM.get(definition,
-              nameFormOID);
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_UNKNOWN_NAME_FORM
+          .get(definition, nameFormOID);
       throw new SchemaException(message, e);
     }
 
     if (!superiorRuleIDs.isEmpty())
     {
-      superiorRules =
-          new HashSet<DITStructureRule>(superiorRuleIDs.size());
+      superiorRules = new HashSet<DITStructureRule>(superiorRuleIDs.size());
       DITStructureRule rule;
       for (final Integer id : superiorRuleIDs)
       {
@@ -331,12 +332,13 @@
         }
         catch (final UnknownSchemaElementException e)
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_DSR_UNKNOWN_RULE_ID.get(definition, id);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_UNKNOWN_RULE_ID
+              .get(definition, id);
           throw new SchemaException(message, e);
         }
         superiorRules.add(rule);
       }
     }
+    superiorRules = Collections.unmodifiableSet(superiorRules);
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/DITStructureRuleSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/DITStructureRuleSyntaxImpl.java
index 5246ce6..4100f6c 100644
--- a/sdk/src/org/opends/sdk/schema/DITStructureRuleSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/DITStructureRuleSyntaxImpl.java
@@ -29,8 +29,12 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_DSR_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_DSR_EXPECTED_OPEN_PARENTHESIS;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_DSR_NO_NAME_FORM;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_ILLEGAL_TOKEN;
+import static org.opends.sdk.schema.SchemaConstants.EMR_INTEGER_FIRST_COMPONENT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_DIT_STRUCTURE_RULE_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DecodeException;
@@ -43,9 +47,9 @@
 
 
 /**
- * This class implements the DIT structure rule description syntax,
- * which is used to hold DIT structure rule definitions in the server
- * schema. The format of this syntax is defined in RFC 2252.
+ * This class implements the DIT structure rule description syntax, which is
+ * used to hold DIT structure rule definitions in the server schema. The format
+ * of this syntax is defined in RFC 2252.
  */
 final class DITStructureRuleSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -72,8 +76,8 @@
 
 
 
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We'll use the decodeDITStructureRule method to determine if the
     // value is acceptable.
@@ -90,7 +94,8 @@
       {
         // This means that the value was empty or contained only
         // whitespace. That is illegal.
-        final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_EMPTY_VALUE.get();
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_EMPTY_VALUE
+            .get();
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("DITStructureRuleSyntax",
             "valueIsAcceptable", e);
@@ -102,9 +107,8 @@
       final char c = reader.read();
       if (c != '(')
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_DSR_EXPECTED_OPEN_PARENTHESIS.get(
-                definition, (reader.pos() - 1), String.valueOf(c));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_EXPECTED_OPEN_PARENTHESIS
+            .get(definition, (reader.pos() - 1), String.valueOf(c));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("DITStructureRuleSyntax",
             "valueIsAcceptable", e);
@@ -173,8 +177,8 @@
         }
         else
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
+              .get(tokenName);
           final DecodeException e = DecodeException.error(message);
           StaticUtils.DEBUG_LOG.throwing("DITStructureRuleSyntax",
               "valueIsAcceptable", e);
@@ -184,8 +188,8 @@
 
       if (nameForm == null)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_DSR_NO_NAME_FORM.get(definition);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_DSR_NO_NAME_FORM
+            .get(definition);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("DITStructureRuleSyntax",
             "valueIsAcceptable", e);
diff --git a/sdk/src/org/opends/sdk/schema/DeliveryMethodSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/DeliveryMethodSyntaxImpl.java
index 0eb0e27..bb621a9 100644
--- a/sdk/src/org/opends/sdk/schema/DeliveryMethodSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/DeliveryMethodSyntaxImpl.java
@@ -29,8 +29,9 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_DELIVERY_METHOD_INVALID_ELEMENT;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_DELIVERY_METHOD_NO_ELEMENTS;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
 import static org.opends.sdk.schema.SchemaConstants.*;
 
 import java.util.HashSet;
@@ -41,12 +42,11 @@
 
 
 
-
 /**
- * This class defines the delivery method attribute syntax. This
- * contains one or more of a fixed set of values. If there are multiple
- * values, then they are separated by spaces with a dollar sign between
- * them. The allowed values include:
+ * This class defines the delivery method attribute syntax. This contains one or
+ * more of a fixed set of values. If there are multiple values, then they are
+ * separated by spaces with a dollar sign between them. The allowed values
+ * include:
  * <UL>
  * <LI>any</LI>
  * <LI>mhs</LI>
@@ -65,8 +65,7 @@
   /**
    * The set of values that may be used as delivery methods.
    */
-  private static final HashSet<String> ALLOWED_VALUES =
-      new HashSet<String>();
+  private static final HashSet<String> ALLOWED_VALUES = new HashSet<String>();
   {
     ALLOWED_VALUES.add("any");
     ALLOWED_VALUES.add("mhs");
@@ -129,25 +128,24 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     final String stringValue = toLowerCase(value.toString());
-    final StringTokenizer tokenizer =
-        new StringTokenizer(stringValue, " $");
+    final StringTokenizer tokenizer = new StringTokenizer(stringValue, " $");
     if (!tokenizer.hasMoreTokens())
     {
       invalidReason.append(ERR_ATTR_SYNTAX_DELIVERY_METHOD_NO_ELEMENTS
@@ -160,9 +158,8 @@
       final String token = tokenizer.nextToken();
       if (!ALLOWED_VALUES.contains(token))
       {
-        invalidReason
-            .append(ERR_ATTR_SYNTAX_DELIVERY_METHOD_INVALID_ELEMENT
-                .get(value.toString(), token));
+        invalidReason.append(ERR_ATTR_SYNTAX_DELIVERY_METHOD_INVALID_ELEMENT
+            .get(value.toString(), token));
         return false;
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java
index 1972726..e601b54 100644
--- a/sdk/src/org/opends/sdk/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java
@@ -28,8 +28,11 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_EXPECTED_OPEN_PARENTHESIS;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.*;
 
@@ -38,19 +41,18 @@
 
 
 /**
- * This class implements the directoryStringFirstComponentMatch matching
- * rule defined in X.520 and referenced in RFC 2252. This rule is
- * intended for use with attributes whose values contain a set of
- * parentheses enclosing a space-delimited set of names and/or
- * name-value pairs (like attribute type or objectclass descriptions) in
- * which the "first component" is the first item after the opening
- * parenthesis.
+ * This class implements the directoryStringFirstComponentMatch matching rule
+ * defined in X.520 and referenced in RFC 2252. This rule is intended for use
+ * with attributes whose values contain a set of parentheses enclosing a
+ * space-delimited set of names and/or name-value pairs (like attribute type or
+ * objectclass descriptions) in which the "first component" is the first item
+ * after the opening parenthesis.
  */
-final class DirectoryStringFirstComponentEqualityMatchingRuleImpl
-    extends AbstractMatchingRuleImpl
+final class DirectoryStringFirstComponentEqualityMatchingRuleImpl extends
+    AbstractMatchingRuleImpl
 {
   @Override
-  public Assertion getAssertion(Schema schema, ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, CASE_FOLD);
@@ -62,8 +64,7 @@
       {
         // This should only happen if the value is composed entirely of
         // spaces. In that case, the normalized value is a single space.
-        return new DefaultEqualityAssertion(
-            SchemaConstants.SINGLE_SPACE_VALUE);
+        return new DefaultEqualityAssertion(SchemaConstants.SINGLE_SPACE_VALUE);
       }
       else
       {
@@ -84,14 +85,13 @@
       }
     }
 
-    return new DefaultEqualityAssertion(ByteString.valueOf(buffer
-        .toString()));
+    return new DefaultEqualityAssertion(ByteString.valueOf(buffer.toString()));
   }
 
 
 
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     final String definition = value.toString();
     final SubstringReader reader = new SubstringReader(definition);
@@ -115,9 +115,8 @@
     final char c = reader.read();
     if (c != '(')
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_EXPECTED_OPEN_PARENTHESIS.get(definition,
-              (reader.pos() - 1), String.valueOf(c));
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_EXPECTED_OPEN_PARENTHESIS
+          .get(definition, (reader.pos() - 1), String.valueOf(c));
       throw DecodeException.error(message);
     }
 
diff --git a/sdk/src/org/opends/sdk/schema/DirectoryStringSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/DirectoryStringSyntaxImpl.java
index 20e67d9..e971310 100644
--- a/sdk/src/org/opends/sdk/schema/DirectoryStringSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/DirectoryStringSyntaxImpl.java
@@ -29,7 +29,8 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_DIRECTORYSTRING_INVALID_ZEROLENGTH_VALUE;
 import static org.opends.sdk.schema.SchemaConstants.*;
 
 import org.opends.sdk.ByteSequence;
@@ -37,12 +38,11 @@
 
 
 
-
 /**
- * This class defines the directory string attribute syntax, which is
- * simply a set of UTF-8 characters. By default, they will be treated in
- * a case-insensitive manner, and equality, ordering, substring, and
- * approximate matching will be allowed.
+ * This class defines the directory string attribute syntax, which is simply a
+ * set of UTF-8 characters. By default, they will be treated in a
+ * case-insensitive manner, and equality, ordering, substring, and approximate
+ * matching will be allowed.
  */
 final class DirectoryStringSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -93,21 +93,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     if (value.length() > 0
         || schema.getSchemaCompatOptions()
diff --git a/sdk/src/org/opends/sdk/schema/DistinguishedNameEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/DistinguishedNameEqualityMatchingRuleImpl.java
index fe252e4..83ae0ca 100644
--- a/sdk/src/org/opends/sdk/schema/DistinguishedNameEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/DistinguishedNameEqualityMatchingRuleImpl.java
@@ -32,21 +32,19 @@
 import java.util.Comparator;
 
 import org.opends.sdk.*;
-import org.opends.sdk.RDN.AVA;
-
 
 
 
 /**
- * This class defines the distinguishedNameMatch matching rule defined
- * in X.520 and referenced in RFC 2252.
+ * This class defines the distinguishedNameMatch matching rule defined in X.520
+ * and referenced in RFC 2252.
  */
 final class DistinguishedNameEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
   private static final Comparator<AVA> ATV_COMPARATOR = new Comparator<AVA>()
   {
-    public int compare(AVA o1, AVA o2)
+    public int compare(final AVA o1, final AVA o2)
     {
       return o1.getAttributeType().compareTo(o2.getAttributeType());
     }
@@ -55,7 +53,7 @@
 
 
   @Override
-  public Assertion getAssertion(final Schema schema, ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     DN assertion;
@@ -71,12 +69,11 @@
     final DN finalAssertion = assertion;
     return new Assertion()
     {
-      public ConditionResult matches(ByteSequence attributeValue)
+      public ConditionResult matches(final ByteSequence attributeValue)
       {
         try
         {
-          final DN attribute = DN.valueOf(attributeValue.toString(),
-              schema);
+          final DN attribute = DN.valueOf(attributeValue.toString(), schema);
           return matchDNs(finalAssertion, attribute);
         }
         catch (final LocalizedIllegalArgumentException e)
@@ -89,8 +86,8 @@
 
 
 
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     try
     {
@@ -105,7 +102,7 @@
 
 
 
-  private ConditionResult matchAVAs(AVA ava1, AVA ava2)
+  private ConditionResult matchAVAs(final AVA ava1, final AVA ava2)
   {
     final AttributeType type = ava1.getAttributeType();
 
@@ -119,12 +116,11 @@
     {
       try
       {
-        final ByteString nv1 = matchingRule
-            .normalizeAttributeValue(ava1.getAttributeValue());
-        final ByteString nv2 = matchingRule
-            .normalizeAttributeValue(ava2.getAttributeValue());
-        return nv1.equals(nv2) ? ConditionResult.TRUE
-            : ConditionResult.FALSE;
+        final ByteString nv1 = matchingRule.normalizeAttributeValue(ava1
+            .getAttributeValue());
+        final ByteString nv2 = matchingRule.normalizeAttributeValue(ava2
+            .getAttributeValue());
+        return nv1.equals(nv2) ? ConditionResult.TRUE : ConditionResult.FALSE;
       }
       catch (final DecodeException de)
       {
@@ -137,7 +133,7 @@
 
 
 
-  private ConditionResult matchDNs(DN dn1, DN dn2)
+  private ConditionResult matchDNs(final DN dn1, final DN dn2)
   {
     final int sz1 = dn1.size();
     final int sz2 = dn2.size();
@@ -164,7 +160,7 @@
 
 
 
-  private ConditionResult matchRDNs(RDN rdn1, RDN rdn2)
+  private ConditionResult matchRDNs(final RDN rdn1, final RDN rdn2)
   {
     final int sz1 = rdn1.size();
     final int sz2 = rdn2.size();
diff --git a/sdk/src/org/opends/sdk/schema/DistinguishedNameSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/DistinguishedNameSyntaxImpl.java
index d3eb04d..5b80627 100644
--- a/sdk/src/org/opends/sdk/schema/DistinguishedNameSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/DistinguishedNameSyntaxImpl.java
@@ -29,20 +29,21 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_DN_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_DN_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DN;
-import org.opends.sdk.LocalizedIllegalArgumentException;
 import org.opends.sdk.LocalizableMessageBuilder;
-
+import org.opends.sdk.LocalizedIllegalArgumentException;
 
 
 
 /**
- * This class defines the distinguished name attribute syntax, which is
- * used for attributes that hold distinguished names (DNs). Equality and
- * substring matching will be allowed by default.
+ * This class defines the distinguished name attribute syntax, which is used for
+ * attributes that hold distinguished names (DNs). Equality and substring
+ * matching will be allowed by default.
  */
 final class DistinguishedNameSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -76,8 +77,8 @@
 
 
 
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     try
     {
diff --git a/sdk/src/org/opends/sdk/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java
index 875b0f5..f047a4e 100644
--- a/sdk/src/org/opends/sdk/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java
@@ -36,24 +36,22 @@
 
 
 /**
- * This class defines an approximate matching rule based on the Double
- * Metaphone algorithm. The Metaphone and Double Metaphone algorithms
- * were originally devised by Lawrence Philips (published in the
- * December 1990 issue of <I>Computer Language</I> and the <A
- * HREF="http://www.cuj.com/documents/s=8038/cuj0006philips/">June 2000
- * issue of <I>C/C++ Users Journal</I></A>, respectively), and this
- * version of the algorithm is based on a version modified by Kevin
- * Atkinson to include bugfixes and additional functionality (source is
- * available <A HREF="http://aspell.net/metaphone/dmetaph.cpp">here</A>
- * and additional Metaphone and Double Metaphone information is
- * available at <A
- * HREF="http://aspell.net/metaphone/">http://aspell.net/
- * metaphone/</A>). This implementation is largely the same as the one
- * provided by Kevin Atkinson, but it has been re-written for better
- * readability, for more efficiency, to get rid of checks for conditions
- * that can't possibly happen, and to get rid of redundant checks that
- * aren't needed. It has also been updated to always only generate a
- * single value rather than one or possibly two values.
+ * This class defines an approximate matching rule based on the Double Metaphone
+ * algorithm. The Metaphone and Double Metaphone algorithms were originally
+ * devised by Lawrence Philips (published in the December 1990 issue of
+ * <I>Computer Language</I> and the <A
+ * HREF="http://www.cuj.com/documents/s=8038/cuj0006philips/">June 2000 issue of
+ * <I>C/C++ Users Journal</I></A>, respectively), and this version of the
+ * algorithm is based on a version modified by Kevin Atkinson to include
+ * bugfixes and additional functionality (source is available <A
+ * HREF="http://aspell.net/metaphone/dmetaph.cpp">here</A> and additional
+ * Metaphone and Double Metaphone information is available at <A
+ * HREF="http://aspell.net/metaphone/">http://aspell.net/ metaphone/</A>). This
+ * implementation is largely the same as the one provided by Kevin Atkinson, but
+ * it has been re-written for better readability, for more efficiency, to get
+ * rid of checks for conditions that can't possibly happen, and to get rid of
+ * redundant checks that aren't needed. It has also been updated to always only
+ * generate a single value rather than one or possibly two values.
  */
 final class DoubleMetaphoneApproximateMatchingRuleImpl extends
     AbstractMatchingRuleImpl
@@ -62,8 +60,8 @@
   /**
    * {@inheritDoc}
    */
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     String valueString = value.toString();
     final int length = valueString.length();
@@ -214,10 +212,10 @@
               || (pos == 0
                   || (posMinusOne = valueString.charAt(pos - 1)) == 'A'
                   || posMinusOne == 'O' || posMinusOne == 'U' || posMinusOne == 'E')
-              && (posPlusTwo == 'L' || posPlusTwo == 'R'
-                  || posPlusTwo == 'N' || posPlusTwo == 'M'
-                  || posPlusTwo == 'B' || posPlusTwo == 'H'
-                  || posPlusTwo == 'F' || posPlusTwo == 'V' || posPlusTwo == 'W'))
+              && (posPlusTwo == 'L' || posPlusTwo == 'R' || posPlusTwo == 'N'
+                  || posPlusTwo == 'M' || posPlusTwo == 'B'
+                  || posPlusTwo == 'H' || posPlusTwo == 'F'
+                  || posPlusTwo == 'V' || posPlusTwo == 'W'))
           {
             metaphone.append("K");
             pos += 2;
@@ -246,8 +244,7 @@
         }
 
         // Check for "CZ" as in "czerny" but not "wicz" and map to 'S'.
-        if (posPlusOne == 'Z'
-            && !hasSubstring(valueString, pos - 2, "WI"))
+        if (posPlusOne == 'Z' && !hasSubstring(valueString, pos - 2, "WI"))
         {
           metaphone.append("S");
           pos += 2;
@@ -263,8 +260,7 @@
         }
 
         // Check for a double C but not in values that start with "McC"
-        if (posPlusOne == 'C'
-            && !(pos == 1 && valueString.charAt(0) == 'M'))
+        if (posPlusOne == 'C' && !(pos == 1 && valueString.charAt(0) == 'M'))
         {
           if (((posPlusTwo = valueString.charAt(pos + 2)) == 'I'
               || posPlusTwo == 'E' || posPlusTwo == 'H')
@@ -450,8 +446,7 @@
             if (pos > 2
                 && valueString.charAt(pos - 1) == 'U'
                 && ((posMinusThree = valueString.charAt(pos - 3)) == 'C'
-                    || posMinusThree == 'G'
-                    || posMinusThree == 'L'
+                    || posMinusThree == 'G' || posMinusThree == 'L'
                     || posMinusThree == 'R' || posMinusThree == 'T'))
             {
               // Words like laugh, McLaughlin, cough, rough are mapped
@@ -524,8 +519,7 @@
         posPlusTwo = valueString.charAt(pos + 2);
         if ((posPlusOne == 'E' && posPlusTwo == 'R' || posPlusOne == 'Y')
             && (posMinusOne = valueString.charAt(pos - 1)) != 'E'
-            && posMinusOne != 'I'
-            && !hasSubstring(valueString, 0, "DANGER")
+            && posMinusOne != 'I' && !hasSubstring(valueString, 0, "DANGER")
             && !hasSubstring(valueString, 0, "RANGER")
             && !hasSubstring(valueString, 0, "MANGER")
             && !hasSubstring(valueString, pos - 1, "RGY")
@@ -655,8 +649,7 @@
         }
         else if (hasSubstring(valueString, pos - 1, "UMB"))
         {
-          if (pos + 1 == last
-              || hasSubstring(valueString, pos + 2, "ER"))
+          if (pos + 1 == last || hasSubstring(valueString, pos + 2, "ER"))
           {
             pos++;
           }
@@ -789,8 +782,7 @@
         // Various combinations at the beginning of words will be mapped
         // to 'S'.
         if (pos == 0
-            && (posPlusOne == 'M' || posPlusOne == 'N'
-                || posPlusOne == 'L' || posPlusOne == 'W'))
+            && (posPlusOne == 'M' || posPlusOne == 'N' || posPlusOne == 'L' || posPlusOne == 'W'))
         {
           metaphone.append("S");
           pos++;
@@ -818,8 +810,7 @@
             break;
           }
 
-          if (posPlusTwo == 'I' || posPlusTwo == 'E'
-              || posPlusTwo == 'Y')
+          if (posPlusTwo == 'I' || posPlusTwo == 'E' || posPlusTwo == 'Y')
           {
             metaphone.append("S");
             pos += 3;
@@ -1003,21 +994,19 @@
   /**
    * Indicates whether the provided value has the given substring at the
    * specified position.
-   * 
+   *
    * @param value
    *          The value containing the range for which to make the
    *          determination.
    * @param start
-   *          The position in the value at which to start the
-   *          comparison.
+   *          The position in the value at which to start the comparison.
    * @param substring
-   *          The substring to compare against the specified value
-   *          range.
-   * @return <CODE>true</CODE> if the specified portion of the value
-   *         matches the given substring, or <CODE>false</CODE> if it
-   *         does not.
+   *          The substring to compare against the specified value range.
+   * @return <CODE>true</CODE> if the specified portion of the value matches the
+   *         given substring, or <CODE>false</CODE> if it does not.
    */
-  private boolean hasSubstring(String value, int start, String substring)
+  private boolean hasSubstring(final String value, final int start,
+      final String substring)
   {
     try
     {
@@ -1048,8 +1037,8 @@
     }
     catch (final Exception e)
     {
-      StaticUtils.DEBUG_LOG.throwing(
-          "DoubleMetaphoneApproximateMatchingRule", "hasSubstring", e);
+      StaticUtils.DEBUG_LOG.throwing("DoubleMetaphoneApproximateMatchingRule",
+          "hasSubstring", e);
 
       return false;
     }
@@ -1058,31 +1047,30 @@
 
 
   /**
-   * Indicates whether the provided string appears Germanic (starts with
-   * "VAN ", "VON ", or "SCH").
-   * 
+   * Indicates whether the provided string appears Germanic (starts with "VAN ",
+   * "VON ", or "SCH").
+   *
    * @param s
    *          The string for which to make the determination.
-   * @return <CODE>true</CODE> if the provided string appears Germanic,
-   *         or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided string appears Germanic, or
+   *         <CODE>false</CODE> if not.
    */
-  private boolean isGermanic(String s)
+  private boolean isGermanic(final String s)
   {
-    return s.startsWith("VAN ") || s.startsWith("VON ")
-        || s.startsWith("SCH");
+    return s.startsWith("VAN ") || s.startsWith("VON ") || s.startsWith("SCH");
   }
 
 
 
   /**
    * Indicates whether the provided string appears to be Slavo-Germanic.
-   * 
+   *
    * @param s
    *          The string for which to make the determination.
    * @return <CODE>true</CODE> if the provided string appears to be
    *         Slavo-Germanic, or <CODE>false</CODE> if not.
    */
-  private boolean isSlavoGermanic(String s)
+  private boolean isSlavoGermanic(final String s)
   {
     return s.contains("W") || s.contains("K") || s.contains("CZ")
         || s.contains("WITZ");
@@ -1091,15 +1079,14 @@
 
 
   /**
-   * Indicates whether the provided character is a vowel (including
-   * "Y").
-   * 
+   * Indicates whether the provided character is a vowel (including "Y").
+   *
    * @param c
    *          The character for which to make the determination.
    * @return <CODE>true</CODE> if the provided character is a vowel, or
    *         <CODE>false</CODE> if not.
    */
-  private boolean isVowel(char c)
+  private boolean isVowel(final char c)
   {
     switch (c)
     {
diff --git a/sdk/src/org/opends/sdk/schema/EnhancedGuideSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/EnhancedGuideSyntaxImpl.java
index 9f9cd06..2a8914f 100644
--- a/sdk/src/org/opends/sdk/schema/EnhancedGuideSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/EnhancedGuideSyntaxImpl.java
@@ -30,8 +30,10 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_ENHANCED_GUIDE_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DecodeException;
@@ -42,9 +44,9 @@
 
 
 /**
- * This class implements the enhanced guide attribute syntax, which may
- * be used to provide criteria for generating search filters for entries
- * of a given objectclass.
+ * This class implements the enhanced guide attribute syntax, which may be used
+ * to provide criteria for generating search filters for entries of a given
+ * objectclass.
  */
 final class EnhancedGuideSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -79,21 +81,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // Get a lowercase string version of the provided value.
     final String valueStr = toLowerCase(value.toString());
@@ -104,8 +106,8 @@
     if (sharpPos < 0)
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_ENHANCEDGUIDE_NO_SHARP
-          .get(valueStr));
+      invalidReason
+          .append(ERR_ATTR_SYNTAX_ENHANCEDGUIDE_NO_SHARP.get(valueStr));
       return false;
     }
 
@@ -115,15 +117,13 @@
     if (ocLength == 0)
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_ENHANCEDGUIDE_NO_OC
-          .get(valueStr));
+      invalidReason.append(ERR_ATTR_SYNTAX_ENHANCEDGUIDE_NO_OC.get(valueStr));
       return false;
     }
 
     try
     {
-      SchemaUtils.readOID(new SubstringReader(ocName
-          .substring(ocLength)));
+      SchemaUtils.readOID(new SubstringReader(ocName.substring(ocLength)));
     }
     catch (final DecodeException de)
     {
@@ -156,9 +156,8 @@
       else
       {
 
-        invalidReason
-            .append(ERR_ATTR_SYNTAX_ENHANCEDGUIDE_INVALID_SCOPE.get(
-                valueStr, scopeStr));
+        invalidReason.append(ERR_ATTR_SYNTAX_ENHANCEDGUIDE_INVALID_SCOPE.get(
+            valueStr, scopeStr));
       }
 
       return false;
@@ -166,8 +165,8 @@
 
     // Everything between the two octothorpes must be the criteria. Make
     // sure it is valid.
-    final String criteria =
-        valueStr.substring(sharpPos + 1, lastSharpPos).trim();
+    final String criteria = valueStr.substring(sharpPos + 1, lastSharpPos)
+        .trim();
     final int criteriaLength = criteria.length();
     if (criteriaLength == 0)
     {
@@ -177,7 +176,6 @@
       return false;
     }
 
-    return GuideSyntaxImpl.criteriaIsValid(criteria, valueStr,
-        invalidReason);
+    return GuideSyntaxImpl.criteriaIsValid(criteria, valueStr, invalidReason);
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/EnumOrderingMatchingRule.java b/sdk/src/org/opends/sdk/schema/EnumOrderingMatchingRule.java
index ab0446a..3d1c62d 100644
--- a/sdk/src/org/opends/sdk/schema/EnumOrderingMatchingRule.java
+++ b/sdk/src/org/opends/sdk/schema/EnumOrderingMatchingRule.java
@@ -28,7 +28,7 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_LDAPSYNTAX_ENUM_INVALID_VALUE;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -39,18 +39,17 @@
 
 
 /**
- * This class is the ordering matching rule implementation for an enum
- * syntax implmentation. The ordering is determined by the order of the
- * entries in the X-ENUM extension value.
+ * This class is the ordering matching rule implementation for an enum syntax
+ * implmentation. The ordering is determined by the order of the entries in the
+ * X-ENUM extension value.
  */
-final class EnumOrderingMatchingRule extends
-    AbstractOrderingMatchingRuleImpl
+final class EnumOrderingMatchingRule extends AbstractOrderingMatchingRuleImpl
 {
   private final EnumSyntaxImpl syntax;
 
 
 
-  EnumOrderingMatchingRule(EnumSyntaxImpl syntax)
+  EnumOrderingMatchingRule(final EnumSyntaxImpl syntax)
   {
     Validator.ensureNotNull(syntax);
     this.syntax = syntax;
@@ -58,14 +57,14 @@
 
 
 
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     final int index = syntax.indexOf(value);
     if (index < 0)
     {
-      throw DecodeException.error(
-          WARN_ATTR_SYNTAX_LDAPSYNTAX_ENUM_INVALID_VALUE.get(value
+      throw DecodeException
+          .error(WARN_ATTR_SYNTAX_LDAPSYNTAX_ENUM_INVALID_VALUE.get(value
               .toString(), syntax.getName()));
     }
     return ByteString.valueOf(index);
diff --git a/sdk/src/org/opends/sdk/schema/EnumSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/EnumSyntaxImpl.java
index 693a4cc..69c2256 100644
--- a/sdk/src/org/opends/sdk/schema/EnumSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/EnumSyntaxImpl.java
@@ -29,9 +29,14 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_LDAPSYNTAX_ENUM_INVALID_VALUE;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
+import static org.opends.sdk.schema.SchemaConstants.AMR_DOUBLE_METAPHONE_OID;
+import static org.opends.sdk.schema.SchemaConstants.EMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OID_GENERIC_ENUM;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_OID;
 
 import java.util.ArrayList;
 import java.util.Collections;
@@ -47,9 +52,9 @@
 
 
 /**
- * This class provides an enumeration-based mechanism where a new syntax
- * and its corresponding matching rules can be created on-the-fly. An
- * enum syntax is an LDAPSyntaxDescriptionSyntax with X-ENUM extension.
+ * This class provides an enumeration-based mechanism where a new syntax and its
+ * corresponding matching rules can be created on-the-fly. An enum syntax is an
+ * LDAPSyntaxDescriptionSyntax with X-ENUM extension.
  */
 final class EnumSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -59,12 +64,11 @@
 
 
 
-  EnumSyntaxImpl(String oid, List<String> entries)
+  EnumSyntaxImpl(final String oid, final List<String> entries)
   {
     Validator.ensureNotNull(oid, entries);
     this.oid = oid;
-    final List<String> entryStrings =
-        new ArrayList<String>(entries.size());
+    final List<String> entryStrings = new ArrayList<String>(entries.size());
 
     for (final String entry : entries)
     {
@@ -87,13 +91,6 @@
 
 
 
-  public Iterable<String> getEntries()
-  {
-    return entries;
-  }
-
-
-
   @Override
   public String getEqualityMatchingRule()
   {
@@ -125,7 +122,7 @@
 
 
 
-  public int indexOf(ByteSequence value)
+  public int indexOf(final ByteSequence value)
   {
     return entries.indexOf(normalize(value));
   }
@@ -139,17 +136,16 @@
 
 
 
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // The value is acceptable if it belongs to the set.
     final boolean isAllowed = entries.contains(normalize(value));
 
     if (!isAllowed)
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_LDAPSYNTAX_ENUM_INVALID_VALUE.get(value
-              .toString(), oid);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_LDAPSYNTAX_ENUM_INVALID_VALUE
+          .get(value.toString(), oid);
       invalidReason.append(message);
     }
 
@@ -158,7 +154,7 @@
 
 
 
-  private String normalize(ByteSequence value)
+  private String normalize(final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/EqualLengthApproximateMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/EqualLengthApproximateMatchingRuleImpl.java
index f72ee01..f071f70 100644
--- a/sdk/src/org/opends/sdk/schema/EqualLengthApproximateMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/EqualLengthApproximateMatchingRuleImpl.java
@@ -33,20 +33,20 @@
 
 
 /**
- * This class implements an extremely simple approximate matching rule
- * that will consider two values approximately equal only if they have
- * the same length. It is intended purely for testing purposes.
+ * This class implements an extremely simple approximate matching rule that will
+ * consider two values approximately equal only if they have the same length. It
+ * is intended purely for testing purposes.
  */
 final class EqualLengthApproximateMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
   @Override
-  public Assertion getAssertion(Schema schema, final ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     return new Assertion()
     {
-      public ConditionResult matches(ByteSequence attributeValue)
+      public ConditionResult matches(final ByteSequence attributeValue)
       {
         return attributeValue.length() == value.length() ? ConditionResult.TRUE
             : ConditionResult.FALSE;
@@ -59,8 +59,8 @@
   /**
    * {@inheritDoc}
    */
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     return value.toByteString();
   }
diff --git a/sdk/src/org/opends/sdk/schema/FacsimileNumberSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/FacsimileNumberSyntaxImpl.java
index bda558e..ed8a331 100644
--- a/sdk/src/org/opends/sdk/schema/FacsimileNumberSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/FacsimileNumberSyntaxImpl.java
@@ -29,9 +29,15 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_FAXNUMBER_EMPTY;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_FAXNUMBER_END_WITH_DOLLAR;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_FAXNUMBER_ILLEGAL_PARAMETER;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_FAXNUMBER_NOT_PRINTABLE;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
+import static org.opends.sdk.schema.SchemaConstants.EMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_FAXNUMBER_NAME;
 
 import java.util.HashSet;
 
@@ -40,12 +46,11 @@
 
 
 
-
 /**
- * This class implements the facsimile telephone number attribute
- * syntax, which contains a printable string (the number) followed by
- * zero or more parameters. Those parameters should start with a dollar
- * sign may be any of the following strings:
+ * This class implements the facsimile telephone number attribute syntax, which
+ * contains a printable string (the number) followed by zero or more parameters.
+ * Those parameters should start with a dollar sign may be any of the following
+ * strings:
  * <UL>
  * <LI>twoDimensional</LI>
  * <LI>fineResolution</LI>
@@ -59,11 +64,11 @@
 final class FacsimileNumberSyntaxImpl extends AbstractSyntaxImpl
 {
   /**
-   * The set of allowed fax parameter values, formatted entirely in
-   * lowercase characters.
+   * The set of allowed fax parameter values, formatted entirely in lowercase
+   * characters.
    */
-  public static final HashSet<String> ALLOWED_FAX_PARAMETERS =
-      new HashSet<String>(7);
+  public static final HashSet<String> ALLOWED_FAX_PARAMETERS = new HashSet<String>(
+      7);
 
   static
   {
@@ -117,21 +122,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // Get a lowercase string representation of the value and find its
     // length.
@@ -173,8 +178,8 @@
         if (!PrintableStringSyntaxImpl.isPrintableCharacter(c))
         {
 
-          invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_NOT_PRINTABLE
-              .get(valueString, String.valueOf(c), pos));
+          invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_NOT_PRINTABLE.get(
+              valueString, String.valueOf(c), pos));
         }
       }
     }
@@ -204,14 +209,12 @@
       c = valueString.charAt(pos++);
       if (c == '$')
       {
-        final String paramStr =
-            valueString.substring(paramStartPos, pos);
+        final String paramStr = valueString.substring(paramStartPos, pos);
         if (!ALLOWED_FAX_PARAMETERS.contains(paramStr))
         {
 
-          invalidReason
-              .append(ERR_ATTR_SYNTAX_FAXNUMBER_ILLEGAL_PARAMETER.get(
-                  valueString, paramStr, paramStartPos, (pos - 1)));
+          invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_ILLEGAL_PARAMETER.get(
+              valueString, paramStr, paramStartPos, (pos - 1)));
           return false;
         }
 
@@ -224,8 +227,8 @@
     final String paramStr = valueString.substring(paramStartPos);
     if (!ALLOWED_FAX_PARAMETERS.contains(paramStr))
     {
-      invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_ILLEGAL_PARAMETER
-          .get(valueString, paramStr, paramStartPos, (pos - 1)));
+      invalidReason.append(ERR_ATTR_SYNTAX_FAXNUMBER_ILLEGAL_PARAMETER.get(
+          valueString, paramStr, paramStartPos, (pos - 1)));
       return false;
     }
 
diff --git a/sdk/src/org/opends/sdk/schema/FaxSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/FaxSyntaxImpl.java
index f39b962..5e08a5d 100644
--- a/sdk/src/org/opends/sdk/schema/FaxSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/FaxSyntaxImpl.java
@@ -29,19 +29,19 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_FAX_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the fax attribute syntax. This should be
- * restricted to holding only fax message contents, but we will accept
- * any set of bytes. It will be treated much like the octet string
- * attribute syntax.
+ * This class implements the fax attribute syntax. This should be restricted to
+ * holding only fax message contents, but we will accept any set of bytes. It
+ * will be treated much like the octet string attribute syntax.
  */
 final class FaxSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -77,21 +77,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // All values will be acceptable for the fax syntax.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/GeneralizedTimeEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/GeneralizedTimeEqualityMatchingRuleImpl.java
index 2cdf4a6..32ab6e1 100644
--- a/sdk/src/org/opends/sdk/schema/GeneralizedTimeEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/GeneralizedTimeEqualityMatchingRuleImpl.java
@@ -35,14 +35,14 @@
 
 
 /**
- * This class defines the generalizedTimeMatch matching rule defined in
- * X.520 and referenced in RFC 2252.
+ * This class defines the generalizedTimeMatch matching rule defined in X.520
+ * and referenced in RFC 2252.
  */
 final class GeneralizedTimeEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     return ByteString.valueOf(GeneralizedTimeSyntaxImpl
         .decodeGeneralizedTimeValue(value));
diff --git a/sdk/src/org/opends/sdk/schema/GeneralizedTimeOrderingMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/GeneralizedTimeOrderingMatchingRuleImpl.java
index b7e6c42..7b92d0b 100644
--- a/sdk/src/org/opends/sdk/schema/GeneralizedTimeOrderingMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/GeneralizedTimeOrderingMatchingRuleImpl.java
@@ -35,14 +35,14 @@
 
 
 /**
- * This class defines the generalizedTimeOrderingMatch matching rule
- * defined in X.520 and referenced in RFC 2252.
+ * This class defines the generalizedTimeOrderingMatch matching rule defined in
+ * X.520 and referenced in RFC 2252.
  */
 final class GeneralizedTimeOrderingMatchingRuleImpl extends
     AbstractOrderingMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     return ByteString.valueOf(GeneralizedTimeSyntaxImpl
         .decodeGeneralizedTimeValue(value));
diff --git a/sdk/src/org/opends/sdk/schema/GeneralizedTimeSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/GeneralizedTimeSyntaxImpl.java
index 643d365..08ea880 100644
--- a/sdk/src/org/opends/sdk/schema/GeneralizedTimeSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/GeneralizedTimeSyntaxImpl.java
@@ -46,34 +46,31 @@
 
 
 /**
- * This class implements the fax attribute syntax. This should be
- * restricted to holding only fax message contents, but we will accept
- * any set of bytes. It will be treated much like the octet string
- * attribute syntax.
+ * This class implements the fax attribute syntax. This should be restricted to
+ * holding only fax message contents, but we will accept any set of bytes. It
+ * will be treated much like the octet string attribute syntax.
  */
 final class GeneralizedTimeSyntaxImpl extends AbstractSyntaxImpl
 {
 
   // UTC TimeZone is assumed to never change over JVM lifetime
-  private static final TimeZone TIME_ZONE_UTC_OBJ =
-      TimeZone.getTimeZone(TIME_ZONE_UTC);
+  private static final TimeZone TIME_ZONE_UTC_OBJ = TimeZone
+      .getTimeZone(TIME_ZONE_UTC);
 
 
 
   /**
-   * Decodes the provided normalized value as a generalized time value
-   * and retrieves a timestamp containing its representation.
-   * 
+   * Decodes the provided normalized value as a generalized time value and
+   * retrieves a timestamp containing its representation.
+   *
    * @param value
-   *          The normalized value to decode using the generalized time
-   *          syntax.
-   * @return The timestamp created from the provided generalized time
-   *         value.
+   *          The normalized value to decode using the generalized time syntax.
+   * @return The timestamp created from the provided generalized time value.
    * @throws DecodeException
-   *           If the provided value cannot be parsed as a valid
-   *           generalized time string.
+   *           If the provided value cannot be parsed as a valid generalized
+   *           time string.
    */
-  static long decodeGeneralizedTimeValue(ByteSequence value)
+  static long decodeGeneralizedTimeValue(final ByteSequence value)
       throws DecodeException
   {
     int year = 0;
@@ -89,8 +86,8 @@
     final int length = valueString.length();
     if (length < 11)
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_TOO_SHORT.get(valueString);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_TOO_SHORT
+          .get(valueString);
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "valueIsAcceptable", e);
@@ -144,9 +141,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_YEAR.get(
-                valueString, String.valueOf(valueString.charAt(i)));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_YEAR
+            .get(valueString, String.valueOf(valueString.charAt(i)));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -201,9 +197,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_MONTH.get(
-                valueString, valueString.substring(4, 6));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_MONTH
+            .get(valueString, valueString.substring(4, 6));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -227,9 +222,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_MONTH.get(
-                valueString, valueString.substring(4, 6));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_MONTH
+            .get(valueString, valueString.substring(4, 6));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -237,9 +231,8 @@
       }
       break;
     default:
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_MONTH.get(
-              valueString, valueString.substring(4, 6));
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_MONTH
+          .get(valueString, valueString.substring(4, 6));
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "valueIsAcceptable", e);
@@ -296,9 +289,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_DAY.get(
-                valueString, valueString.substring(6, 8));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_DAY
+            .get(valueString, valueString.substring(6, 8));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -351,9 +343,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_DAY.get(
-                valueString, valueString.substring(6, 8));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_DAY
+            .get(valueString, valueString.substring(6, 8));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -406,9 +397,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_DAY.get(
-                valueString, valueString.substring(6, 8));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_DAY
+            .get(valueString, valueString.substring(6, 8));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -429,9 +419,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_DAY.get(
-                valueString, valueString.substring(6, 8));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_DAY
+            .get(valueString, valueString.substring(6, 8));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -440,9 +429,8 @@
       break;
 
     default:
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_DAY.get(
-              valueString, valueString.substring(6, 8));
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_DAY
+          .get(valueString, valueString.substring(6, 8));
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "valueIsAcceptable", e);
@@ -499,9 +487,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_HOUR.get(
-                valueString, valueString.substring(8, 10));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_HOUR
+            .get(valueString, valueString.substring(8, 10));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -553,9 +540,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_HOUR.get(
-                valueString, valueString.substring(8, 10));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_HOUR
+            .get(valueString, valueString.substring(8, 10));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -583,9 +569,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_HOUR.get(
-                valueString, valueString.substring(8, 10));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_HOUR
+            .get(valueString, valueString.substring(8, 10));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -594,9 +579,8 @@
       break;
 
     default:
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_HOUR.get(
-              valueString, valueString.substring(8, 10));
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_HOUR
+          .get(valueString, valueString.substring(8, 10));
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "valueIsAcceptable", e);
@@ -621,9 +605,8 @@
       // must be a digit between 0 and 9.
       if (length < 13)
       {
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR.get(
-                valueString, String.valueOf(m1), 10);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(m1), 10);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -674,9 +657,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_MINUTE.get(
-                valueString, valueString.substring(10, 12));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_MINUTE
+            .get(valueString, valueString.substring(10, 12));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -702,9 +684,8 @@
         {
           // This should only happen if the provided date wasn't legal
           // (e.g., September 31).
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME.get(
-                  valueString, String.valueOf(e));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME
+              .get(valueString, String.valueOf(e));
           final DecodeException de = DecodeException.error(message, e);
           StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
               "valueIsAcceptable", de);
@@ -713,9 +694,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR.get(
-                valueString, String.valueOf(m1), 10);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(m1), 10);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -742,9 +722,8 @@
 
           // This should only happen if the provided date wasn't legal
           // (e.g., September 31).
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME.get(
-                  valueString, String.valueOf(e));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME
+              .get(valueString, String.valueOf(e));
           final DecodeException de = DecodeException.error(message, e);
           StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
               "valueIsAcceptable", de);
@@ -753,9 +732,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR.get(
-                valueString, String.valueOf(m1), 10);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(m1), 10);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -764,13 +742,12 @@
 
     case '.':
     case ',':
-      return finishDecodingFraction(valueString, 11, year, month, day,
-          hour, minute, second, 3600000);
+      return finishDecodingFraction(valueString, 11, year, month, day, hour,
+          minute, second, 3600000);
 
     default:
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR.get(
-              valueString, String.valueOf(m1), 10);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+          .get(valueString, String.valueOf(m1), 10);
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "valueIsAcceptable", e);
@@ -795,9 +772,8 @@
       // must be a digit between 0 and 9.
       if (length < 15)
       {
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR.get(
-                valueString, String.valueOf(s1), 12);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(s1), 12);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -848,9 +824,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_MINUTE.get(
-                valueString, valueString.substring(12, 14));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_MINUTE
+            .get(valueString, valueString.substring(12, 14));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -864,9 +839,8 @@
       // must be a 0.
       if (length < 15)
       {
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR.get(
-                valueString, String.valueOf(s1), 12);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(s1), 12);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -875,9 +849,8 @@
 
       if (valueString.charAt(13) != '0')
       {
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_SECOND.get(
-                valueString, valueString.substring(12, 14));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_SECOND
+            .get(valueString, valueString.substring(12, 14));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -905,9 +878,8 @@
 
           // This should only happen if the provided date wasn't legal
           // (e.g., September 31).
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME.get(
-                  valueString, String.valueOf(e));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME
+              .get(valueString, String.valueOf(e));
           final DecodeException de = DecodeException.error(message, e);
           StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
               "valueIsAcceptable", de);
@@ -916,9 +888,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR.get(
-                valueString, String.valueOf(s1), 12);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(s1), 12);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -945,9 +916,8 @@
 
           // This should only happen if the provided date wasn't legal
           // (e.g., September 31).
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME.get(
-                  valueString, String.valueOf(e));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME
+              .get(valueString, String.valueOf(e));
           final DecodeException de = DecodeException.error(message, e);
           StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
               "valueIsAcceptable", de);
@@ -956,9 +926,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR.get(
-                valueString, String.valueOf(s1), 12);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(s1), 12);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -967,13 +936,12 @@
 
     case '.':
     case ',':
-      return finishDecodingFraction(valueString, 13, year, month, day,
-          hour, minute, second, 60000);
+      return finishDecodingFraction(valueString, 13, year, month, day, hour,
+          minute, second, 60000);
 
     default:
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR.get(
-              valueString, String.valueOf(s1), 12);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+          .get(valueString, String.valueOf(s1), 12);
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "valueIsAcceptable", e);
@@ -988,8 +956,8 @@
     {
     case '.':
     case ',':
-      return finishDecodingFraction(valueString, 15, year, month, day,
-          hour, minute, second, 1000);
+      return finishDecodingFraction(valueString, 15, year, month, day, hour,
+          minute, second, 1000);
 
     case 'Z':
       // This is fine only if we are at the end of the value.
@@ -1008,9 +976,8 @@
         {
           // This should only happen if the provided date wasn't legal
           // (e.g., September 31).
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME.get(
-                  valueString, String.valueOf(e));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME
+              .get(valueString, String.valueOf(e));
           final DecodeException de = DecodeException.error(message, e);
           StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
               "valueIsAcceptable", de);
@@ -1019,10 +986,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
-                .get(valueString, String
-                    .valueOf(valueString.charAt(14)), 14);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(valueString.charAt(14)), 14);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -1048,9 +1013,8 @@
         {
           // This should only happen if the provided date wasn't legal
           // (e.g., September 31).
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME.get(
-                  valueString, String.valueOf(e));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME
+              .get(valueString, String.valueOf(e));
           final DecodeException de = DecodeException.error(message, e);
           StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
               "valueIsAcceptable", de);
@@ -1059,10 +1023,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
-                .get(valueString, String
-                    .valueOf(valueString.charAt(14)), 14);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(valueString.charAt(14)), 14);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "valueIsAcceptable", e);
@@ -1070,9 +1032,8 @@
       }
 
     default:
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR.get(
-              valueString, String.valueOf(valueString.charAt(14)), 14);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_CHAR
+          .get(valueString, String.valueOf(valueString.charAt(14)), 14);
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "valueIsAcceptable", e);
@@ -1083,16 +1044,15 @@
 
 
   /**
-   * Completes decoding the generalized time value containing a
-   * fractional component. It will also decode the trailing 'Z' or
-   * offset.
-   * 
+   * Completes decoding the generalized time value containing a fractional
+   * component. It will also decode the trailing 'Z' or offset.
+   *
    * @param value
-   *          The whole value, including the fractional component and
-   *          time zone information.
+   *          The whole value, including the fractional component and time zone
+   *          information.
    * @param startPos
-   *          The position of the first character after the period in
-   *          the value string.
+   *          The position of the first character after the period in the value
+   *          string.
    * @param year
    *          The year decoded from the provided value.
    * @param month
@@ -1106,24 +1066,25 @@
    * @param second
    *          The second decoded from the provided value.
    * @param multiplier
-   *          The multiplier value that should be used to scale the
-   *          fraction appropriately. If it's a fraction of an hour,
-   *          then it should be 3600000 (60*60*1000). If it's a fraction
-   *          of a minute, then it should be 60000. If it's a fraction
-   *          of a second, then it should be 1000.
-   * @return The timestamp created from the provided generalized time
-   *         value including the fractional element.
+   *          The multiplier value that should be used to scale the fraction
+   *          appropriately. If it's a fraction of an hour, then it should be
+   *          3600000 (60*60*1000). If it's a fraction of a minute, then it
+   *          should be 60000. If it's a fraction of a second, then it should be
+   *          1000.
+   * @return The timestamp created from the provided generalized time value
+   *         including the fractional element.
    * @throws DecodeException
-   *           If the provided value cannot be parsed as a valid
-   *           generalized time string.
+   *           If the provided value cannot be parsed as a valid generalized
+   *           time string.
    */
-  private static long finishDecodingFraction(String value,
-      int startPos, int year, int month, int day, int hour, int minute,
-      int second, int multiplier) throws DecodeException
+  private static long finishDecodingFraction(final String value,
+      final int startPos, final int year, final int month, final int day,
+      final int hour, final int minute, final int second, final int multiplier)
+      throws DecodeException
   {
     final int length = value.length();
-    final StringBuilder fractionBuffer =
-        new StringBuilder(2 + length - startPos);
+    final StringBuilder fractionBuffer = new StringBuilder(2 + length
+        - startPos);
     fractionBuffer.append("0.");
 
     TimeZone timeZone = null;
@@ -1150,9 +1111,8 @@
         // This is only acceptable if we're at the end of the value.
         if (i != value.length() - 1)
         {
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_FRACTION_CHAR
-                  .get(value, String.valueOf(c));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_FRACTION_CHAR
+              .get(value, String.valueOf(c));
           final DecodeException e = DecodeException.error(message);
           StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
               "finishDecodingFraction", e);
@@ -1168,9 +1128,8 @@
         break outerLoop;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_FRACTION_CHAR
-                .get(value, String.valueOf(c));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_FRACTION_CHAR
+            .get(value, String.valueOf(c));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "finishDecodingFraction", e);
@@ -1180,8 +1139,8 @@
 
     if (fractionBuffer.length() == 2)
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_EMPTY_FRACTION.get(value);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_EMPTY_FRACTION
+          .get(value);
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "finishDecodingFraction", e);
@@ -1190,19 +1149,16 @@
 
     if (timeZone == null)
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_NO_TIME_ZONE_INFO
-              .get(value);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_NO_TIME_ZONE_INFO
+          .get(value);
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "finishDecodingFraction", e);
       throw e;
     }
 
-    final Double fractionValue =
-        Double.parseDouble(fractionBuffer.toString());
-    final long additionalMilliseconds =
-        Math.round(fractionValue * multiplier);
+    final Double fractionValue = Double.parseDouble(fractionBuffer.toString());
+    final long additionalMilliseconds = Math.round(fractionValue * multiplier);
 
     try
     {
@@ -1218,9 +1174,8 @@
 
       // This should only happen if the provided date wasn't legal
       // (e.g., September 31).
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME.get(value,
-              String.valueOf(e));
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_ILLEGAL_TIME
+          .get(value, String.valueOf(e));
       final DecodeException de = DecodeException.error(message, e);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "valueIsAcceptable", de);
@@ -1232,27 +1187,25 @@
 
   /**
    * Decodes a time zone offset from the provided value.
-   * 
+   *
    * @param value
    *          The whole value, including the offset.
    * @param startPos
-   *          The position of the first character that is contained in
-   *          the offset. This should be the position of the plus or
-   *          minus character.
-   * @return The {@code TimeZone} object representing the decoded time
-   *         zone.
+   *          The position of the first character that is contained in the
+   *          offset. This should be the position of the plus or minus
+   *          character.
+   * @return The {@code TimeZone} object representing the decoded time zone.
    * @throws DecodeException
    *           If the provided value does not contain a valid offset.
    */
-  private static TimeZone getTimeZoneForOffset(String value,
-      int startPos) throws DecodeException
+  private static TimeZone getTimeZoneForOffset(final String value,
+      final int startPos) throws DecodeException
   {
     final String offSetStr = value.substring(startPos);
     if (offSetStr.length() != 3 && offSetStr.length() != 5)
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET.get(value,
-              offSetStr);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET
+          .get(value, offSetStr);
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "getTimeZoneForOffset", e);
@@ -1268,9 +1221,8 @@
       break;
 
     default:
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET.get(value,
-              offSetStr);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET
+          .get(value, offSetStr);
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "getTimeZoneForOffset", e);
@@ -1298,9 +1250,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET.get(value,
-                offSetStr);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET
+            .get(value, offSetStr);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "getTimeZoneForOffset", e);
@@ -1319,9 +1270,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET.get(value,
-                offSetStr);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET
+            .get(value, offSetStr);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "getTimeZoneForOffset", e);
@@ -1330,9 +1280,8 @@
       break;
 
     default:
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET.get(value,
-              offSetStr);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET
+          .get(value, offSetStr);
       final DecodeException e = DecodeException.error(message);
       StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
           "getTimeZoneForOffset", e);
@@ -1367,9 +1316,8 @@
           break;
 
         default:
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET.get(
-                  value, offSetStr);
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET
+              .get(value, offSetStr);
           final DecodeException e = DecodeException.error(message);
           StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
               "getTimeZoneForOffset", e);
@@ -1378,9 +1326,8 @@
         break;
 
       default:
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET.get(value,
-                offSetStr);
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_GENERALIZED_TIME_INVALID_OFFSET
+            .get(value, offSetStr);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("GeneralizedTimeSyntax",
             "getTimeZoneForOffset", e);
@@ -1434,21 +1381,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     try
     {
diff --git a/sdk/src/org/opends/sdk/schema/GenerateCoreSchema.java b/sdk/src/org/opends/sdk/schema/GenerateCoreSchema.java
index 0e2d647..9e2db8c 100644
--- a/sdk/src/org/opends/sdk/schema/GenerateCoreSchema.java
+++ b/sdk/src/org/opends/sdk/schema/GenerateCoreSchema.java
@@ -38,74 +38,10 @@
  */
 final class GenerateCoreSchema
 {
-  private static boolean isOpenDSOID(String oid)
-  {
-    return oid.startsWith(SchemaConstants.OID_OPENDS_SERVER_BASE + ".");
-  }
-
-
-
-  private static final Set<String> ABBREVIATIONS = new HashSet<String>(
-      Arrays.asList("SASL", "LDAP", "DN", "DIT", "RDN", "JPEG", "OID",
-          "UUID", "IA5", "UID", "UTC", "X500", "X121", "C", "CN", "O",
-          "OU", "L", "DC", "ISDN", "SN", "ST"));
-
-
-
-  private static String splitNameIntoWords(String name)
-  {
-    String splitName = name.replaceAll("([A-Z][a-z])", "_$1");
-    splitName = splitName.replaceAll("([a-z])([A-Z])", "$1_$2");
-
-    return splitName.toUpperCase(Locale.ENGLISH);
-  }
-
-
-
-  private static String toJavaName(String splitName)
-  {
-    StringBuilder builder = new StringBuilder();
-    for (String word : splitName.split("_"))
-    {
-      if (ABBREVIATIONS.contains(word))
-      {
-        builder.append(word);
-      }
-      else
-      {
-        builder.append(word.charAt(0));
-        if (word.length() > 1)
-        {
-          builder.append(word.substring(1).toLowerCase(Locale.ENGLISH));
-        }
-      }
-    }
-    return builder.toString();
-  }
-
-
-
-  private static void testSplitNameIntoWords()
-  {
-    String[][] values =
-        new String[][] { { "oneTwoThree", "ONE_TWO_THREE" },
-            { "oneTWOThree", "ONE_TWO_THREE" },
-            { "oneX500Three", "ONE_X500_THREE" },
-            { "oneTwoX500", "ONE_TWO_X500" },
-            { "oneTwoX500", "ONE_TWO_X500" },
-            { "x500TwoThree", "X500_TWO_THREE" }, };
-
-    for (String[] test : values)
-    {
-      String actual = splitNameIntoWords(test[0]);
-      String expected = test[1];
-      if (!actual.equals(expected))
-      {
-        System.out.println("Test Split Failure: " + test[0] + " -> "
-            + actual + " != " + expected);
-      }
-    }
-  }
+  private static final Set<String> ABBREVIATIONS = new HashSet<String>(Arrays
+      .asList("SASL", "LDAP", "DN", "DIT", "RDN", "JPEG", "OID", "UUID", "IA5",
+          "UID", "UTC", "X500", "X121", "C", "CN", "O", "OU", "L", "DC",
+          "ISDN", "SN", "ST"));
 
 
 
@@ -115,68 +51,62 @@
    * @param args
    *          The command line arguments (none required).
    */
-  public static void main(String[] args)
+  public static void main(final String[] args)
   {
     testSplitNameIntoWords();
 
-    Schema schema = Schema.getCoreSchema();
+    final Schema schema = Schema.getCoreSchema();
 
-    SortedMap<String, Syntax> syntaxes = new TreeMap<String, Syntax>();
-    for (Syntax syntax : schema.getSyntaxes())
+    final SortedMap<String, Syntax> syntaxes = new TreeMap<String, Syntax>();
+    for (final Syntax syntax : schema.getSyntaxes())
     {
       if (isOpenDSOID(syntax.getOID()))
       {
         continue;
       }
 
-      String name = syntax.getDescription().replaceAll(" Syntax$", "");
-      String fieldName =
-          name.replace(" ", "_").toUpperCase(Locale.ENGLISH).concat(
-              "_SYNTAX");
+      final String name = syntax.getDescription().replaceAll(" Syntax$", "");
+      final String fieldName = name.replace(" ", "_").toUpperCase(
+          Locale.ENGLISH).concat("_SYNTAX");
       syntaxes.put(fieldName, syntax);
     }
 
-    SortedMap<String, MatchingRule> matchingRules =
-        new TreeMap<String, MatchingRule>();
-    for (MatchingRule matchingRule : schema.getMatchingRules())
+    final SortedMap<String, MatchingRule> matchingRules = new TreeMap<String, MatchingRule>();
+    for (final MatchingRule matchingRule : schema.getMatchingRules())
     {
       if (isOpenDSOID(matchingRule.getOID()))
       {
         continue;
       }
 
-      String name =
-          matchingRule.getNameOrOID().replaceAll("Match$", "");
-      String fieldName =
-          splitNameIntoWords(name).concat("_MATCHING_RULE");
+      final String name = matchingRule.getNameOrOID().replaceAll("Match$", "");
+      final String fieldName = splitNameIntoWords(name)
+          .concat("_MATCHING_RULE");
       matchingRules.put(fieldName, matchingRule);
     }
 
-    SortedMap<String, AttributeType> attributeTypes =
-        new TreeMap<String, AttributeType>();
-    for (AttributeType attributeType : schema.getAttributeTypes())
+    final SortedMap<String, AttributeType> attributeTypes = new TreeMap<String, AttributeType>();
+    for (final AttributeType attributeType : schema.getAttributeTypes())
     {
       if (isOpenDSOID(attributeType.getOID()))
       {
         continue;
       }
-      String name = attributeType.getNameOrOID();
-      String fieldName =
-          splitNameIntoWords(name).concat("_ATTRIBUTE_TYPE");
+      final String name = attributeType.getNameOrOID();
+      final String fieldName = splitNameIntoWords(name).concat(
+          "_ATTRIBUTE_TYPE");
       attributeTypes.put(fieldName, attributeType);
     }
 
-    SortedMap<String, ObjectClass> objectClasses =
-        new TreeMap<String, ObjectClass>();
-    for (ObjectClass objectClass : schema.getObjectClasses())
+    final SortedMap<String, ObjectClass> objectClasses = new TreeMap<String, ObjectClass>();
+    for (final ObjectClass objectClass : schema.getObjectClasses())
     {
       if (isOpenDSOID(objectClass.getOID()))
       {
         continue;
       }
-      String name = objectClass.getNameOrOID();
-      String fieldName =
-          splitNameIntoWords(name).concat("_OBJECT_CLASS");
+      final String name = objectClass.getNameOrOID();
+      final String fieldName = splitNameIntoWords(name).concat("_OBJECT_CLASS");
 
       objectClasses.put(fieldName, objectClass);
     }
@@ -189,8 +119,8 @@
     System.out.println();
     System.out.println();
     System.out.println("/**");
-    System.out
-        .println(" * The OpenDS SDK core schema contains standard LDAP RFC schema elements. These include:");
+    System.out.println(" * The OpenDS SDK core schema contains standard LDAP "
+        + "RFC schema elements. These include:");
     System.out.println(" * <ul>");
     System.out
         .println(" * <li><a href=\"http://tools.ietf.org/html/rfc4512\">RFC 4512 -");
@@ -214,8 +144,7 @@
     System.out.println(" * Attribute </a>");
     System.out
         .println(" * <li><a href=\"http://tools.ietf.org/html/rfc3045\">RFC 3045 - Storing");
-    System.out
-        .println(" * Vendor Information in the LDAP Root DSE </a>");
+    System.out.println(" * Vendor Information in the LDAP Root DSE </a>");
     System.out
         .println(" * <li><a href=\"http://tools.ietf.org/html/rfc3112\">RFC 3112 - LDAP");
     System.out.println(" * Authentication Password Schema </a>");
@@ -225,56 +154,51 @@
         .println(" * The core schema is non-strict: attempts to retrieve");
     System.out
         .println(" * non-existent Attribute Types will return a temporary");
-    System.out
-        .println(" * Attribute Type having the Octet String syntax.");
+    System.out.println(" * Attribute Type having the Octet String syntax.");
     System.out.println(" */");
     System.out.println("public final class CoreSchema");
     System.out.println("{");
 
     System.out.println("  // Core Syntaxes");
-    for (Map.Entry<String, Syntax> syntax : syntaxes.entrySet())
+    for (final Map.Entry<String, Syntax> syntax : syntaxes.entrySet())
     {
-      System.out.println("  private static final Syntax "
-          + syntax.getKey() + " =");
-      System.out
-          .println("    CoreSchemaImpl.getInstance().getSyntax(\""
-              + syntax.getValue().getOID() + "\");");
+      System.out.println("  private static final Syntax " + syntax.getKey()
+          + " =");
+      System.out.println("    CoreSchemaImpl.getInstance().getSyntax(\""
+          + syntax.getValue().getOID() + "\");");
     }
 
     System.out.println();
     System.out.println("  // Core Matching Rules");
-    for (Map.Entry<String, MatchingRule> matchingRule : matchingRules
+    for (final Map.Entry<String, MatchingRule> matchingRule : matchingRules
         .entrySet())
     {
       System.out.println("  private static final MatchingRule "
           + matchingRule.getKey() + " =");
-      System.out
-          .println("    CoreSchemaImpl.getInstance().getMatchingRule(\""
-              + matchingRule.getValue().getOID() + "\");");
+      System.out.println("    CoreSchemaImpl.getInstance().getMatchingRule(\""
+          + matchingRule.getValue().getOID() + "\");");
     }
 
     System.out.println();
     System.out.println("  // Core Attribute Types");
-    for (Map.Entry<String, AttributeType> attributeType : attributeTypes
+    for (final Map.Entry<String, AttributeType> attributeType : attributeTypes
         .entrySet())
     {
       System.out.println("  private static final AttributeType "
           + attributeType.getKey() + " =");
-      System.out
-          .println("    CoreSchemaImpl.getInstance().getAttributeType(\""
-              + attributeType.getValue().getOID() + "\");");
+      System.out.println("    CoreSchemaImpl.getInstance().getAttributeType(\""
+          + attributeType.getValue().getOID() + "\");");
     }
 
     System.out.println();
     System.out.println("  // Core Object Classes");
-    for (Map.Entry<String, ObjectClass> objectClass : objectClasses
+    for (final Map.Entry<String, ObjectClass> objectClass : objectClasses
         .entrySet())
     {
       System.out.println("  private static final ObjectClass "
           + objectClass.getKey() + " =");
-      System.out
-          .println("    CoreSchemaImpl.getInstance().getObjectClass(\""
-              + objectClass.getValue().getOID() + "\");");
+      System.out.println("    CoreSchemaImpl.getInstance().getObjectClass(\""
+          + objectClass.getValue().getOID() + "\");");
     }
 
     System.out.println();
@@ -300,24 +224,22 @@
     System.out.println("    return CoreSchemaImpl.getInstance();");
     System.out.println("  }");
 
-    for (Map.Entry<String, Syntax> syntax : syntaxes.entrySet())
+    for (final Map.Entry<String, Syntax> syntax : syntaxes.entrySet())
     {
       System.out.println();
       System.out.println();
       System.out.println();
 
-      String description =
-          toCodeJavaDoc(syntax.getValue().getDescription().replaceAll(
-              " Syntax$", "")
-              + " Syntax");
+      final String description = toCodeJavaDoc(syntax.getValue()
+          .getDescription().replaceAll(" Syntax$", "")
+          + " Syntax");
       System.out.println("  /**");
-      System.out.println("   * Returns a reference to the "
-          + description);
+      System.out.println("   * Returns a reference to the " + description);
       System.out.println("   * which has the OID "
           + toCodeJavaDoc(syntax.getValue().getOID()) + ".");
       System.out.println("   *");
-      System.out.println("   * @return A reference to the "
-          + description + ".");
+      System.out
+          .println("   * @return A reference to the " + description + ".");
 
       System.out.println("   */");
       System.out.println("  public static Syntax get"
@@ -327,23 +249,23 @@
       System.out.println("  }");
     }
 
-    for (Map.Entry<String, MatchingRule> matchingRule : matchingRules
+    for (final Map.Entry<String, MatchingRule> matchingRule : matchingRules
         .entrySet())
     {
       System.out.println();
       System.out.println();
       System.out.println();
 
-      String description =
-          toCodeJavaDoc(matchingRule.getValue().getNameOrOID());
+      final String description = toCodeJavaDoc(matchingRule.getValue()
+          .getNameOrOID());
       System.out.println("  /**");
-      System.out.println("   * Returns a reference to the "
-          + description + " Matching Rule");
+      System.out.println("   * Returns a reference to the " + description
+          + " Matching Rule");
       System.out.println("   * which has the OID "
           + toCodeJavaDoc(matchingRule.getValue().getOID()) + ".");
       System.out.println("   *");
-      System.out.println("   * @return A reference to the "
-          + description + " Matching Rule.");
+      System.out.println("   * @return A reference to the " + description
+          + " Matching Rule.");
 
       System.out.println("   */");
       System.out.println("  public static MatchingRule get"
@@ -353,23 +275,23 @@
       System.out.println("  }");
     }
 
-    for (Map.Entry<String, AttributeType> attributeType : attributeTypes
+    for (final Map.Entry<String, AttributeType> attributeType : attributeTypes
         .entrySet())
     {
       System.out.println();
       System.out.println();
       System.out.println();
 
-      String description =
-          toCodeJavaDoc(attributeType.getValue().getNameOrOID());
+      final String description = toCodeJavaDoc(attributeType.getValue()
+          .getNameOrOID());
       System.out.println("  /**");
-      System.out.println("   * Returns a reference to the "
-          + description + " Attribute Type");
+      System.out.println("   * Returns a reference to the " + description
+          + " Attribute Type");
       System.out.println("   * which has the OID "
           + toCodeJavaDoc(attributeType.getValue().getOID()) + ".");
       System.out.println("   *");
-      System.out.println("   * @return A reference to the "
-          + description + " Attribute Type.");
+      System.out.println("   * @return A reference to the " + description
+          + " Attribute Type.");
 
       System.out.println("   */");
       System.out.println("  public static AttributeType get"
@@ -379,23 +301,23 @@
       System.out.println("  }");
     }
 
-    for (Map.Entry<String, ObjectClass> objectClass : objectClasses
+    for (final Map.Entry<String, ObjectClass> objectClass : objectClasses
         .entrySet())
     {
       System.out.println();
       System.out.println();
       System.out.println();
 
-      String description =
-          toCodeJavaDoc(objectClass.getValue().getNameOrOID());
+      final String description = toCodeJavaDoc(objectClass.getValue()
+          .getNameOrOID());
       System.out.println("  /**");
-      System.out.println("   * Returns a reference to the "
-          + description + " Object Class");
+      System.out.println("   * Returns a reference to the " + description
+          + " Object Class");
       System.out.println("   * which has the OID "
           + toCodeJavaDoc(objectClass.getValue().getOID()) + ".");
       System.out.println("   *");
-      System.out.println("   * @return A reference to the "
-          + description + " Object Class.");
+      System.out.println("   * @return A reference to the " + description
+          + " Object Class.");
 
       System.out.println("   */");
       System.out.println("  public static ObjectClass get"
@@ -410,8 +332,76 @@
 
 
 
-  private static String toCodeJavaDoc(String text)
+  private static boolean isOpenDSOID(final String oid)
+  {
+    return oid.startsWith(SchemaConstants.OID_OPENDS_SERVER_BASE + ".");
+  }
+
+
+
+  private static String splitNameIntoWords(final String name)
+  {
+    String splitName = name.replaceAll("([A-Z][a-z])", "_$1");
+    splitName = splitName.replaceAll("([a-z])([A-Z])", "$1_$2");
+
+    return splitName.toUpperCase(Locale.ENGLISH);
+  }
+
+
+
+  private static void testSplitNameIntoWords()
+  {
+    final String[][] values = new String[][] {
+        { "oneTwoThree", "ONE_TWO_THREE" }, { "oneTWOThree", "ONE_TWO_THREE" },
+        { "oneX500Three", "ONE_X500_THREE" }, { "oneTwoX500", "ONE_TWO_X500" },
+        { "oneTwoX500", "ONE_TWO_X500" }, { "x500TwoThree", "X500_TWO_THREE" }, };
+
+    for (final String[] test : values)
+    {
+      final String actual = splitNameIntoWords(test[0]);
+      final String expected = test[1];
+      if (!actual.equals(expected))
+      {
+        System.out.println("Test Split Failure: " + test[0] + " -> " + actual
+            + " != " + expected);
+      }
+    }
+  }
+
+
+
+  private static String toCodeJavaDoc(final String text)
   {
     return String.format("{@code %s}", text);
   }
+
+
+
+  private static String toJavaName(final String splitName)
+  {
+    final StringBuilder builder = new StringBuilder();
+    for (final String word : splitName.split("_"))
+    {
+      if (ABBREVIATIONS.contains(word))
+      {
+        builder.append(word);
+      }
+      else
+      {
+        builder.append(word.charAt(0));
+        if (word.length() > 1)
+        {
+          builder.append(word.substring(1).toLowerCase(Locale.ENGLISH));
+        }
+      }
+    }
+    return builder.toString();
+  }
+
+
+
+  private GenerateCoreSchema()
+  {
+    // Prevent instantiation.
+  }
 }
diff --git a/sdk/src/org/opends/sdk/schema/GuideSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/GuideSyntaxImpl.java
index ec30ea0..09c3ed8 100644
--- a/sdk/src/org/opends/sdk/schema/GuideSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/GuideSyntaxImpl.java
@@ -30,8 +30,10 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_GUIDE_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DecodeException;
@@ -42,37 +44,35 @@
 
 
 /**
- * This class implements the guide attribute syntax, which may be used
- * to provide criteria for generating search filters for entries,
- * optionally tied to a specified objectclass.
+ * This class implements the guide attribute syntax, which may be used to
+ * provide criteria for generating search filters for entries, optionally tied
+ * to a specified objectclass.
  */
 final class GuideSyntaxImpl extends AbstractSyntaxImpl
 {
   /**
    * Determines whether the provided string represents a valid criteria
    * according to the guide syntax.
-   * 
+   *
    * @param criteria
-   *          The portion of the criteria for which to make the
-   *          determination.
+   *          The portion of the criteria for which to make the determination.
    * @param valueStr
    *          The complete guide value provided by the client.
    * @param invalidReason
-   *          The buffer to which to append the reason that the criteria
-   *          is invalid if a problem is found.
-   * @return <CODE>true</CODE> if the provided string does contain a
-   *         valid criteria, or <CODE>false</CODE> if not.
+   *          The buffer to which to append the reason that the criteria is
+   *          invalid if a problem is found.
+   * @return <CODE>true</CODE> if the provided string does contain a valid
+   *         criteria, or <CODE>false</CODE> if not.
    */
-  static boolean criteriaIsValid(String criteria, String valueStr,
-      LocalizableMessageBuilder invalidReason)
+  static boolean criteriaIsValid(final String criteria, final String valueStr,
+      final LocalizableMessageBuilder invalidReason)
   {
     // See if the criteria starts with a '!'. If so, then just evaluate
     // everything after that as a criteria.
     char c = criteria.charAt(0);
     if (c == '!')
     {
-      return criteriaIsValid(criteria.substring(1), valueStr,
-          invalidReason);
+      return criteriaIsValid(criteria.substring(1), valueStr, invalidReason);
     }
 
     // See if the criteria starts with a '('. If so, then find the
@@ -108,14 +108,14 @@
               c = criteria.charAt(i + 1);
               if (c == '|' || c == '&')
               {
-                return criteriaIsValid(criteria.substring(i + 2),
-                    valueStr, invalidReason);
+                return criteriaIsValid(criteria.substring(i + 2), valueStr,
+                    invalidReason);
               }
               else
               {
 
-                invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_ILLEGAL_CHAR
-                    .get(valueStr, criteria, c, (i + 1)));
+                invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_ILLEGAL_CHAR.get(
+                    valueStr, criteria, c, (i + 1)));
                 return false;
               }
             }
@@ -130,8 +130,8 @@
       // If we've gotten here, then we went through the entire value
       // without finding the appropriate closing parenthesis.
 
-      invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_MISSING_CLOSE_PAREN
-          .get(valueStr, criteria));
+      invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_MISSING_CLOSE_PAREN.get(
+          valueStr, criteria));
       return false;
     }
 
@@ -157,8 +157,8 @@
           }
           else
           {
-            invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_ILLEGAL_CHAR
-                .get(valueStr, criteria, c, 5));
+            invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_ILLEGAL_CHAR.get(
+                valueStr, criteria, c, 5));
             return false;
           }
         }
@@ -181,17 +181,16 @@
           }
           else
           {
-            invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_ILLEGAL_CHAR
-                .get(valueStr, criteria, c, 6));
+            invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_ILLEGAL_CHAR.get(
+                valueStr, criteria, c, 6));
             return false;
           }
         }
       }
       else
       {
-        invalidReason
-            .append(ERR_ATTR_SYNTAX_GUIDE_INVALID_QUESTION_MARK.get(
-                valueStr, criteria));
+        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_QUESTION_MARK.get(
+            valueStr, criteria));
         return false;
       }
     }
@@ -210,28 +209,28 @@
     final int dollarPos = criteria.indexOf('$');
     if (dollarPos < 0)
     {
-      invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_NO_DOLLAR.get(
-          valueStr, criteria));
+      invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_NO_DOLLAR.get(valueStr,
+          criteria));
       return false;
     }
     else if (dollarPos == 0)
     {
-      invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_NO_ATTR.get(valueStr,
-          criteria));
+      invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_NO_ATTR
+          .get(valueStr, criteria));
       return false;
     }
     else if (dollarPos == criteria.length() - 1)
     {
-      invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_NO_MATCH_TYPE.get(
-          valueStr, criteria));
+      invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_NO_MATCH_TYPE.get(valueStr,
+          criteria));
       return false;
     }
     else
     {
       try
       {
-        SchemaUtils.readOID(new SubstringReader(criteria.substring(0,
-            dollarPos)));
+        SchemaUtils.readOID(new SubstringReader(criteria
+            .substring(0, dollarPos)));
       }
       catch (final DecodeException de)
       {
@@ -255,8 +254,8 @@
       }
       else
       {
-        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE
-            .get(valueStr, criteria, dollarPos + 1));
+        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE.get(
+            valueStr, criteria, dollarPos + 1));
         return false;
       }
 
@@ -268,8 +267,8 @@
       }
       else
       {
-        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE
-            .get(valueStr, criteria, dollarPos + 1));
+        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE.get(
+            valueStr, criteria, dollarPos + 1));
         return false;
       }
 
@@ -281,8 +280,8 @@
       }
       else
       {
-        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE
-            .get(valueStr, criteria, dollarPos + 1));
+        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE.get(
+            valueStr, criteria, dollarPos + 1));
         return false;
       }
 
@@ -294,8 +293,8 @@
       }
       else
       {
-        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE
-            .get(valueStr, criteria, dollarPos + 1));
+        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE.get(
+            valueStr, criteria, dollarPos + 1));
         return false;
       }
 
@@ -307,14 +306,14 @@
       }
       else
       {
-        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE
-            .get(valueStr, criteria, dollarPos + 1));
+        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE.get(
+            valueStr, criteria, dollarPos + 1));
         return false;
       }
 
     default:
-      invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE
-          .get(valueStr, criteria, dollarPos + 1));
+      invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_INVALID_MATCH_TYPE.get(
+          valueStr, criteria, dollarPos + 1));
       return false;
     }
 
@@ -329,13 +328,13 @@
       c = criteria.charAt(endPos);
       if (c == '|' || c == '&')
       {
-        return criteriaIsValid(criteria.substring(endPos + 1),
-            valueStr, invalidReason);
+        return criteriaIsValid(criteria.substring(endPos + 1), valueStr,
+            invalidReason);
       }
       else
       {
-        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_ILLEGAL_CHAR.get(
-            valueStr, criteria, c, endPos));
+        invalidReason.append(ERR_ATTR_SYNTAX_GUIDE_ILLEGAL_CHAR.get(valueStr,
+            criteria, c, endPos));
         return false;
       }
     }
@@ -374,21 +373,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // Get a lowercase string version of the provided value.
     final String valueStr = toLowerCase(value.toString());
@@ -413,8 +412,7 @@
 
     try
     {
-      SchemaUtils.readOID(new SubstringReader(ocName.substring(0,
-          ocLength)));
+      SchemaUtils.readOID(new SubstringReader(ocName.substring(0, ocLength)));
     }
     catch (final DecodeException de)
     {
diff --git a/sdk/src/org/opends/sdk/schema/IA5StringSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/IA5StringSyntaxImpl.java
index aba5901..93a50db 100644
--- a/sdk/src/org/opends/sdk/schema/IA5StringSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/IA5StringSyntaxImpl.java
@@ -29,7 +29,7 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER;
 import static org.opends.sdk.schema.SchemaConstants.*;
 
 import org.opends.sdk.ByteSequence;
@@ -38,12 +38,11 @@
 
 
 
-
 /**
- * This class implements the IA5 string attribute syntax, which is
- * simply a set of ASCII characters. By default, they will be treated in
- * a case-insensitive manner, and equality, ordering, substring, and
- * approximate matching will be allowed.
+ * This class implements the IA5 string attribute syntax, which is simply a set
+ * of ASCII characters. By default, they will be treated in a case-insensitive
+ * manner, and equality, ordering, substring, and approximate matching will be
+ * allowed.
  */
 final class IA5StringSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -94,21 +93,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We will allow any value that does not contain any non-ASCII
     // characters. Empty values are acceptable as well.
@@ -119,9 +118,8 @@
       if ((b & 0x7F) != b)
       {
 
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER.get(
-                value.toString(), String.valueOf(b));
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_IA5_ILLEGAL_CHARACTER
+            .get(value.toString(), String.valueOf(b));
         invalidReason.append(message);
         return false;
       }
diff --git a/sdk/src/org/opends/sdk/schema/IntegerEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/IntegerEqualityMatchingRuleImpl.java
index a44868b..4044bb4 100644
--- a/sdk/src/org/opends/sdk/schema/IntegerEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/IntegerEqualityMatchingRuleImpl.java
@@ -28,7 +28,7 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_ILLEGAL_INTEGER;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -40,15 +40,14 @@
 
 
 /**
- * This class defines the integerMatch matching rule defined in X.520
- * and referenced in RFC 2252.
+ * This class defines the integerMatch matching rule defined in X.520 and
+ * referenced in RFC 2252.
  */
-final class IntegerEqualityMatchingRuleImpl extends
-    AbstractMatchingRuleImpl
+final class IntegerEqualityMatchingRuleImpl extends AbstractMatchingRuleImpl
 {
 
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     try
     {
@@ -59,8 +58,8 @@
       StaticUtils.DEBUG_LOG.throwing("IntegerEqualityMatchingRule",
           "normalizeAttributeValue", e);
 
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_ILLEGAL_INTEGER.get(value.toString());
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_ILLEGAL_INTEGER
+          .get(value.toString());
       throw DecodeException.error(message);
     }
   }
diff --git a/sdk/src/org/opends/sdk/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java
index 413e361..34cad39 100644
--- a/sdk/src/org/opends/sdk/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_EXPECTED_OPEN_PARENTHESIS;
+import static com.sun.opends.sdk.messages.Messages.ERR_EMR_INTFIRSTCOMP_FIRST_COMPONENT_NOT_INT;
 
 import org.opends.sdk.*;
 
@@ -38,19 +40,19 @@
 
 
 /**
- * This class implements the integerFirstComponentMatch matching rule
- * defined in X.520 and referenced in RFC 2252. This rule is intended
- * for use with attributes whose values contain a set of parentheses
- * enclosing a space-delimited set of names and/or name-value pairs
- * (like attribute type or objectclass descriptions) in which the
- * "first component" is the first item after the opening parenthesis.
+ * This class implements the integerFirstComponentMatch matching rule defined in
+ * X.520 and referenced in RFC 2252. This rule is intended for use with
+ * attributes whose values contain a set of parentheses enclosing a
+ * space-delimited set of names and/or name-value pairs (like attribute type or
+ * objectclass descriptions) in which the "first component" is the first item
+ * after the opening parenthesis.
  */
 final class IntegerFirstComponentEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
 
   @Override
-  public Assertion getAssertion(Schema schema, ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     try
@@ -61,10 +63,9 @@
 
       return new Assertion()
       {
-        public ConditionResult matches(ByteSequence attributeValue)
+        public ConditionResult matches(final ByteSequence attributeValue)
         {
-          final int actualIntValue =
-              attributeValue.toByteString().toInt();
+          final int actualIntValue = attributeValue.toByteString().toInt();
           return intValue == actualIntValue ? ConditionResult.TRUE
               : ConditionResult.FALSE;
         }
@@ -73,12 +74,10 @@
     catch (final Exception e)
     {
       StaticUtils.DEBUG_LOG.throwing(
-          "IntegerFirstComponentEqualityMatchingRule", "getAssertion",
-          e);
+          "IntegerFirstComponentEqualityMatchingRule", "getAssertion", e);
 
-      final LocalizableMessage message =
-          ERR_EMR_INTFIRSTCOMP_FIRST_COMPONENT_NOT_INT.get(value
-              .toString());
+      final LocalizableMessage message = ERR_EMR_INTFIRSTCOMP_FIRST_COMPONENT_NOT_INT
+          .get(value.toString());
       throw DecodeException.error(message);
     }
 
@@ -86,8 +85,8 @@
 
 
 
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     final String definition = value.toString();
     final SubstringReader reader = new SubstringReader(definition);
@@ -109,9 +108,8 @@
     final char c = reader.read();
     if (c != '(')
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_EXPECTED_OPEN_PARENTHESIS.get(definition,
-              (reader.pos() - 1), String.valueOf(c));
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_EXPECTED_OPEN_PARENTHESIS
+          .get(definition, (reader.pos() - 1), String.valueOf(c));
       throw DecodeException.error(message);
     }
 
diff --git a/sdk/src/org/opends/sdk/schema/IntegerOrderingMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/IntegerOrderingMatchingRuleImpl.java
index 0b5c441..a8257d3 100644
--- a/sdk/src/org/opends/sdk/schema/IntegerOrderingMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/IntegerOrderingMatchingRuleImpl.java
@@ -28,7 +28,7 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_ILLEGAL_INTEGER;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -40,15 +40,15 @@
 
 
 /**
- * This class defines the integerOrderingMatch matching rule defined in
- * X.520 and referenced in RFC 4519.
+ * This class defines the integerOrderingMatch matching rule defined in X.520
+ * and referenced in RFC 4519.
  */
 final class IntegerOrderingMatchingRuleImpl extends
     AbstractOrderingMatchingRuleImpl
 {
 
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     try
     {
@@ -59,8 +59,8 @@
       StaticUtils.DEBUG_LOG.throwing("IntegerOrderingMatchingRule",
           "normalizeAttributeValue", e);
 
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_ILLEGAL_INTEGER.get(value.toString());
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_ILLEGAL_INTEGER
+          .get(value.toString());
       throw DecodeException.error(message);
     }
   }
diff --git a/sdk/src/org/opends/sdk/schema/IntegerSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/IntegerSyntaxImpl.java
index 8fab889..754f921 100644
--- a/sdk/src/org/opends/sdk/schema/IntegerSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/IntegerSyntaxImpl.java
@@ -29,19 +29,24 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_INTEGER_DASH_NEEDS_VALUE;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_INTEGER_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_INTEGER_INITIAL_ZERO;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER;
+import static org.opends.sdk.schema.SchemaConstants.EMR_INTEGER_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_INTEGER_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_EXACT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_INTEGER_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
  * This class defines the integer attribute syntax, which holds an
- * arbitrarily-long integer value. Equality, ordering, and substring
- * matching will be allowed by default.
+ * arbitrarily-long integer value. Equality, ordering, and substring matching
+ * will be allowed by default.
  */
 final class IntegerSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -84,21 +89,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     final String valueString = value.toString();
     final int length = valueString.length();
@@ -129,8 +134,8 @@
             .get(valueString));
         return false;
       default:
-        invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER
-            .get(valueString, valueString.charAt(0), 0));
+        invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get(
+            valueString, valueString.charAt(0), 0));
         return false;
       }
     }
@@ -160,8 +165,8 @@
         negative = true;
         break;
       default:
-        invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER
-            .get(valueString, valueString.charAt(0), 0));
+        invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get(
+            valueString, valueString.charAt(0), 0));
         return false;
       }
 
@@ -188,8 +193,8 @@
         // These are all fine.
         break;
       default:
-        invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER
-            .get(valueString, valueString.charAt(0), 0));
+        invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get(
+            valueString, valueString.charAt(0), 0));
         return false;
       }
 
@@ -210,9 +215,8 @@
           // These are all fine.
           break;
         default:
-          invalidReason
-              .append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get(
-                  valueString, valueString.charAt(0), 0));
+          invalidReason.append(WARN_ATTR_SYNTAX_INTEGER_INVALID_CHARACTER.get(
+              valueString, valueString.charAt(0), 0));
           return false;
         }
       }
diff --git a/sdk/src/org/opends/sdk/schema/JPEGSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/JPEGSyntaxImpl.java
index c7afd9a..fe514ba 100644
--- a/sdk/src/org/opends/sdk/schema/JPEGSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/JPEGSyntaxImpl.java
@@ -29,19 +29,19 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_JPEG_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the JPEG attribute syntax. This should be
- * restricted to holding only JPEG image contents, but we will accept
- * any set of bytes. It will be treated much like the octet string
- * attribute syntax.
+ * This class implements the JPEG attribute syntax. This should be restricted to
+ * holding only JPEG image contents, but we will accept any set of bytes. It
+ * will be treated much like the octet string attribute syntax.
  */
 final class JPEGSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -76,21 +76,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // All values will be acceptable for the fax syntax.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/KeywordEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/KeywordEqualityMatchingRuleImpl.java
index c258116..9dbc99c 100644
--- a/sdk/src/org/opends/sdk/schema/KeywordEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/KeywordEqualityMatchingRuleImpl.java
@@ -28,18 +28,20 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.*;
 
 
 
 /**
- * This class implements the keywordMatch matching rule defined in
- * X.520. That document defines "keyword" as implementation-specific,
- * but in this case we will consider it a match if the assertion value
- * is contained within the attribute value and is bounded by the edge of
- * the value or any of the following characters: <BR>
+ * This class implements the keywordMatch matching rule defined in X.520. That
+ * document defines "keyword" as implementation-specific, but in this case we
+ * will consider it a match if the assertion value is contained within the
+ * attribute value and is bounded by the edge of the value or any of the
+ * following characters: <BR>
  * <UL>
  * <LI>A space</LI>
  * <LI>A period</LI>
@@ -53,18 +55,17 @@
  * <LI>An equal sign</LI>
  * </UL>
  */
-final class KeywordEqualityMatchingRuleImpl extends
-    AbstractMatchingRuleImpl
+final class KeywordEqualityMatchingRuleImpl extends AbstractMatchingRuleImpl
 {
   @Override
-  public Assertion getAssertion(Schema schema, ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     final String normalStr = normalize(value);
 
     return new Assertion()
     {
-      public ConditionResult matches(ByteSequence attributeValue)
+      public ConditionResult matches(final ByteSequence attributeValue)
       {
         // See if the assertion value is contained in the attribute
         // value. If not, then it isn't a match.
@@ -132,15 +133,15 @@
 
 
 
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     return ByteString.valueOf(normalize(value));
   }
 
 
 
-  private String normalize(ByteSequence value)
+  private String normalize(final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/LDAPSyntaxDescriptionSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/LDAPSyntaxDescriptionSyntaxImpl.java
index 1fb555a..80964d4 100644
--- a/sdk/src/org/opends/sdk/schema/LDAPSyntaxDescriptionSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/LDAPSyntaxDescriptionSyntaxImpl.java
@@ -30,7 +30,8 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OID_FIRST_COMPONENT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_LDAP_SYNTAX_NAME;
 
 import java.util.*;
 import java.util.regex.Pattern;
@@ -46,9 +47,9 @@
 
 
 /**
- * This class defines the LDAP syntax description syntax, which is used
- * to hold attribute syntax definitions in the schema. The format of
- * this syntax is defined in RFC 2252.
+ * This class defines the LDAP syntax description syntax, which is used to hold
+ * attribute syntax definitions in the schema. The format of this syntax is
+ * defined in RFC 2252.
  */
 final class LDAPSyntaxDescriptionSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -75,8 +76,8 @@
 
 
 
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We'll use the decodeNameForm method to determine if the value is
     // acceptable.
@@ -93,8 +94,8 @@
       {
         // This means that the value was empty or contained only
         // whitespace. That is illegal.
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_ATTRSYNTAX_EMPTY_VALUE.get();
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_ATTRSYNTAX_EMPTY_VALUE
+            .get();
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("LDAPSyntaxDescriptionSyntax",
             "valueIsAcceptable", e);
@@ -106,9 +107,8 @@
       final char c = reader.read();
       if (c != '(')
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_ATTRSYNTAX_EXPECTED_OPEN_PARENTHESIS.get(
-                definition, (reader.pos() - 1), String.valueOf(c));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_ATTRSYNTAX_EXPECTED_OPEN_PARENTHESIS
+            .get(definition, (reader.pos() - 1), String.valueOf(c));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("LDAPSyntaxDescriptionSyntax",
             "valueIsAcceptable", e);
@@ -122,8 +122,7 @@
       // The next set of characters must be the OID.
       final String oid = SchemaUtils.readOID(reader);
 
-      Map<String, List<String>> extraProperties =
-          Collections.emptyMap();
+      Map<String, List<String>> extraProperties = Collections.emptyMap();
       // At this point, we should have a pretty specific syntax that
       // describes what may come next, but some of the components are
       // optional and it would be pretty easy to put something in the
@@ -158,13 +157,12 @@
           {
             extraProperties = new HashMap<String, List<String>>();
           }
-          extraProperties.put(tokenName, SchemaUtils
-              .readExtensions(reader));
+          extraProperties.put(tokenName, SchemaUtils.readExtensions(reader));
         }
         else
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
+              .get(tokenName);
           final DecodeException e = DecodeException.error(message);
           StaticUtils.DEBUG_LOG.throwing("LDAPSyntaxDescriptionSyntax",
               "valueIsAcceptable", e);
@@ -177,8 +175,7 @@
       {
         if (property.getKey().equalsIgnoreCase("x-pattern"))
         {
-          final Iterator<String> values =
-              property.getValue().iterator();
+          final Iterator<String> values = property.getValue().iterator();
           if (values.hasNext())
           {
             final String pattern = values.next();
@@ -188,14 +185,11 @@
             }
             catch (final Exception e)
             {
-              final LocalizableMessage message =
-                  WARN_ATTR_SYNTAX_LDAPSYNTAX_REGEX_INVALID_PATTERN
-                      .get(oid, pattern);
-              final DecodeException de =
-                  DecodeException.error(message, e);
-              StaticUtils.DEBUG_LOG.throwing(
-                  "LDAPSyntaxDescriptionSyntax", "valueIsAcceptable",
-                  de);
+              final LocalizableMessage message = WARN_ATTR_SYNTAX_LDAPSYNTAX_REGEX_INVALID_PATTERN
+                  .get(oid, pattern);
+              final DecodeException de = DecodeException.error(message, e);
+              StaticUtils.DEBUG_LOG.throwing("LDAPSyntaxDescriptionSyntax",
+                  "valueIsAcceptable", de);
               throw de;
             }
             break;
@@ -211,13 +205,11 @@
             {
               if (entry.equals(values.get(j)))
               {
-                final LocalizableMessage message =
-                    WARN_ATTR_SYNTAX_LDAPSYNTAX_ENUM_DUPLICATE_VALUE
-                        .get(oid, entry, j);
+                final LocalizableMessage message = WARN_ATTR_SYNTAX_LDAPSYNTAX_ENUM_DUPLICATE_VALUE
+                    .get(oid, entry, j);
                 final DecodeException e = DecodeException.error(message);
-                StaticUtils.DEBUG_LOG.throwing(
-                    "LDAPSyntaxDescriptionSyntax", "valueIsAcceptable",
-                    e);
+                StaticUtils.DEBUG_LOG.throwing("LDAPSyntaxDescriptionSyntax",
+                    "valueIsAcceptable", e);
                 throw e;
               }
             }
diff --git a/sdk/src/org/opends/sdk/schema/MatchingRule.java b/sdk/src/org/opends/sdk/schema/MatchingRule.java
index daed051..3343f7d 100644
--- a/sdk/src/org/opends/sdk/schema/MatchingRule.java
+++ b/sdk/src/org/opends/sdk/schema/MatchingRule.java
@@ -22,14 +22,15 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk.schema;
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_MR_UNKNOWN_SYNTAX;
+import static com.sun.opends.sdk.messages.Messages.WARN_MATCHING_RULE_NOT_IMPLEMENTED;
 
 import java.util.Comparator;
 import java.util.Iterator;
@@ -43,20 +44,19 @@
 
 
 /**
- * This class defines a data structure for storing and interacting with
- * matching rules, which are used by servers to compare attribute values
- * against assertion values when performing Search and Compare
- * operations. They are also used to identify the value to be added or
- * deleted when modifying entries, and are used when comparing a
- * purported distinguished name with the name of an entry.
+ * This class defines a data structure for storing and interacting with matching
+ * rules, which are used by servers to compare attribute values against
+ * assertion values when performing Search and Compare operations. They are also
+ * used to identify the value to be added or deleted when modifying entries, and
+ * are used when comparing a purported distinguished name with the name of an
+ * entry.
  * <p>
  * Matching rule implementations must extend the
- * <code>MatchingRuleImplementation</code> class so they can be used by
- * OpenDS.
+ * <code>MatchingRuleImplementation</code> class so they can be used by OpenDS.
  * <p>
- * Where ordered sets of names, or extra properties are provided, the
- * ordering will be preserved when the associated fields are accessed
- * via their getters or via the {@link #toString()} methods.
+ * Where ordered sets of names, or extra properties are provided, the ordering
+ * will be preserved when the associated fields are accessed via their getters
+ * or via the {@link #toString()} methods.
  */
 public final class MatchingRule extends SchemaElement
 {
@@ -71,10 +71,10 @@
 
 
 
-  MatchingRule(String oid, List<String> names, String description,
-      boolean obsolete, String syntax,
-      Map<String, List<String>> extraProperties, String definition,
-      MatchingRuleImpl implementation)
+  MatchingRule(final String oid, final List<String> names,
+      final String description, final boolean obsolete, final String syntax,
+      final Map<String, List<String>> extraProperties, final String definition,
+      final MatchingRuleImpl implementation)
   {
     super(description, extraProperties);
 
@@ -102,8 +102,8 @@
    * Get a comparator that can be used to compare the attribute values
    * normalized by this matching rule.
    *
-   * @return A comparator that can be used to compare the attribute
-   *         values normalized by this matching rule.
+   * @return A comparator that can be used to compare the attribute values
+   *         normalized by this matching rule.
    */
   public Comparator<ByteSequence> comparator()
   {
@@ -113,10 +113,36 @@
 
 
   /**
-   * Retrieves the normalized form of the provided assertion value,
-   * which is best suite for efficiently performing matching operations
-   * on that value. The assertion value is guarenteed to be valid
-   * against this matching rule's assertion syntax.
+   * {@inheritDoc}
+   */
+  @Override
+  public boolean equals(final Object o)
+  {
+    if (o == null)
+    {
+      return false;
+    }
+
+    if (this == o)
+    {
+      return true;
+    }
+
+    if (!(o instanceof MatchingRule))
+    {
+      return false;
+    }
+
+    return getOID().equals(((MatchingRule) o).getOID());
+  }
+
+
+
+  /**
+   * Returns the normalized form of the provided assertion value, which is best
+   * suite for efficiently performing matching operations on that value. The
+   * assertion value is guarenteed to be valid against this matching rule's
+   * assertion syntax.
    *
    * @param value
    *          The syntax checked assertion value to be normalized.
@@ -124,7 +150,7 @@
    * @throws DecodeException
    *           if the syntax of the value is not valid.
    */
-  public Assertion getAssertion(ByteSequence value)
+  public Assertion getAssertion(final ByteSequence value)
       throws DecodeException
   {
     return impl.getAssertion(schema, value);
@@ -133,39 +159,37 @@
 
 
   /**
-   * Retrieves the normalized form of the provided assertion substring
-   * values, which is best suite for efficiently performing matching
-   * operations on that value.
+   * Returns the normalized form of the provided assertion substring values,
+   * which is best suite for efficiently performing matching operations on that
+   * value.
    *
    * @param subInitial
-   *          The normalized substring value fragment that should appear
-   *          at the beginning of the target value.
+   *          The normalized substring value fragment that should appear at the
+   *          beginning of the target value.
    * @param subAnyElements
-   *          The normalized substring value fragments that should
-   *          appear in the middle of the target value.
+   *          The normalized substring value fragments that should appear in the
+   *          middle of the target value.
    * @param subFinal
-   *          The normalized substring value fragment that should appear
-   *          at the end of the target value.
+   *          The normalized substring value fragment that should appear at the
+   *          end of the target value.
    * @return The normalized version of the provided assertion value.
    * @throws DecodeException
    *           if the syntax of the value is not valid.
    */
-  public Assertion getAssertion(ByteSequence subInitial,
-      List<? extends ByteSequence> subAnyElements, ByteSequence subFinal)
-      throws DecodeException
+  public Assertion getAssertion(final ByteSequence subInitial,
+      final List<? extends ByteSequence> subAnyElements,
+      final ByteSequence subFinal) throws DecodeException
   {
-    return impl.getAssertion(schema, subInitial, subAnyElements,
-        subFinal);
+    return impl.getAssertion(schema, subInitial, subAnyElements, subFinal);
   }
 
 
 
   /**
-   * Retrieves the normalized form of the provided assertion value,
-   * which is best suite for efficiently performing greater than or
-   * equal ordering matching operations on that value. The assertion
-   * value is guarenteed to be valid against this matching rule's
-   * assertion syntax.
+   * Returns the normalized form of the provided assertion value, which is best
+   * suite for efficiently performing greater than or equal ordering matching
+   * operations on that value. The assertion value is guarenteed to be valid
+   * against this matching rule's assertion syntax.
    *
    * @param value
    *          The syntax checked assertion value to be normalized.
@@ -173,7 +197,7 @@
    * @throws DecodeException
    *           if the syntax of the value is not valid.
    */
-  public Assertion getGreaterOrEqualAssertion(ByteSequence value)
+  public Assertion getGreaterOrEqualAssertion(final ByteSequence value)
       throws DecodeException
   {
     return impl.getGreaterOrEqualAssertion(schema, value);
@@ -182,11 +206,10 @@
 
 
   /**
-   * Retrieves the normalized form of the provided assertion value,
-   * which is best suite for efficiently performing greater than or
-   * equal ordering matching operations on that value. The assertion
-   * value is guarenteed to be valid against this matching rule's
-   * assertion syntax.
+   * Returns the normalized form of the provided assertion value, which is best
+   * suite for efficiently performing greater than or equal ordering matching
+   * operations on that value. The assertion value is guarenteed to be valid
+   * against this matching rule's assertion syntax.
    *
    * @param value
    *          The syntax checked assertion value to be normalized.
@@ -194,7 +217,7 @@
    * @throws DecodeException
    *           if the syntax of the value is not valid.
    */
-  public Assertion getLessOrEqualAssertion(ByteSequence value)
+  public Assertion getLessOrEqualAssertion(final ByteSequence value)
       throws DecodeException
   {
     return impl.getLessOrEqualAssertion(schema, value);
@@ -203,9 +226,9 @@
 
 
   /**
-   * Retrieves the name or OID for this schema definition. If it has one
-   * or more names, then the primary name will be returned. If it does
-   * not have any names, then the OID will be returned.
+   * Returns the name or OID for this schema definition. If it has one or more
+   * names, then the primary name will be returned. If it does not have any
+   * names, then the OID will be returned.
    *
    * @return The name or OID for this schema definition.
    */
@@ -221,13 +244,13 @@
 
 
   /**
-   * Retrieves an iterable over the set of user-defined names that may
-   * be used to reference this schema definition.
+   * Returns an unmodifiable list containing the user-defined names that may be
+   * used to reference this schema definition.
    *
-   * @return Returns an iterable over the set of user-defined names that
+   * @return Returns an unmodifiable list containing the user-defined names that
    *         may be used to reference this schema definition.
    */
-  public Iterable<String> getNames()
+  public List<String> getNames()
   {
     return names;
   }
@@ -235,7 +258,7 @@
 
 
   /**
-   * Retrieves the OID for this schema definition.
+   * Returns the OID for this schema definition.
    *
    * @return The OID for this schema definition.
    */
@@ -248,11 +271,11 @@
 
 
   /**
-   * Retrieves the OID of the assertion value syntax with which this
-   * matching rule is associated.
+   * Returns the OID of the assertion value syntax with which this matching rule
+   * is associated.
    *
-   * @return The OID of the assertion value syntax with which this
-   *         matching rule is associated.
+   * @return The OID of the assertion value syntax with which this matching rule
+   *         is associated.
    */
   public Syntax getSyntax()
   {
@@ -261,6 +284,9 @@
 
 
 
+  /**
+   * {@inheritDoc}
+   */
   @Override
   public int hashCode()
   {
@@ -274,10 +300,10 @@
    *
    * @param name
    *          The name for which to make the determination.
-   * @return <code>true</code> if the specified name is assigned to this
-   *         schema definition, or <code>false</code> if not.
+   * @return <code>true</code> if the specified name is assigned to this schema
+   *         definition, or <code>false</code> if not.
    */
-  public boolean hasName(String name)
+  public boolean hasName(final String name)
   {
     for (final String n : names)
     {
@@ -292,16 +318,15 @@
 
 
   /**
-   * Indicates whether this schema definition has the specified name or
-   * OID.
+   * Indicates whether this schema definition has the specified name or OID.
    *
    * @param value
    *          The value for which to make the determination.
-   * @return <code>true</code> if the provided value matches the OID or
-   *         one of the names assigned to this schema definition, or
-   *         <code>false</code> if not.
+   * @return <code>true</code> if the provided value matches the OID or one of
+   *         the names assigned to this schema definition, or <code>false</code>
+   *         if not.
    */
-  public boolean hasNameOrOID(String value)
+  public boolean hasNameOrOID(final String value)
   {
     return hasName(value) || getOID().equals(value);
   }
@@ -311,8 +336,8 @@
   /**
    * Indicates whether this schema definition is declared "obsolete".
    *
-   * @return <code>true</code> if this schema definition is declared
-   *         "obsolete", or <code>false</code> if not.
+   * @return <code>true</code> if this schema definition is declared "obsolete",
+   *         or <code>false</code> if not.
    */
   public boolean isObsolete()
   {
@@ -322,9 +347,8 @@
 
 
   /**
-   * Retrieves the normalized form of the provided attribute value,
-   * which is best suite for efficiently performing matching operations
-   * on that value.
+   * Returns the normalized form of the provided attribute value, which is best
+   * suite for efficiently performing matching operations on that value.
    *
    * @param value
    *          The attribute value to be normalized.
@@ -332,7 +356,7 @@
    * @throws DecodeException
    *           if the syntax of the value is not valid.
    */
-  public ByteString normalizeAttributeValue(ByteSequence value)
+  public ByteString normalizeAttributeValue(final ByteSequence value)
       throws DecodeException
   {
     return impl.normalizeAttributeValue(schema, value);
@@ -341,11 +365,11 @@
 
 
   /**
-   * Retrieves the string representation of this schema definition in
-   * the form specified in RFC 2252.
+   * Returns the string representation of this schema definition in the form
+   * specified in RFC 2252.
    *
-   * @return The string representation of this schema definition in the
-   *         form specified in RFC 2252.
+   * @return The string representation of this schema definition in the form
+   *         specified in RFC 2252.
    */
   @Override
   public String toString()
@@ -357,14 +381,14 @@
 
   MatchingRule duplicate()
   {
-    return new MatchingRule(oid, names, description, isObsolete,
-        syntaxOID, extraProperties, definition, impl);
+    return new MatchingRule(oid, names, description, isObsolete, syntaxOID,
+        extraProperties, definition, impl);
   }
 
 
 
   @Override
-  void toStringContent(StringBuilder buffer)
+  void toStringContent(final StringBuilder buffer)
   {
     buffer.append(oid);
 
@@ -413,7 +437,7 @@
 
 
   @Override
-  void validate(List<LocalizableMessage> warnings, Schema schema)
+  void validate(final List<LocalizableMessage> warnings, final Schema schema)
       throws SchemaException
   {
     // Try finding an implementation in the core schema
@@ -429,9 +453,8 @@
     if (impl == null)
     {
       impl = Schema.getDefaultMatchingRule().impl;
-      final LocalizableMessage message =
-          WARN_MATCHING_RULE_NOT_IMPLEMENTED.get(oid, Schema
-              .getDefaultMatchingRule().getOID());
+      final LocalizableMessage message = WARN_MATCHING_RULE_NOT_IMPLEMENTED
+          .get(oid, Schema.getDefaultMatchingRule().getOID());
       warnings.add(message);
     }
 
@@ -442,9 +465,8 @@
     }
     catch (final UnknownSchemaElementException e)
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_MR_UNKNOWN_SYNTAX.get(getNameOrOID(),
-              syntaxOID);
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_MR_UNKNOWN_SYNTAX.get(
+          getNameOrOID(), syntaxOID);
       throw new SchemaException(message, e);
     }
 
diff --git a/sdk/src/org/opends/sdk/schema/MatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/MatchingRuleImpl.java
index 2c526d2..d29b53f 100644
--- a/sdk/src/org/opends/sdk/schema/MatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/MatchingRuleImpl.java
@@ -39,30 +39,30 @@
 
 
 /**
- * This interface defines the set of methods that must be implemented to
- * define a new matching rule.
+ * This interface defines the set of methods that must be implemented to define
+ * a new matching rule.
  */
 public interface MatchingRuleImpl
 {
   /**
    * Get a comparator that can be used to compare the attribute values
    * normalized by this matching rule.
-   * 
+   *
    * @param schema
    *          The schema in which this matching rule is defined.
-   * @return A comparator that can be used to compare the attribute
-   *         values normalized by this matching rule.
+   * @return A comparator that can be used to compare the attribute values
+   *         normalized by this matching rule.
    */
   public Comparator<ByteSequence> comparator(Schema schema);
 
 
 
   /**
-   * Retrieves the normalized form of the provided assertion value,
-   * which is best suite for efficiently performing matching operations
-   * on that value. The assertion value is guarenteed to be valid
-   * against this matching rule's assertion syntax.
-   * 
+   * Retrieves the normalized form of the provided assertion value, which is
+   * best suite for efficiently performing matching operations on that value.
+   * The assertion value is guarenteed to be valid against this matching rule's
+   * assertion syntax.
+   *
    * @param schema
    *          The schema in which this matching rule is defined.
    * @param value
@@ -77,21 +77,21 @@
 
 
   /**
-   * Retrieves the normalized form of the provided assertion substring
-   * values, which is best suite for efficiently performing matching
-   * operations on that value.
-   * 
+   * Retrieves the normalized form of the provided assertion substring values,
+   * which is best suite for efficiently performing matching operations on that
+   * value.
+   *
    * @param schema
    *          The schema in which this matching rule is defined.
    * @param subInitial
-   *          The normalized substring value fragment that should appear
-   *          at the beginning of the target value.
+   *          The normalized substring value fragment that should appear at the
+   *          beginning of the target value.
    * @param subAnyElements
-   *          The normalized substring value fragments that should
-   *          appear in the middle of the target value.
+   *          The normalized substring value fragments that should appear in the
+   *          middle of the target value.
    * @param subFinal
-   *          The normalized substring value fragment that should appear
-   *          at the end of the target value.
+   *          The normalized substring value fragment that should appear at the
+   *          end of the target value.
    * @return The normalized version of the provided assertion value.
    * @throws DecodeException
    *           if an syntax error occured while parsing the value.
@@ -103,12 +103,11 @@
 
 
   /**
-   * Retrieves the normalized form of the provided assertion value,
-   * which is best suite for efficiently performing greater than or
-   * equal matching operations on that value. The assertion value is
-   * guarenteed to be valid against this matching rule's assertion
-   * syntax.
-   * 
+   * Retrieves the normalized form of the provided assertion value, which is
+   * best suite for efficiently performing greater than or equal matching
+   * operations on that value. The assertion value is guarenteed to be valid
+   * against this matching rule's assertion syntax.
+   *
    * @param schema
    *          The schema in which this matching rule is defined.
    * @param value
@@ -117,18 +116,17 @@
    * @throws DecodeException
    *           if an syntax error occured while parsing the value.
    */
-  public Assertion getGreaterOrEqualAssertion(Schema schema,
-      ByteSequence value) throws DecodeException;
+  public Assertion getGreaterOrEqualAssertion(Schema schema, ByteSequence value)
+      throws DecodeException;
 
 
 
   /**
-   * Retrieves the normalized form of the provided assertion value,
-   * which is best suite for efficiently performing greater than or
-   * equal matching operations on that value. The assertion value is
-   * guarenteed to be valid against this matching rule's assertion
-   * syntax.
-   * 
+   * Retrieves the normalized form of the provided assertion value, which is
+   * best suite for efficiently performing greater than or equal matching
+   * operations on that value. The assertion value is guarenteed to be valid
+   * against this matching rule's assertion syntax.
+   *
    * @param schema
    *          The schema in which this matching rule is defined.
    * @param value
@@ -137,16 +135,15 @@
    * @throws DecodeException
    *           if an syntax error occured while parsing the value.
    */
-  public Assertion getLessOrEqualAssertion(Schema schema,
-      ByteSequence value) throws DecodeException;
+  public Assertion getLessOrEqualAssertion(Schema schema, ByteSequence value)
+      throws DecodeException;
 
 
 
   /**
-   * Retrieves the normalized form of the provided attribute value,
-   * which is best suite for efficiently performing matching operations
-   * on that value.
-   * 
+   * Retrieves the normalized form of the provided attribute value, which is
+   * best suite for efficiently performing matching operations on that value.
+   *
    * @param schema
    *          The schema in which this matching rule is defined.
    * @param value
@@ -155,6 +152,6 @@
    * @throws DecodeException
    *           if an syntax error occured while parsing the value.
    */
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException;
+  public ByteString normalizeAttributeValue(Schema schema, ByteSequence value)
+      throws DecodeException;
 }
diff --git a/sdk/src/org/opends/sdk/schema/MatchingRuleSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/MatchingRuleSyntaxImpl.java
index 7bdb643..0de0869 100644
--- a/sdk/src/org/opends/sdk/schema/MatchingRuleSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/MatchingRuleSyntaxImpl.java
@@ -29,8 +29,12 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_ILLEGAL_TOKEN;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_MR_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_MR_EXPECTED_OPEN_PARENTHESIS;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_MR_NO_SYNTAX;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OID_FIRST_COMPONENT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_MATCHING_RULE_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DecodeException;
@@ -43,9 +47,9 @@
 
 
 /**
- * This class implements the matching rule description syntax, which is
- * used to hold matching rule definitions in the server schema. The
- * format of this syntax is defined in RFC 2252.
+ * This class implements the matching rule description syntax, which is used to
+ * hold matching rule definitions in the server schema. The format of this
+ * syntax is defined in RFC 2252.
  */
 final class MatchingRuleSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -73,21 +77,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We'll use the decodeMatchingRule method to determine if the value
     // is acceptable.
@@ -116,9 +120,8 @@
       final char c = reader.read();
       if (c != '(')
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_MR_EXPECTED_OPEN_PARENTHESIS.get(
-                definition, (reader.pos() - 1), String.valueOf(c));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_MR_EXPECTED_OPEN_PARENTHESIS
+            .get(definition, (reader.pos() - 1), String.valueOf(c));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("MatchingRuleSyntax",
             "valueIsAcceptable", e);
@@ -182,8 +185,8 @@
         }
         else
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
+              .get(tokenName);
           final DecodeException e = DecodeException.error(message);
           StaticUtils.DEBUG_LOG.throwing("MatchingRuleSyntax",
               "valueIsAcceptable", e);
@@ -194,8 +197,8 @@
       // Make sure that a syntax was specified.
       if (syntax == null)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_MR_NO_SYNTAX.get(definition);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_MR_NO_SYNTAX
+            .get(definition);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("MatchingRuleSyntax",
             "valueIsAcceptable", e);
diff --git a/sdk/src/org/opends/sdk/schema/MatchingRuleUse.java b/sdk/src/org/opends/sdk/schema/MatchingRuleUse.java
index 7d59b2c..6efee7f 100644
--- a/sdk/src/org/opends/sdk/schema/MatchingRuleUse.java
+++ b/sdk/src/org/opends/sdk/schema/MatchingRuleUse.java
@@ -29,7 +29,8 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_MRUSE_UNKNOWN_ATTR;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_MRUSE_UNKNOWN_MATCHING_RULE;
 
 import java.util.*;
 
@@ -40,9 +41,9 @@
 
 
 /**
- * This class defines a data structure for storing and interacting with
- * a matching rule use definition, which may be used to restrict the set
- * of attribute types that may be used for a given matching rule.
+ * This class defines a data structure for storing and interacting with a
+ * matching rule use definition, which may be used to restrict the set of
+ * attribute types that may be used for a given matching rule.
  */
 public final class MatchingRuleUse extends SchemaElement
 {
@@ -68,9 +69,10 @@
 
 
 
-  MatchingRuleUse(String oid, List<String> names, String description,
-      boolean obsolete, Set<String> attributeOIDs,
-      Map<String, List<String>> extraProperties, String definition)
+  MatchingRuleUse(final String oid, final List<String> names,
+      final String description, final boolean obsolete,
+      final Set<String> attributeOIDs,
+      final Map<String, List<String>> extraProperties, final String definition)
   {
     super(description, extraProperties);
 
@@ -93,13 +95,13 @@
 
 
   /**
-   * Retrieves the set of attributes associated with this matching rule
-   * use.
-   * 
-   * @return The set of attributes associated with this matching rule
-   *         use.
+   * Returns an unmodifiable set containing the attributes associated with this
+   * matching rule use.
+   *
+   * @return An unmodifiable set containing the attributes associated with this
+   *         matching rule use.
    */
-  public Iterable<AttributeType> getAttributes()
+  public Set<AttributeType> getAttributes()
   {
     return attributes;
   }
@@ -107,8 +109,8 @@
 
 
   /**
-   * Retrieves the matching rule for this matching rule use.
-   * 
+   * Returns the matching rule for this matching rule use.
+   *
    * @return The matching rule for this matching rule use.
    */
   public MatchingRule getMatchingRule()
@@ -119,8 +121,8 @@
 
 
   /**
-   * Retrieves the matching rule OID for this schema definition.
-   * 
+   * Returns the matching rule OID for this schema definition.
+   *
    * @return The OID for this schema definition.
    */
   public String getMatchingRuleOID()
@@ -131,11 +133,10 @@
 
 
   /**
-   * Retrieves the name or matching rule OID for this schema definition.
-   * If it has one or more names, then the primary name will be
-   * returned. If it does not have any names, then the OID will be
-   * returned.
-   * 
+   * Returns the name or matching rule OID for this schema definition. If it has
+   * one or more names, then the primary name will be returned. If it does not
+   * have any names, then the OID will be returned.
+   *
    * @return The name or OID for this schema definition.
    */
   public String getNameOrOID()
@@ -150,13 +151,13 @@
 
 
   /**
-   * Retrieves an iterable over the set of user-defined names that may
-   * be used to reference this schema definition.
-   * 
-   * @return Returns an iterable over the set of user-defined names that
+   * Returns an unmodifiable list containing the user-defined names that may be
+   * used to reference this schema definition.
+   *
+   * @return Returns an unmodifiable list containing the user-defined names that
    *         may be used to reference this schema definition.
    */
-  public Iterable<String> getNames()
+  public List<String> getNames()
   {
     return names;
   }
@@ -166,13 +167,13 @@
   /**
    * Indicates whether the provided attribute type is referenced by this
    * matching rule use.
-   * 
+   *
    * @param attributeType
    *          The attribute type for which to make the determination.
-   * @return {@code true} if the provided attribute type is referenced
-   *         by this matching rule use, or {@code false} if it is not.
+   * @return {@code true} if the provided attribute type is referenced by this
+   *         matching rule use, or {@code false} if it is not.
    */
-  public boolean hasAttribute(AttributeType attributeType)
+  public boolean hasAttribute(final AttributeType attributeType)
   {
     return attributes.contains(attributeType);
   }
@@ -189,13 +190,13 @@
 
   /**
    * Indicates whether this schema definition has the specified name.
-   * 
+   *
    * @param name
    *          The name for which to make the determination.
-   * @return <code>true</code> if the specified name is assigned to this
-   *         schema definition, or <code>false</code> if not.
+   * @return <code>true</code> if the specified name is assigned to this schema
+   *         definition, or <code>false</code> if not.
    */
-  public boolean hasName(String name)
+  public boolean hasName(final String name)
   {
     for (final String n : names)
     {
@@ -210,16 +211,16 @@
 
 
   /**
-   * Indicates whether this schema definition has the specified name or
-   * matching rule OID.
-   * 
+   * Indicates whether this schema definition has the specified name or matching
+   * rule OID.
+   *
    * @param value
    *          The value for which to make the determination.
-   * @return <code>true</code> if the provided value matches the OID or
-   *         one of the names assigned to this schema definition, or
-   *         <code>false</code> if not.
+   * @return <code>true</code> if the provided value matches the OID or one of
+   *         the names assigned to this schema definition, or <code>false</code>
+   *         if not.
    */
-  public boolean hasNameOrOID(String value)
+  public boolean hasNameOrOID(final String value)
   {
     return hasName(value) || oid.equals(value);
   }
@@ -228,9 +229,9 @@
 
   /**
    * Indicates whether this schema definition is declared "obsolete".
-   * 
-   * @return <code>true</code> if this schema definition is declared
-   *         "obsolete", or <code>false</code> if not.
+   *
+   * @return <code>true</code> if this schema definition is declared "obsolete",
+   *         or <code>false</code> if not.
    */
   public boolean isObsolete()
   {
@@ -240,11 +241,11 @@
 
 
   /**
-   * Retrieves the string representation of this schema definition in
-   * the form specified in RFC 2252.
-   * 
-   * @return The string representation of this schema definition in the
-   *         form specified in RFC 2252.
+   * Returns the string representation of this schema definition in the form
+   * specified in RFC 2252.
+   *
+   * @return The string representation of this schema definition in the form
+   *         specified in RFC 2252.
    */
   @Override
   public String toString()
@@ -263,7 +264,7 @@
 
 
   @Override
-  void toStringContent(StringBuilder buffer)
+  void toStringContent(final StringBuilder buffer)
   {
     buffer.append(oid);
 
@@ -334,7 +335,7 @@
 
 
   @Override
-  void validate(List<LocalizableMessage> warnings, Schema schema)
+  void validate(final List<LocalizableMessage> warnings, final Schema schema)
       throws SchemaException
   {
     try
@@ -345,9 +346,8 @@
     {
       // This is bad because the matching rule use is associated with a
       // matching rule that we don't know anything about.
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_MRUSE_UNKNOWN_MATCHING_RULE.get(definition,
-              oid);
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_MRUSE_UNKNOWN_MATCHING_RULE
+          .get(definition, oid);
       throw new SchemaException(message, e);
     }
 
@@ -361,11 +361,12 @@
       }
       catch (final UnknownSchemaElementException e)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_MRUSE_UNKNOWN_ATTR.get(oid, attribute);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_MRUSE_UNKNOWN_ATTR
+            .get(oid, attribute);
         throw new SchemaException(message, e);
       }
       attributes.add(attributeType);
     }
+    attributes = Collections.unmodifiableSet(attributes);
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/MatchingRuleUseSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/MatchingRuleUseSyntaxImpl.java
index 4440012..9728454 100644
--- a/sdk/src/org/opends/sdk/schema/MatchingRuleUseSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/MatchingRuleUseSyntaxImpl.java
@@ -29,8 +29,12 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_ILLEGAL_TOKEN;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_MRUSE_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_MRUSE_EXPECTED_OPEN_PARENTHESIS;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_MRUSE_NO_ATTR;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OID_FIRST_COMPONENT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_MATCHING_RULE_USE_NAME;
 
 import java.util.Set;
 
@@ -45,9 +49,9 @@
 
 
 /**
- * This class implements the matching rule use description syntax, which
- * is used to hold matching rule use definitions in the server schema.
- * The format of this syntax is defined in RFC 2252.
+ * This class implements the matching rule use description syntax, which is used
+ * to hold matching rule use definitions in the server schema. The format of
+ * this syntax is defined in RFC 2252.
  */
 final class MatchingRuleUseSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -75,21 +79,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We'll use the decodeAttributeType method to determine if the
     // value is acceptable.
@@ -106,7 +110,8 @@
       {
         // This means that the value was empty or contained only
         // whitespace. That is illegal.
-        final LocalizableMessage message = ERR_ATTR_SYNTAX_MRUSE_EMPTY_VALUE.get();
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_MRUSE_EMPTY_VALUE
+            .get();
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("MatchingRuleUseSyntax",
             "valueIsAcceptable", e);
@@ -118,9 +123,8 @@
       final char c = reader.read();
       if (c != '(')
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_MRUSE_EXPECTED_OPEN_PARENTHESIS.get(
-                definition, (reader.pos() - 1), String.valueOf(c));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_MRUSE_EXPECTED_OPEN_PARENTHESIS
+            .get(definition, (reader.pos() - 1), String.valueOf(c));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("MatchingRuleUseSyntax",
             "valueIsAcceptable", e);
@@ -184,8 +188,8 @@
         }
         else
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
+              .get(tokenName);
           final DecodeException e = DecodeException.error(message);
           StaticUtils.DEBUG_LOG.throwing("MatchingRuleUseSyntax",
               "valueIsAcceptable", e);
@@ -196,8 +200,8 @@
       // Make sure that the set of attributes was defined.
       if (attributes == null || attributes.size() == 0)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_MRUSE_NO_ATTR.get(definition);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_MRUSE_NO_ATTR
+            .get(definition);
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("MatchingRuleUseSyntax",
             "valueIsAcceptable", e);
diff --git a/sdk/src/org/opends/sdk/schema/NameAndOptionalUIDSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/NameAndOptionalUIDSyntaxImpl.java
index bcc80a5..f0367e0 100644
--- a/sdk/src/org/opends/sdk/schema/NameAndOptionalUIDSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/NameAndOptionalUIDSyntaxImpl.java
@@ -29,21 +29,23 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_NAMEANDUID_ILLEGAL_BINARY_DIGIT;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_NAMEANDUID_INVALID_DN;
+import static org.opends.sdk.schema.SchemaConstants.EMR_UNIQUE_MEMBER_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_NAME_AND_OPTIONAL_UID_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DN;
-import org.opends.sdk.LocalizedIllegalArgumentException;
 import org.opends.sdk.LocalizableMessageBuilder;
-
+import org.opends.sdk.LocalizedIllegalArgumentException;
 
 
 
 /**
- * This class implements the name and optional UID attribute syntax,
- * which holds values consisting of a DN, optionally followed by an
- * octothorpe (#) and a bit string value.
+ * This class implements the name and optional UID attribute syntax, which holds
+ * values consisting of a DN, optionally followed by an octothorpe (#) and a bit
+ * string value.
  */
 final class NameAndOptionalUIDSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -79,21 +81,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     final String valueString = value.toString().trim();
     final int valueLength = valueString.length();
@@ -136,9 +138,8 @@
         if (!(c == '0' || c == '1'))
         {
 
-          invalidReason
-              .append(ERR_ATTR_SYNTAX_NAMEANDUID_ILLEGAL_BINARY_DIGIT
-                  .get(valueString, String.valueOf(c), i));
+          invalidReason.append(ERR_ATTR_SYNTAX_NAMEANDUID_ILLEGAL_BINARY_DIGIT
+              .get(valueString, String.valueOf(c), i));
           return false;
         }
       }
diff --git a/sdk/src/org/opends/sdk/schema/NameForm.java b/sdk/src/org/opends/sdk/schema/NameForm.java
index 30d73ef..6860c5c 100644
--- a/sdk/src/org/opends/sdk/schema/NameForm.java
+++ b/sdk/src/org/opends/sdk/schema/NameForm.java
@@ -29,7 +29,14 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_NAME_FORM_STRUCTURAL_CLASS_NOT_STRUCTURAL;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_OPTIONAL_ATTR;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_REQUIRED_ATTR;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_STRUCTURAL_CLASS;
 
 import java.util.*;
 
@@ -40,9 +47,9 @@
 
 
 /**
- * This class defines a data structure for storing and interacting with
- * a name form, which defines the attribute type(s) that must and/or may
- * be used in the RDN of an entry with a given structural objectclass.
+ * This class defines a data structure for storing and interacting with a name
+ * form, which defines the attribute type(s) that must and/or may be used in the
+ * RDN of an entry with a given structural objectclass.
  */
 public final class NameForm extends SchemaElement
 {
@@ -68,18 +75,16 @@
   private final String definition;
 
   private ObjectClass structuralClass;
-  private Set<AttributeType> optionalAttributes =
-      Collections.emptySet();
-  private Set<AttributeType> requiredAttributes =
-      Collections.emptySet();
+  private Set<AttributeType> optionalAttributes = Collections.emptySet();
+  private Set<AttributeType> requiredAttributes = Collections.emptySet();
 
 
 
-  NameForm(String oid, List<String> names, String description,
-      boolean obsolete, String structuralClassOID,
-      Set<String> requiredAttributeOIDs,
-      Set<String> optionalAttributeOIDs,
-      Map<String, List<String>> extraProperties, String definition)
+  NameForm(final String oid, final List<String> names,
+      final String description, final boolean obsolete,
+      final String structuralClassOID, final Set<String> requiredAttributeOIDs,
+      final Set<String> optionalAttributeOIDs,
+      final Map<String, List<String>> extraProperties, final String definition)
   {
     super(description, extraProperties);
 
@@ -108,10 +113,10 @@
 
 
   /**
-   * Retrieves the name or OID for this schema definition. If it has one
-   * or more names, then the primary name will be returned. If it does
-   * not have any names, then the OID will be returned.
-   * 
+   * Returns the name or OID for this schema definition. If it has one or more
+   * names, then the primary name will be returned. If it does not have any
+   * names, then the OID will be returned.
+   *
    * @return The name or OID for this schema definition.
    */
   public String getNameOrOID()
@@ -126,13 +131,13 @@
 
 
   /**
-   * Retrieves an iterable over the set of user-defined names that may
-   * be used to reference this schema definition.
-   * 
-   * @return Returns an iterable over the set of user-defined names that
+   * Returns an unmodifiable list containing the user-defined names that may be
+   * used to reference this schema definition.
+   *
+   * @return Returns an unmodifiable list containing the user-defined names that
    *         may be used to reference this schema definition.
    */
-  public Iterable<String> getNames()
+  public List<String> getNames()
   {
     return names;
   }
@@ -140,8 +145,8 @@
 
 
   /**
-   * Retrieves the OID for this schema definition.
-   * 
+   * Returns the OID for this schema definition.
+   *
    * @return The OID for this schema definition.
    */
   public String getOID()
@@ -153,11 +158,13 @@
 
 
   /**
-   * Retrieves the set of optional attributes for this name form.
-   * 
-   * @return The set of optional attributes for this name form.
+   * Returns an unmodifiable set containing the optional attributes for this
+   * name form.
+   *
+   * @return An unmodifiable set containing the optional attributes for this
+   *         name form.
    */
-  public Iterable<AttributeType> getOptionalAttributes()
+  public Set<AttributeType> getOptionalAttributes()
   {
     return optionalAttributes;
   }
@@ -165,11 +172,13 @@
 
 
   /**
-   * Retrieves the set of required attributes for this name form.
-   * 
-   * @return The set of required attributes for this name form.
+   * Returns an unmodifiable set containing the required attributes for this
+   * name form.
+   *
+   * @return An unmodifiable set containing the required attributes for this
+   *         name form.
    */
-  public Iterable<AttributeType> getRequiredAttributes()
+  public Set<AttributeType> getRequiredAttributes()
   {
     return requiredAttributes;
   }
@@ -177,11 +186,9 @@
 
 
   /**
-   * Retrieves the reference to the structural objectclass for this name
-   * form.
-   * 
-   * @return The reference to the structural objectclass for this name
-   *         form.
+   * Returns the reference to the structural objectclass for this name form.
+   *
+   * @return The reference to the structural objectclass for this name form.
    */
   public ObjectClass getStructuralClass()
   {
@@ -200,13 +207,13 @@
 
   /**
    * Indicates whether this schema definition has the specified name.
-   * 
+   *
    * @param name
    *          The name for which to make the determination.
-   * @return <code>true</code> if the specified name is assigned to this
-   *         schema definition, or <code>false</code> if not.
+   * @return <code>true</code> if the specified name is assigned to this schema
+   *         definition, or <code>false</code> if not.
    */
-  public boolean hasName(String name)
+  public boolean hasName(final String name)
   {
     for (final String n : names)
     {
@@ -221,16 +228,15 @@
 
 
   /**
-   * Indicates whether this schema definition has the specified name or
-   * OID.
-   * 
+   * Indicates whether this schema definition has the specified name or OID.
+   *
    * @param value
    *          The value for which to make the determination.
-   * @return <code>true</code> if the provided value matches the OID or
-   *         one of the names assigned to this schema definition, or
-   *         <code>false</code> if not.
+   * @return <code>true</code> if the provided value matches the OID or one of
+   *         the names assigned to this schema definition, or <code>false</code>
+   *         if not.
    */
-  public boolean hasNameOrOID(String value)
+  public boolean hasNameOrOID(final String value)
   {
     return hasName(value) || getOID().equals(value);
   }
@@ -239,9 +245,9 @@
 
   /**
    * Indicates whether this schema definition is declared "obsolete".
-   * 
-   * @return <code>true</code> if this schema definition is declared
-   *         "obsolete", or <code>false</code> if not.
+   *
+   * @return <code>true</code> if this schema definition is declared "obsolete",
+   *         or <code>false</code> if not.
    */
   public boolean isObsolete()
   {
@@ -251,11 +257,11 @@
 
 
   /**
-   * Retrieves the string representation of this schema definition in
-   * the form specified in RFC 2252.
-   * 
-   * @return The string representation of this schema definition in the
-   *         form specified in RFC 2252.
+   * Returns the string representation of this schema definition in the form
+   * specified in RFC 2252.
+   *
+   * @return The string representation of this schema definition in the form
+   *         specified in RFC 2252.
    */
   @Override
   public String toString()
@@ -268,14 +274,14 @@
   NameForm duplicate()
   {
     return new NameForm(oid, names, description, isObsolete,
-        structuralClassOID, requiredAttributeOIDs,
-        optionalAttributeOIDs, extraProperties, definition);
+        structuralClassOID, requiredAttributeOIDs, optionalAttributeOIDs,
+        extraProperties, definition);
   }
 
 
 
   @Override
-  void toStringContent(StringBuilder buffer)
+  void toStringContent(final StringBuilder buffer)
   {
     buffer.append(oid);
 
@@ -322,8 +328,7 @@
 
     if (!requiredAttributeOIDs.isEmpty())
     {
-      final Iterator<String> iterator =
-          requiredAttributeOIDs.iterator();
+      final Iterator<String> iterator = requiredAttributeOIDs.iterator();
 
       final String firstName = iterator.next();
       if (iterator.hasNext())
@@ -348,8 +353,7 @@
 
     if (!optionalAttributeOIDs.isEmpty())
     {
-      final Iterator<String> iterator =
-          optionalAttributeOIDs.iterator();
+      final Iterator<String> iterator = optionalAttributeOIDs.iterator();
 
       final String firstName = iterator.next();
       if (iterator.hasNext())
@@ -376,7 +380,7 @@
 
 
   @Override
-  void validate(List<LocalizableMessage> warnings, Schema schema)
+  void validate(final List<LocalizableMessage> warnings, final Schema schema)
       throws SchemaException
   {
     try
@@ -385,25 +389,22 @@
     }
     catch (final UnknownSchemaElementException e)
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_STRUCTURAL_CLASS.get(oid,
-              structuralClassOID);
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_STRUCTURAL_CLASS
+          .get(oid, structuralClassOID);
       throw new SchemaException(message, e);
     }
     if (structuralClass.getObjectClassType() != ObjectClassType.STRUCTURAL)
     {
       // This is bad because the associated structural class type is not
       // structural.
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_NAME_FORM_STRUCTURAL_CLASS_NOT_STRUCTURAL
-              .get(oid, structuralClass.getOID(), structuralClass
-                  .getNameOrOID(), String.valueOf(structuralClass
-                  .getObjectClassType()));
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_STRUCTURAL_CLASS_NOT_STRUCTURAL
+          .get(oid, structuralClass.getOID(), structuralClass.getNameOrOID(),
+              String.valueOf(structuralClass.getObjectClassType()));
       throw new SchemaException(message);
     }
 
-    requiredAttributes =
-        new HashSet<AttributeType>(requiredAttributeOIDs.size());
+    requiredAttributes = new HashSet<AttributeType>(requiredAttributeOIDs
+        .size());
     AttributeType attributeType;
     for (final String oid : requiredAttributeOIDs)
     {
@@ -415,9 +416,8 @@
       {
         // This isn't good because it means that the name form requires
         // an attribute type that we don't know anything about.
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_REQUIRED_ATTR.get(
-                this.oid, oid);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_REQUIRED_ATTR
+            .get(this.oid, oid);
         throw new SchemaException(message, e);
       }
       requiredAttributes.add(attributeType);
@@ -425,8 +425,8 @@
 
     if (!optionalAttributeOIDs.isEmpty())
     {
-      optionalAttributes =
-          new HashSet<AttributeType>(optionalAttributeOIDs.size());
+      optionalAttributes = new HashSet<AttributeType>(optionalAttributeOIDs
+          .size());
       for (final String oid : optionalAttributeOIDs)
       {
         try
@@ -438,13 +438,15 @@
           // This isn't good because it means that the name form
           // requires an attribute type that we don't know anything
           // about.
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_OPTIONAL_ATTR.get(
-                  this.oid, oid);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_UNKNOWN_OPTIONAL_ATTR
+              .get(this.oid, oid);
           throw new SchemaException(message, e);
         }
         optionalAttributes.add(attributeType);
       }
     }
+
+    optionalAttributes = Collections.unmodifiableSet(optionalAttributes);
+    requiredAttributes = Collections.unmodifiableSet(requiredAttributes);
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/NameFormSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/NameFormSyntaxImpl.java
index e57f3dd..74d50f5 100644
--- a/sdk/src/org/opends/sdk/schema/NameFormSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/NameFormSyntaxImpl.java
@@ -30,7 +30,8 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OID_FIRST_COMPONENT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_NAME_FORM_NAME;
 
 import java.util.Set;
 
@@ -45,9 +46,9 @@
 
 
 /**
- * This class implements the name form description syntax, which is used
- * to hold name form definitions in the server schema. The format of
- * this syntax is defined in RFC 2252.
+ * This class implements the name form description syntax, which is used to hold
+ * name form definitions in the server schema. The format of this syntax is
+ * defined in RFC 2252.
  */
 final class NameFormSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -74,8 +75,8 @@
 
 
 
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We'll use the decodeNameForm method to determine if the value is
     // acceptable.
@@ -92,11 +93,11 @@
       {
         // This means that the value was empty or contained only
         // whitespace. That is illegal.
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_NAME_FORM_EMPTY_VALUE.get();
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_EMPTY_VALUE
+            .get();
         final DecodeException e = DecodeException.error(message);
-        StaticUtils.DEBUG_LOG.throwing("NameFormSyntax",
-            "valueIsAcceptable", e);
+        StaticUtils.DEBUG_LOG
+            .throwing("NameFormSyntax", "valueIsAcceptable", e);
         throw e;
       }
 
@@ -105,12 +106,11 @@
       final char c = reader.read();
       if (c != '(')
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_NAME_FORM_EXPECTED_OPEN_PARENTHESIS.get(
-                definition, (reader.pos() - 1), c);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_EXPECTED_OPEN_PARENTHESIS
+            .get(definition, (reader.pos() - 1), c);
         final DecodeException e = DecodeException.error(message);
-        StaticUtils.DEBUG_LOG.throwing("NameFormSyntax",
-            "valueIsAcceptable", e);
+        StaticUtils.DEBUG_LOG
+            .throwing("NameFormSyntax", "valueIsAcceptable", e);
         throw e;
       }
 
@@ -181,11 +181,11 @@
         }
         else
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
+              .get(tokenName);
           final DecodeException e = DecodeException.error(message);
-          StaticUtils.DEBUG_LOG.throwing("NameFormSyntax",
-              "valueIsAcceptable", e);
+          StaticUtils.DEBUG_LOG.throwing("NameFormSyntax", "valueIsAcceptable",
+              e);
           throw e;
         }
       }
@@ -194,22 +194,21 @@
       // it cannot be valid.
       if (structuralClass == null)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_NAME_FORM_NO_STRUCTURAL_CLASS
-                .get(definition);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_NO_STRUCTURAL_CLASS
+            .get(definition);
         final DecodeException e = DecodeException.error(message);
-        StaticUtils.DEBUG_LOG.throwing("NameFormSyntax",
-            "valueIsAcceptable", e);
+        StaticUtils.DEBUG_LOG
+            .throwing("NameFormSyntax", "valueIsAcceptable", e);
         throw e;
       }
 
       if (requiredAttributes == null || requiredAttributes.size() == 0)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_NAME_FORM_NO_REQUIRED_ATTR.get(definition);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_NAME_FORM_NO_REQUIRED_ATTR
+            .get(definition);
         final DecodeException e = DecodeException.error(message);
-        StaticUtils.DEBUG_LOG.throwing("NameFormSyntax",
-            "valueIsAcceptable", e);
+        StaticUtils.DEBUG_LOG
+            .throwing("NameFormSyntax", "valueIsAcceptable", e);
         throw e;
       }
       return true;
diff --git a/sdk/src/org/opends/sdk/schema/NumericStringEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/NumericStringEqualityMatchingRuleImpl.java
index 6b3d71b9..90cd3d8 100644
--- a/sdk/src/org/opends/sdk/schema/NumericStringEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/NumericStringEqualityMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.NO_CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -36,15 +38,15 @@
 
 
 /**
- * This class implements the numericStringMatch matching rule defined in
- * X.520 and referenced in RFC 2252. It allows for values with numeric
- * digits and spaces, but ignores spaces when performing matching.
+ * This class implements the numericStringMatch matching rule defined in X.520
+ * and referenced in RFC 2252. It allows for values with numeric digits and
+ * spaces, but ignores spaces when performing matching.
  */
 final class NumericStringEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, NO_CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/NumericStringOrderingMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/NumericStringOrderingMatchingRuleImpl.java
index a6aa797..67eea56 100644
--- a/sdk/src/org/opends/sdk/schema/NumericStringOrderingMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/NumericStringOrderingMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.NO_CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -36,14 +38,14 @@
 
 
 /**
- * This implements defines the numericStringOrderingMatch matching rule
- * defined in X.520 and referenced in RFC 2252.
+ * This implements defines the numericStringOrderingMatch matching rule defined
+ * in X.520 and referenced in RFC 2252.
  */
 final class NumericStringOrderingMatchingRuleImpl extends
     AbstractOrderingMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, NO_CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/NumericStringSubstringMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/NumericStringSubstringMatchingRuleImpl.java
index 6637ec0..224c592 100644
--- a/sdk/src/org/opends/sdk/schema/NumericStringSubstringMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/NumericStringSubstringMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.NO_CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -36,14 +38,14 @@
 
 
 /**
- * This class implements the numericStringSubstringsMatch matching rule
- * defined in X.520 and referenced in RFC 2252.
+ * This class implements the numericStringSubstringsMatch matching rule defined
+ * in X.520 and referenced in RFC 2252.
  */
 final class NumericStringSubstringMatchingRuleImpl extends
     AbstractSubstringMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, NO_CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/NumericStringSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/NumericStringSyntaxImpl.java
index b1ace1c..30dcbf0 100644
--- a/sdk/src/org/opends/sdk/schema/NumericStringSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/NumericStringSyntaxImpl.java
@@ -29,20 +29,23 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_NUMERIC_STRING_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_NUMERIC_STRING_ILLEGAL_CHAR;
+import static com.sun.opends.sdk.util.StaticUtils.isDigit;
+import static org.opends.sdk.schema.SchemaConstants.EMR_NUMERIC_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_NUMERIC_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_EXACT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_NUMERIC_STRING_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the numeric string attribute syntax, which may
- * be hold one or more numeric digits and/or spaces. Equality, ordering,
- * and substring matching will be allowed by default.
+ * This class implements the numeric string attribute syntax, which may be hold
+ * one or more numeric digits and/or spaces. Equality, ordering, and substring
+ * matching will be allowed by default.
  */
 final class NumericStringSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -86,21 +89,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     final String valueString = value.toString();
     final int length = valueString.length();
@@ -109,8 +112,7 @@
     if (length == 0)
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_NUMERIC_STRING_EMPTY_VALUE
-          .get());
+      invalidReason.append(ERR_ATTR_SYNTAX_NUMERIC_STRING_EMPTY_VALUE.get());
       return false;
     }
 
@@ -122,9 +124,8 @@
       if (!(isDigit(c) || c == ' '))
       {
 
-        invalidReason
-            .append(WARN_ATTR_SYNTAX_NUMERIC_STRING_ILLEGAL_CHAR.get(
-                valueString, String.valueOf(c), i));
+        invalidReason.append(WARN_ATTR_SYNTAX_NUMERIC_STRING_ILLEGAL_CHAR.get(
+            valueString, String.valueOf(c), i));
         return false;
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/OIDSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/OIDSyntaxImpl.java
index 8a8265b..1699ac7 100644
--- a/sdk/src/org/opends/sdk/schema/OIDSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/OIDSyntaxImpl.java
@@ -29,7 +29,9 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OID_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_OID_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DecodeException;
@@ -40,9 +42,8 @@
 
 
 /**
- * This class defines the OID syntax, which holds either an identifier
- * name or a numeric OID. Equality and substring matching will be
- * allowed by default.
+ * This class defines the OID syntax, which holds either an identifier name or a
+ * numeric OID. Equality and substring matching will be allowed by default.
  */
 final class OIDSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -77,21 +78,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     try
     {
diff --git a/sdk/src/org/opends/sdk/schema/ObjectClass.java b/sdk/src/org/opends/sdk/schema/ObjectClass.java
index 15b3940..a19b6fd 100644
--- a/sdk/src/org/opends/sdk/schema/ObjectClass.java
+++ b/sdk/src/org/opends/sdk/schema/ObjectClass.java
@@ -30,7 +30,9 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EXTENSIBLE_OBJECT_OBJECTCLASS_NAME;
+import static org.opends.sdk.schema.SchemaConstants.EXTENSIBLE_OBJECT_OBJECTCLASS_OID;
+import static org.opends.sdk.schema.SchemaConstants.TOP_OBJECTCLASS_NAME;
 
 import java.util.*;
 
@@ -41,14 +43,13 @@
 
 
 /**
- * This class defines a data structure for storing and interacting with
- * an objectclass, which contains a collection of attributes that must
- * and/or may be present in an entry with that objectclass.
+ * This class defines a data structure for storing and interacting with an
+ * objectclass, which contains a collection of attributes that must and/or may
+ * be present in an entry with that objectclass.
  * <p>
  * Where ordered sets of names, attribute types, or extra properties are
- * provided, the ordering will be preserved when the associated fields
- * are accessed via their getters or via the {@link #toString()}
- * methods.
+ * provided, the ordering will be preserved when the associated fields are
+ * accessed via their getters or via the {@link #toString()} methods.
  */
 public final class ObjectClass extends SchemaElement
 {
@@ -77,24 +78,23 @@
   private final String definition;
 
   private Set<ObjectClass> superiorClasses = Collections.emptySet();
-  private Set<AttributeType> declaredRequiredAttributes =
-      Collections.emptySet();
-  private Set<AttributeType> requiredAttributes =
-      Collections.emptySet();
-  private Set<AttributeType> declaredOptionalAttributes =
-      Collections.emptySet();
-  private Set<AttributeType> optionalAttributes =
-      Collections.emptySet();
+  private Set<AttributeType> declaredRequiredAttributes = Collections
+      .emptySet();
+  private Set<AttributeType> requiredAttributes = Collections.emptySet();
+  private Set<AttributeType> declaredOptionalAttributes = Collections
+      .emptySet();
+  private Set<AttributeType> optionalAttributes = Collections.emptySet();
   private boolean validated = false;
 
 
 
-  ObjectClass(String oid, List<String> names, String description,
-      boolean obsolete, Set<String> superiorClassOIDs,
-      Set<String> requiredAttributeOIDs,
-      Set<String> optionalAttributeOIDs,
-      ObjectClassType objectClassType,
-      Map<String, List<String>> extraProperties, String definition)
+  ObjectClass(final String oid, final List<String> names,
+      final String description, final boolean obsolete,
+      final Set<String> superiorClassOIDs,
+      final Set<String> requiredAttributeOIDs,
+      final Set<String> optionalAttributeOIDs,
+      final ObjectClassType objectClassType,
+      final Map<String, List<String>> extraProperties, final String definition)
   {
     super(description, extraProperties);
 
@@ -123,24 +123,22 @@
 
   /**
    * Construct a extensibleObject object class where the set of allowed
-   * attribute types of this object class is implicitly the set of all
-   * attribute types of userApplications usage.
+   * attribute types of this object class is implicitly the set of all attribute
+   * types of userApplications usage.
    *
    * @param description
    *          The description for this schema definition
    * @param extraProperties
    *          The map of "extra" properties for this schema definition
    */
-  ObjectClass(String description,
-      Map<String, List<String>> extraProperties)
+  ObjectClass(final String description,
+      final Map<String, List<String>> extraProperties)
   {
     super(description, extraProperties);
     this.oid = EXTENSIBLE_OBJECT_OBJECTCLASS_OID;
-    this.names =
-        Collections.singletonList(EXTENSIBLE_OBJECT_OBJECTCLASS_NAME);
+    this.names = Collections.singletonList(EXTENSIBLE_OBJECT_OBJECTCLASS_NAME);
     this.isObsolete = false;
-    this.superiorClassOIDs =
-        Collections.singleton(TOP_OBJECTCLASS_NAME);
+    this.superiorClassOIDs = Collections.singleton(TOP_OBJECTCLASS_NAME);
     this.objectClassType = ObjectClassType.AUXILIARY;
     this.requiredAttributeOIDs = Collections.emptySet();
     this.optionalAttributeOIDs = Collections.emptySet();
@@ -151,7 +149,7 @@
 
 
   @Override
-  public boolean equals(Object o)
+  public boolean equals(final Object o)
   {
     if (this == o)
     {
@@ -170,14 +168,14 @@
 
 
   /**
-   * Retrieves the list of optional attributes for this objectclass.
-   * Note that this set will not automatically include any optional
-   * attributes for superior objectclasses.
+   * Returns an unmodifiable set containing the optional attributes for this
+   * object class. Note that this set will not automatically include any
+   * optional attributes for superior object classes.
    *
-   * @return Returns the list of optional attributes for this
-   *         objectclass.
+   * @return An unmodifiable set containing the optional attributes for this
+   *         object class.
    */
-  public Iterable<AttributeType> getDeclaredOptionalAttributes()
+  public Set<AttributeType> getDeclaredOptionalAttributes()
   {
     return declaredOptionalAttributes;
   }
@@ -185,14 +183,14 @@
 
 
   /**
-   * Retrieves the list of required attributes for this objectclass.
-   * Note that this set will not automatically include any required
-   * attributes for superior objectclasses.
+   * Returns an unmodifiable set containing the required attributes for this
+   * object class. Note that this set will not automatically include any
+   * required attributes for superior object classes.
    *
-   * @return Returns the list of required attributes for this
-   *         objectclass.
+   * @return An unmodifiable set containing the required attributes for this
+   *         object class.
    */
-  public Iterable<AttributeType> getDeclaredRequiredAttributes()
+  public Set<AttributeType> getDeclaredRequiredAttributes()
   {
     return declaredRequiredAttributes;
   }
@@ -200,9 +198,9 @@
 
 
   /**
-   * Retrieves the name or OID for this schema definition. If it has one
-   * or more names, then the primary name will be returned. If it does
-   * not have any names, then the OID will be returned.
+   * Returns the name or OID for this schema definition. If it has one or more
+   * names, then the primary name will be returned. If it does not have any
+   * names, then the OID will be returned.
    *
    * @return The name or OID for this schema definition.
    */
@@ -218,13 +216,13 @@
 
 
   /**
-   * Retrieves an iterable over the set of user-defined names that may
-   * be used to reference this schema definition.
+   * Returns an unmodifiable list containing the user-defined names that may be
+   * used to reference this schema definition.
    *
-   * @return Returns an iterable over the set of user-defined names that
+   * @return Returns an unmodifiable list containing the user-defined names that
    *         may be used to reference this schema definition.
    */
-  public Iterable<String> getNames()
+  public List<String> getNames()
   {
     return names;
   }
@@ -232,7 +230,7 @@
 
 
   /**
-   * Retrieves the objectclass type for this objectclass.
+   * Returns the objectclass type for this objectclass.
    *
    * @return The objectclass type for this objectclass.
    */
@@ -245,7 +243,7 @@
 
 
   /**
-   * Retrieves the OID for this schema definition.
+   * Returns the OID for this schema definition.
    *
    * @return The OID for this schema definition.
    */
@@ -258,14 +256,13 @@
 
 
   /**
-   * Retrieves the list of all optional attributes for this objectclass
-   * and any superior objectclasses that it might have.
+   * Returns an unmodifiable set containing the optional attributes for this
+   * object class and any superior object classes that it might have.
    *
-   * @return Returns the list of all optional attributes for this
-   *         objectclass and any superior objectclasses that it might
-   *         have.
+   * @return An unmodifiable set containing the optional attributes for this
+   *         object class and any superior object classes that it might have.
    */
-  public Iterable<AttributeType> getOptionalAttributes()
+  public Set<AttributeType> getOptionalAttributes()
   {
     return optionalAttributes;
   }
@@ -273,14 +270,13 @@
 
 
   /**
-   * Retrieves the list of all required attributes for this objectclass
-   * and any superior objectclasses that it might have.
+   * Returns an unmodifiable set containing the required attributes for this
+   * object class and any superior object classes that it might have.
    *
-   * @return Returns the list of all required attributes for this
-   *         objectclass and any superior objectclasses that it might
-   *         have.
+   * @return An unmodifiable set containing the required attributes for this
+   *         object class and any superior object classes that it might have.
    */
-  public Iterable<AttributeType> getRequiredAttributes()
+  public Set<AttributeType> getRequiredAttributes()
   {
     return requiredAttributes;
   }
@@ -288,12 +284,13 @@
 
 
   /**
-   * Retrieves the reference to the superior classes for this
-   * objectclass.
+   * Returns an unmodifiable set containing the superior classes for this object
+   * class.
    *
-   * @return The list of superior classes for this objectlass.
+   * @return An unmodifiable set containing the superior classes for this object
+   *         class.
    */
-  public Iterable<ObjectClass> getSuperiorClasses()
+  public Set<ObjectClass> getSuperiorClasses()
   {
     return superiorClasses;
   }
@@ -313,10 +310,10 @@
    *
    * @param name
    *          The name for which to make the determination.
-   * @return <code>true</code> if the specified name is assigned to this
-   *         schema definition, or <code>false</code> if not.
+   * @return <code>true</code> if the specified name is assigned to this schema
+   *         definition, or <code>false</code> if not.
    */
-  public boolean hasName(String name)
+  public boolean hasName(final String name)
   {
     for (final String n : names)
     {
@@ -331,16 +328,15 @@
 
 
   /**
-   * Indicates whether this schema definition has the specified name or
-   * OID.
+   * Indicates whether this schema definition has the specified name or OID.
    *
    * @param value
    *          The value for which to make the determination.
-   * @return <code>true</code> if the provided value matches the OID or
-   *         one of the names assigned to this schema definition, or
-   *         <code>false</code> if not.
+   * @return <code>true</code> if the provided value matches the OID or one of
+   *         the names assigned to this schema definition, or <code>false</code>
+   *         if not.
    */
-  public boolean hasNameOrOID(String value)
+  public boolean hasNameOrOID(final String value)
   {
     return hasName(value) || getOID().equals(value);
   }
@@ -348,15 +344,14 @@
 
 
   /**
-   * Indicates whether this objectclass is a descendant of the provided
-   * class.
+   * Indicates whether this objectclass is a descendant of the provided class.
    *
    * @param objectClass
    *          The objectClass for which to make the determination.
-   * @return <code>true</code> if this objectclass is a descendant of
-   *         the provided class, or <code>false</code> if not.
+   * @return <code>true</code> if this objectclass is a descendant of the
+   *         provided class, or <code>false</code> if not.
    */
-  public boolean isDescendantOf(ObjectClass objectClass)
+  public boolean isDescendantOf(final ObjectClass objectClass)
   {
     for (final ObjectClass sup : superiorClasses)
     {
@@ -373,8 +368,8 @@
   /**
    * Indicates whether this schema definition is declared "obsolete".
    *
-   * @return <code>true</code> if this schema definition is declared
-   *         "obsolete", or <code>false</code> if not.
+   * @return <code>true</code> if this schema definition is declared "obsolete",
+   *         or <code>false</code> if not.
    */
   public boolean isObsolete()
   {
@@ -384,17 +379,16 @@
 
 
   /**
-   * Indicates whether the provided attribute type is included in the
-   * optional attribute list for this or any of its superior
-   * objectclasses.
+   * Indicates whether the provided attribute type is included in the optional
+   * attribute list for this or any of its superior objectclasses.
    *
    * @param attributeType
    *          The attribute type for which to make the determination.
-   * @return <code>true</code> if the provided attribute type is
-   *         optional for this objectclass or any of its superior
-   *         classes, or <code>false</code> if not.
+   * @return <code>true</code> if the provided attribute type is optional for
+   *         this objectclass or any of its superior classes, or
+   *         <code>false</code> if not.
    */
-  public boolean isOptional(AttributeType attributeType)
+  public boolean isOptional(final AttributeType attributeType)
   {
     return optionalAttributes.contains(attributeType);
   }
@@ -402,17 +396,16 @@
 
 
   /**
-   * Indicates whether the provided attribute type is included in the
-   * required attribute list for this or any of its superior
-   * objectclasses.
+   * Indicates whether the provided attribute type is included in the required
+   * attribute list for this or any of its superior objectclasses.
    *
    * @param attributeType
    *          The attribute type for which to make the determination.
-   * @return <code>true</code> if the provided attribute type is
-   *         required by this objectclass or any of its superior
-   *         classes, or <code>false</code> if not.
+   * @return <code>true</code> if the provided attribute type is required by
+   *         this objectclass or any of its superior classes, or
+   *         <code>false</code> if not.
    */
-  public boolean isRequired(AttributeType attributeType)
+  public boolean isRequired(final AttributeType attributeType)
   {
     return requiredAttributes.contains(attributeType);
   }
@@ -420,17 +413,16 @@
 
 
   /**
-   * Indicates whether the provided attribute type is in the list of
-   * required or optional attributes for this objectclass or any of its
-   * superior classes.
+   * Indicates whether the provided attribute type is in the list of required or
+   * optional attributes for this objectclass or any of its superior classes.
    *
    * @param attributeType
    *          The attribute type for which to make the determination.
-   * @return <code>true</code> if the provided attribute type is
-   *         required or allowed for this objectclass or any of its
-   *         superior classes, or <code>false</code> if it is not.
+   * @return <code>true</code> if the provided attribute type is required or
+   *         allowed for this objectclass or any of its superior classes, or
+   *         <code>false</code> if it is not.
    */
-  public boolean isRequiredOrOptional(AttributeType attributeType)
+  public boolean isRequiredOrOptional(final AttributeType attributeType)
   {
     return isRequired(attributeType) || isOptional(attributeType);
   }
@@ -438,11 +430,11 @@
 
 
   /**
-   * Retrieves the string representation of this schema definition in
-   * the form specified in RFC 2252.
+   * Returns the string representation of this schema definition in the form
+   * specified in RFC 2252.
    *
-   * @return The string representation of this schema definition in the
-   *         form specified in RFC 2252.
+   * @return The string representation of this schema definition in the form
+   *         specified in RFC 2252.
    */
   @Override
   public String toString()
@@ -455,15 +447,14 @@
   ObjectClass duplicate()
   {
     return new ObjectClass(oid, names, description, isObsolete,
-        superiorClassOIDs, requiredAttributeOIDs,
-        optionalAttributeOIDs, objectClassType, extraProperties,
-        definition);
+        superiorClassOIDs, requiredAttributeOIDs, optionalAttributeOIDs,
+        objectClassType, extraProperties, definition);
   }
 
 
 
   @Override
-  void toStringContent(StringBuilder buffer)
+  void toStringContent(final StringBuilder buffer)
   {
     buffer.append(oid);
 
@@ -538,8 +529,7 @@
 
     if (!requiredAttributeOIDs.isEmpty())
     {
-      final Iterator<String> iterator =
-          requiredAttributeOIDs.iterator();
+      final Iterator<String> iterator = requiredAttributeOIDs.iterator();
 
       final String firstName = iterator.next();
       if (iterator.hasNext())
@@ -564,8 +554,7 @@
 
     if (!optionalAttributeOIDs.isEmpty())
     {
-      final Iterator<String> iterator =
-          optionalAttributeOIDs.iterator();
+      final Iterator<String> iterator = optionalAttributeOIDs.iterator();
 
       final String firstName = iterator.next();
       if (iterator.hasNext())
@@ -592,7 +581,7 @@
 
 
   @Override
-  void validate(List<LocalizableMessage> warnings, Schema schema)
+  void validate(final List<LocalizableMessage> warnings, final Schema schema)
       throws SchemaException
   {
     if (validated)
@@ -607,8 +596,7 @@
 
     if (!superiorClassOIDs.isEmpty())
     {
-      superiorClasses =
-          new HashSet<ObjectClass>(superiorClassOIDs.size());
+      superiorClasses = new HashSet<ObjectClass>(superiorClassOIDs.size());
       ObjectClass superiorClass;
       for (final String superClassOid : superiorClassOIDs)
       {
@@ -618,15 +606,13 @@
         }
         catch (final UnknownSchemaElementException e)
         {
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_OBJECTCLASS_UNKNOWN_SUPERIOR_CLASS.get(
-                  oid, superClassOid);
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_OBJECTCLASS_UNKNOWN_SUPERIOR_CLASS
+              .get(oid, superClassOid);
           throw new SchemaException(message, e);
         }
 
         // Make sure that the inheritance configuration is acceptable.
-        final ObjectClassType superiorType =
-            superiorClass.getObjectClassType();
+        final ObjectClassType superiorType = superiorClass.getObjectClassType();
         switch (objectClassType)
         {
         case ABSTRACT:
@@ -634,10 +620,9 @@
           // classes.
           if (superiorType != ObjectClassType.ABSTRACT)
           {
-            final LocalizableMessage message =
-                WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE.get(
-                    oid, objectClassType.toString(), superiorType
-                        .toString(), superiorClass.getNameOrOID());
+            final LocalizableMessage message = WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE
+                .get(oid, objectClassType.toString(), superiorType.toString(),
+                    superiorClass.getNameOrOID());
             throw new SchemaException(message);
           }
           break;
@@ -648,10 +633,9 @@
           if (superiorType != ObjectClassType.ABSTRACT
               && superiorType != ObjectClassType.AUXILIARY)
           {
-            final LocalizableMessage message =
-                WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE.get(
-                    oid, objectClassType.toString(), superiorType
-                        .toString(), superiorClass.getNameOrOID());
+            final LocalizableMessage message = WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE
+                .get(oid, objectClassType.toString(), superiorType.toString(),
+                    superiorClass.getNameOrOID());
             throw new SchemaException(message);
           }
           break;
@@ -662,10 +646,9 @@
           if (superiorType != ObjectClassType.ABSTRACT
               && superiorType != ObjectClassType.STRUCTURAL)
           {
-            final LocalizableMessage message =
-                WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE.get(
-                    oid, objectClassType.toString(), superiorType
-                        .toString(), superiorClass.getNameOrOID());
+            final LocalizableMessage message = WARN_ATTR_SYNTAX_OBJECTCLASS_INVALID_SUPERIOR_TYPE
+                .get(oid, objectClassType.toString(), superiorType.toString(),
+                    superiorClass.getNameOrOID());
             throw new SchemaException(message);
           }
           break;
@@ -683,8 +666,8 @@
         superiorClass.validate(warnings, schema);
 
         // Inherit all required attributes from superior class.
-        Iterator<AttributeType> i =
-            superiorClass.getRequiredAttributes().iterator();
+        Iterator<AttributeType> i = superiorClass.getRequiredAttributes()
+            .iterator();
         if (i.hasNext() && requiredAttributes == Collections.EMPTY_SET)
         {
           requiredAttributes = new HashSet<AttributeType>();
@@ -718,18 +701,16 @@
     // in the superior chain.
     if (!derivesTop)
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_OBJECTCLASS_STRUCTURAL_SUPERIOR_NOT_TOP
-              .get(oid);
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_OBJECTCLASS_STRUCTURAL_SUPERIOR_NOT_TOP
+          .get(oid);
       throw new SchemaException(message);
     }
 
     if (oid.equals(EXTENSIBLE_OBJECT_OBJECTCLASS_OID))
     {
-      declaredOptionalAttributes =
-          new HashSet<AttributeType>(requiredAttributeOIDs.size());
-      for (final AttributeType attributeType : schema
-          .getAttributeTypes())
+      declaredOptionalAttributes = new HashSet<AttributeType>(
+          requiredAttributeOIDs.size());
+      for (final AttributeType attributeType : schema.getAttributeTypes())
       {
         if (attributeType.getUsage() == AttributeUsage.USER_APPLICATIONS)
         {
@@ -737,73 +718,80 @@
         }
       }
       optionalAttributes = declaredRequiredAttributes;
-      return;
     }
-
-    if (!requiredAttributeOIDs.isEmpty())
+    else
     {
-      declaredRequiredAttributes =
-          new HashSet<AttributeType>(requiredAttributeOIDs.size());
-      AttributeType attributeType;
-      for (final String requiredAttribute : requiredAttributeOIDs)
+      if (!requiredAttributeOIDs.isEmpty())
       {
-        try
+        declaredRequiredAttributes = new HashSet<AttributeType>(
+            requiredAttributeOIDs.size());
+        AttributeType attributeType;
+        for (final String requiredAttribute : requiredAttributeOIDs)
         {
-          attributeType = schema.getAttributeType(requiredAttribute);
+          try
+          {
+            attributeType = schema.getAttributeType(requiredAttribute);
+          }
+          catch (final UnknownSchemaElementException e)
+          {
+            // This isn't good because it means that the objectclass
+            // requires an attribute type that we don't know anything
+            // about.
+            final LocalizableMessage message = WARN_ATTR_SYNTAX_OBJECTCLASS_UNKNOWN_REQUIRED_ATTR
+                .get(oid, requiredAttribute);
+            throw new SchemaException(message, e);
+          }
+          declaredRequiredAttributes.add(attributeType);
         }
-        catch (final UnknownSchemaElementException e)
+        if (requiredAttributes == Collections.EMPTY_SET)
         {
-          // This isn't good because it means that the objectclass
-          // requires an attribute type that we don't know anything
-          // about.
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_OBJECTCLASS_UNKNOWN_REQUIRED_ATTR.get(
-                  oid, requiredAttribute);
-          throw new SchemaException(message, e);
+          requiredAttributes = declaredRequiredAttributes;
         }
-        declaredRequiredAttributes.add(attributeType);
+        else
+        {
+          requiredAttributes.addAll(declaredRequiredAttributes);
+        }
       }
-      if (requiredAttributes == Collections.EMPTY_SET)
+
+      if (!optionalAttributeOIDs.isEmpty())
       {
-        requiredAttributes = declaredRequiredAttributes;
-      }
-      else
-      {
-        requiredAttributes.addAll(declaredRequiredAttributes);
+        declaredOptionalAttributes = new HashSet<AttributeType>(
+            optionalAttributeOIDs.size());
+        AttributeType attributeType;
+        for (final String optionalAttribute : optionalAttributeOIDs)
+        {
+          try
+          {
+            attributeType = schema.getAttributeType(optionalAttribute);
+          }
+          catch (final UnknownSchemaElementException e)
+          {
+            // This isn't good because it means that the objectclass
+            // requires an attribute type that we don't know anything
+            // about.
+            final LocalizableMessage message = WARN_ATTR_SYNTAX_OBJECTCLASS_UNKNOWN_OPTIONAL_ATTR
+                .get(oid, optionalAttribute);
+            throw new SchemaException(message, e);
+          }
+          declaredOptionalAttributes.add(attributeType);
+        }
+        if (optionalAttributes == Collections.EMPTY_SET)
+        {
+          optionalAttributes = declaredOptionalAttributes;
+        }
+        else
+        {
+          optionalAttributes.addAll(declaredOptionalAttributes);
+        }
       }
     }
 
-    if (!optionalAttributeOIDs.isEmpty())
-    {
-      declaredOptionalAttributes =
-          new HashSet<AttributeType>(optionalAttributeOIDs.size());
-      AttributeType attributeType;
-      for (final String optionalAttribute : optionalAttributeOIDs)
-      {
-        try
-        {
-          attributeType = schema.getAttributeType(optionalAttribute);
-        }
-        catch (final UnknownSchemaElementException e)
-        {
-          // This isn't good because it means that the objectclass
-          // requires an attribute type that we don't know anything
-          // about.
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_OBJECTCLASS_UNKNOWN_OPTIONAL_ATTR.get(
-                  oid, optionalAttribute);
-          throw new SchemaException(message, e);
-        }
-        declaredOptionalAttributes.add(attributeType);
-      }
-      if (optionalAttributes == Collections.EMPTY_SET)
-      {
-        optionalAttributes = declaredOptionalAttributes;
-      }
-      else
-      {
-        optionalAttributes.addAll(declaredOptionalAttributes);
-      }
-    }
+    declaredOptionalAttributes = Collections
+        .unmodifiableSet(declaredOptionalAttributes);
+    declaredRequiredAttributes = Collections
+        .unmodifiableSet(declaredRequiredAttributes);
+    optionalAttributes = Collections.unmodifiableSet(optionalAttributes);
+    requiredAttributes = Collections.unmodifiableSet(requiredAttributes);
+    superiorClasses = Collections.unmodifiableSet(superiorClasses);
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/ObjectClassSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/ObjectClassSyntaxImpl.java
index 6da52d3..167b3ba 100644
--- a/sdk/src/org/opends/sdk/schema/ObjectClassSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/ObjectClassSyntaxImpl.java
@@ -29,8 +29,14 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_ILLEGAL_TOKEN;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_OBJECTCLASS_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.
+  ERR_ATTR_SYNTAX_OBJECTCLASS_EXPECTED_OPEN_PARENTHESIS;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OID_FIRST_COMPONENT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_OBJECTCLASS_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DecodeException;
@@ -43,9 +49,9 @@
 
 
 /**
- * This class implements the object class description syntax, which is
- * used to hold objectclass definitions in the server schema. The format
- * of this syntax is defined in RFC 2252.
+ * This class implements the object class description syntax, which is used to
+ * hold objectclass definitions in the server schema. The format of this syntax
+ * is defined in RFC 2252.
  */
 final class ObjectClassSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -72,8 +78,8 @@
 
 
 
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We'll use the decodeObjectClass method to determine if the value
     // is acceptable.
@@ -90,8 +96,8 @@
       {
         // This means that the value was empty or contained only
         // whitespace. That is illegal.
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_OBJECTCLASS_EMPTY_VALUE.get();
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_OBJECTCLASS_EMPTY_VALUE
+            .get();
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("ObjectClassSyntax",
             "valueIsAcceptable", e);
@@ -103,9 +109,8 @@
       final char c = reader.read();
       if (c != '(')
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_OBJECTCLASS_EXPECTED_OPEN_PARENTHESIS.get(
-                definition, (reader.pos() - 1), String.valueOf(c));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_OBJECTCLASS_EXPECTED_OPEN_PARENTHESIS
+            .get(definition, (reader.pos() - 1), String.valueOf(c));
         final DecodeException e = DecodeException.error(message);
         StaticUtils.DEBUG_LOG.throwing("ObjectClassSyntax",
             "valueIsAcceptable", e);
@@ -193,8 +198,8 @@
         }
         else
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_ILLEGAL_TOKEN.get(tokenName);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_TOKEN
+              .get(tokenName);
           final DecodeException e = DecodeException.error(message);
           StaticUtils.DEBUG_LOG.throwing("ObjectClassSyntax",
               "valueIsAcceptable", e);
diff --git a/sdk/src/org/opends/sdk/schema/ObjectClassType.java b/sdk/src/org/opends/sdk/schema/ObjectClassType.java
index 4affff3..4157ab7 100644
--- a/sdk/src/org/opends/sdk/schema/ObjectClassType.java
+++ b/sdk/src/org/opends/sdk/schema/ObjectClassType.java
@@ -30,8 +30,8 @@
 
 
 /**
- * This enumeration defines the set of possible objectclass types that
- * may be used, as defined in RFC 2252.
+ * This enumeration defines the set of possible objectclass types that may be
+ * used, as defined in RFC 2252.
  */
 public enum ObjectClassType
 {
@@ -56,13 +56,12 @@
 
 
   /**
-   * Creates a new objectclass type with the provided string
-   * representation.
-   * 
+   * Creates a new objectclass type with the provided string representation.
+   *
    * @param typeString
    *          The string representation for this objectclass type.
    */
-  private ObjectClassType(String typeString)
+  private ObjectClassType(final String typeString)
   {
     this.typeString = typeString;
   }
@@ -71,7 +70,7 @@
 
   /**
    * Retrieves a string representation of this objectclass type.
-   * 
+   *
    * @return A string representation of this objectclass type.
    */
   @Override
diff --git a/sdk/src/org/opends/sdk/schema/ObjectIdentifierEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/ObjectIdentifierEqualityMatchingRuleImpl.java
index a18c600..c3bb105 100644
--- a/sdk/src/org/opends/sdk/schema/ObjectIdentifierEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/ObjectIdentifierEqualityMatchingRuleImpl.java
@@ -36,11 +36,10 @@
 
 
 /**
- * This class defines the objectIdentifierMatch matching rule defined in
- * X.520 and referenced in RFC 2252. This expects to work on OIDs and
- * will match either an attribute/objectclass name or a numeric OID.
- * NOTE: This matching rule requires a schema to lookup object
- * identifiers in the descriptor form.
+ * This class defines the objectIdentifierMatch matching rule defined in X.520
+ * and referenced in RFC 2252. This expects to work on OIDs and will match
+ * either an attribute/objectclass name or a numeric OID. NOTE: This matching
+ * rule requires a schema to lookup object identifiers in the descriptor form.
  */
 final class ObjectIdentifierEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
@@ -51,21 +50,20 @@
 
 
 
-    OIDAssertion(String oid)
+    OIDAssertion(final String oid)
     {
       this.oid = oid;
     }
 
 
 
-    public ConditionResult matches(ByteSequence attributeValue)
+    public ConditionResult matches(final ByteSequence attributeValue)
     {
       final String attrStr = attributeValue.toString();
 
       // We should have normalized all values to OIDs. If not, we know
       // the descriptor form is not valid in the schema.
-      if (attrStr.length() == 0
-          || !StaticUtils.isDigit(attrStr.charAt(0)))
+      if (attrStr.length() == 0 || !StaticUtils.isDigit(attrStr.charAt(0)))
       {
         return ConditionResult.UNDEFINED;
       }
@@ -74,14 +72,13 @@
         return ConditionResult.UNDEFINED;
       }
 
-      return attrStr.equals(oid) ? ConditionResult.TRUE
-          : ConditionResult.FALSE;
+      return attrStr.equals(oid) ? ConditionResult.TRUE : ConditionResult.FALSE;
     }
   }
 
 
 
-  static String resolveNames(Schema schema, String oid)
+  static String resolveNames(final Schema schema, final String oid)
   {
     if (!StaticUtils.isDigit(oid.charAt(0)))
     {
@@ -98,9 +95,8 @@
       {
         if (schema.hasDITContentRule(oid))
         {
-          schemaName =
-              schema.getDITContentRule(oid).getStructuralClass()
-                  .getOID();
+          schemaName = schema.getDITContentRule(oid).getStructuralClass()
+              .getOID();
         }
       }
 
@@ -132,8 +128,8 @@
       {
         if (schema.hasMatchingRuleUse(oid))
         {
-          schemaName =
-              schema.getMatchingRuleUse(oid).getMatchingRule().getOID();
+          schemaName = schema.getMatchingRuleUse(oid).getMatchingRule()
+              .getOID();
         }
       }
 
@@ -160,26 +156,24 @@
 
 
   @Override
-  public Assertion getAssertion(Schema schema, ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     final String definition = value.toString();
     final SubstringReader reader = new SubstringReader(definition);
-    final String normalized =
-        resolveNames(schema, SchemaUtils.readOID(reader));
+    final String normalized = resolveNames(schema, SchemaUtils.readOID(reader));
 
     return new OIDAssertion(normalized);
   }
 
 
 
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     final String definition = value.toString();
     final SubstringReader reader = new SubstringReader(definition);
-    final String normalized =
-        resolveNames(schema, SchemaUtils.readOID(reader));
+    final String normalized = resolveNames(schema, SchemaUtils.readOID(reader));
     return ByteString.valueOf(normalized);
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java
index 1e25da2..17bdad5 100644
--- a/sdk/src/org/opends/sdk/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java
@@ -28,7 +28,8 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_EXPECTED_OPEN_PARENTHESIS;
 
 import org.opends.sdk.*;
 
@@ -37,35 +38,32 @@
 
 
 /**
- * This class implements the objectIdentifierFirstComponentMatch
- * matching rule defined in X.520 and referenced in RFC 2252. This rule
- * is intended for use with attributes whose values contain a set of
- * parentheses enclosing a space-delimited set of names and/or
- * name-value pairs (like attribute type or objectclass descriptions) in
- * which the "first component" is the first item after the opening
- * parenthesis.
+ * This class implements the objectIdentifierFirstComponentMatch matching rule
+ * defined in X.520 and referenced in RFC 2252. This rule is intended for use
+ * with attributes whose values contain a set of parentheses enclosing a
+ * space-delimited set of names and/or name-value pairs (like attribute type or
+ * objectclass descriptions) in which the "first component" is the first item
+ * after the opening parenthesis.
  */
-final class ObjectIdentifierFirstComponentEqualityMatchingRuleImpl
-    extends AbstractMatchingRuleImpl
+final class ObjectIdentifierFirstComponentEqualityMatchingRuleImpl extends
+    AbstractMatchingRuleImpl
 {
   @Override
-  public Assertion getAssertion(Schema schema, ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     final String definition = value.toString();
     final SubstringReader reader = new SubstringReader(definition);
-    final String normalized =
-        ObjectIdentifierEqualityMatchingRuleImpl.resolveNames(schema,
-            SchemaUtils.readOID(reader));
+    final String normalized = ObjectIdentifierEqualityMatchingRuleImpl
+        .resolveNames(schema, SchemaUtils.readOID(reader));
 
-    return new ObjectIdentifierEqualityMatchingRuleImpl.OIDAssertion(
-        normalized);
+    return new ObjectIdentifierEqualityMatchingRuleImpl.OIDAssertion(normalized);
   }
 
 
 
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     final String definition = value.toString();
     final SubstringReader reader = new SubstringReader(definition);
@@ -87,9 +85,8 @@
     final char c = reader.read();
     if (c != '(')
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_EXPECTED_OPEN_PARENTHESIS.get(definition,
-              (reader.pos() - 1), String.valueOf(c));
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_EXPECTED_OPEN_PARENTHESIS
+          .get(definition, (reader.pos() - 1), String.valueOf(c));
       throw DecodeException.error(message);
     }
 
@@ -98,9 +95,8 @@
     reader.skipWhitespaces();
 
     // The next set of characters must be the OID.
-    final String normalized =
-        ObjectIdentifierEqualityMatchingRuleImpl.resolveNames(schema,
-            SchemaUtils.readOID(reader));
+    final String normalized = ObjectIdentifierEqualityMatchingRuleImpl
+        .resolveNames(schema, SchemaUtils.readOID(reader));
     return ByteString.valueOf(normalized);
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/OctetStringEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/OctetStringEqualityMatchingRuleImpl.java
index 69e38b9..bd30880 100644
--- a/sdk/src/org/opends/sdk/schema/OctetStringEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/OctetStringEqualityMatchingRuleImpl.java
@@ -34,15 +34,15 @@
 
 
 /**
- * This class defines the octetStringMatch matching rule defined in
- * X.520. It will be used as the default equality matching rule for the
- * binary and octet string syntaxes.
+ * This class defines the octetStringMatch matching rule defined in X.520. It
+ * will be used as the default equality matching rule for the binary and octet
+ * string syntaxes.
  */
 final class OctetStringEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     return value.toByteString();
   }
diff --git a/sdk/src/org/opends/sdk/schema/OctetStringOrderingMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/OctetStringOrderingMatchingRuleImpl.java
index f2d2de0..0777d61 100644
--- a/sdk/src/org/opends/sdk/schema/OctetStringOrderingMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/OctetStringOrderingMatchingRuleImpl.java
@@ -34,15 +34,15 @@
 
 
 /**
- * This class defines the octetStringOrderingMatch matching rule defined
- * in X.520. This will be the default ordering matching rule for the
- * binary and octet string syntaxes.
+ * This class defines the octetStringOrderingMatch matching rule defined in
+ * X.520. This will be the default ordering matching rule for the binary and
+ * octet string syntaxes.
  */
 final class OctetStringOrderingMatchingRuleImpl extends
     AbstractOrderingMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     return value.toByteString();
   }
diff --git a/sdk/src/org/opends/sdk/schema/OctetStringSubstringMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/OctetStringSubstringMatchingRuleImpl.java
index 11bef77..ecee397 100644
--- a/sdk/src/org/opends/sdk/schema/OctetStringSubstringMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/OctetStringSubstringMatchingRuleImpl.java
@@ -34,15 +34,15 @@
 
 
 /**
- * This class defines the octetStringSubstringsMatch matching rule
- * defined in X.520. It will be used as the default substring matching
- * rule for the binary and octet string syntaxes.
+ * This class defines the octetStringSubstringsMatch matching rule defined in
+ * X.520. It will be used as the default substring matching rule for the binary
+ * and octet string syntaxes.
  */
 final class OctetStringSubstringMatchingRuleImpl extends
     AbstractSubstringMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     return value.toByteString();
   }
diff --git a/sdk/src/org/opends/sdk/schema/OctetStringSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/OctetStringSyntaxImpl.java
index 7f22abf..10fc033 100644
--- a/sdk/src/org/opends/sdk/schema/OctetStringSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/OctetStringSyntaxImpl.java
@@ -29,19 +29,19 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_OCTET_STRING_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the octet string attribute syntax, which is
- * equivalent to the binary syntax and should be considered a
- * replacement for it. Equality, ordering, and substring matching will
- * be allowed by default.
+ * This class implements the octet string attribute syntax, which is equivalent
+ * to the binary syntax and should be considered a replacement for it. Equality,
+ * ordering, and substring matching will be allowed by default.
  */
 final class OctetStringSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -76,21 +76,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // All values will be acceptable for the octet string syntax.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/OtherMailboxSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/OtherMailboxSyntaxImpl.java
index d20f867..610733b 100644
--- a/sdk/src/org/opends/sdk/schema/OtherMailboxSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/OtherMailboxSyntaxImpl.java
@@ -30,19 +30,20 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_CASE_IGNORE_LIST_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_LIST_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_OTHER_MAILBOX_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the other mailbox attribute syntax, which
- * consists of a printable string component (the mailbox type) followed
- * by a dollar sign and an IA5 string component (the mailbox). Equality
- * and substring matching will be allowed by default.
+ * This class implements the other mailbox attribute syntax, which consists of a
+ * printable string component (the mailbox type) followed by a dollar sign and
+ * an IA5 string component (the mailbox). Equality and substring matching will
+ * be allowed by default.
  */
 final class OtherMailboxSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -78,29 +79,28 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // Check to see if the provided value was null. If so, then that's
     // not acceptable.
     if (value == null)
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_OTHER_MAILBOX_EMPTY_VALUE
-          .get());
+      invalidReason.append(ERR_ATTR_SYNTAX_OTHER_MAILBOX_EMPTY_VALUE.get());
       return false;
     }
 
@@ -111,8 +111,7 @@
     if (valueLength == 0)
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_OTHER_MAILBOX_EMPTY_VALUE
-          .get());
+      invalidReason.append(ERR_ATTR_SYNTAX_OTHER_MAILBOX_EMPTY_VALUE.get());
       return false;
     }
 
@@ -139,9 +138,8 @@
       else if (!PrintableStringSyntaxImpl.isPrintableCharacter(c))
       {
 
-        invalidReason
-            .append(ERR_ATTR_SYNTAX_OTHER_MAILBOX_ILLEGAL_MBTYPE_CHAR
-                .get(valueString, String.valueOf(c), pos));
+        invalidReason.append(ERR_ATTR_SYNTAX_OTHER_MAILBOX_ILLEGAL_MBTYPE_CHAR
+            .get(valueString, String.valueOf(c), pos));
         return false;
       }
     }
@@ -163,9 +161,8 @@
       if (c != (c & 0x7F))
       {
 
-        invalidReason
-            .append(ERR_ATTR_SYNTAX_OTHER_MAILBOX_ILLEGAL_MB_CHAR.get(
-                valueString, String.valueOf(c), pos));
+        invalidReason.append(ERR_ATTR_SYNTAX_OTHER_MAILBOX_ILLEGAL_MB_CHAR.get(
+            valueString, String.valueOf(c), pos));
         return false;
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/PostalAddressSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/PostalAddressSyntaxImpl.java
index 6f215ad..b1d0102 100644
--- a/sdk/src/org/opends/sdk/schema/PostalAddressSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/PostalAddressSyntaxImpl.java
@@ -29,20 +29,21 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_POSTAL_ADDRESS_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the postal address attribute syntax, which is a
- * list of UCS (Universal Character Set, as defined in the ISO 10646
- * specification and includes UTF-8 and UTF-16) strings separated by
- * dollar signs. By default, they will be treated in a case-insensitive
- * manner, and equality and substring matching will be allowed.
+ * This class implements the postal address attribute syntax, which is a list of
+ * UCS (Universal Character Set, as defined in the ISO 10646 specification and
+ * includes UTF-8 and UTF-16) strings separated by dollar signs. By default,
+ * they will be treated in a case-insensitive manner, and equality and substring
+ * matching will be allowed.
  */
 final class PostalAddressSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -78,21 +79,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We'll allow any value.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/PresentationAddressEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/PresentationAddressEqualityMatchingRuleImpl.java
index c109036..0d6f9a9 100644
--- a/sdk/src/org/opends/sdk/schema/PresentationAddressEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/PresentationAddressEqualityMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -36,16 +38,16 @@
 
 
 /**
- * This class implements the presentationAddressMatch matching rule
- * defined in X.520 and referenced in RFC 2252. However, since this
- * matching rule and the associated syntax have been deprecated, this
- * matching rule behaves exactly like the caseIgnoreMatch rule.
+ * This class implements the presentationAddressMatch matching rule defined in
+ * X.520 and referenced in RFC 2252. However, since this matching rule and the
+ * associated syntax have been deprecated, this matching rule behaves exactly
+ * like the caseIgnoreMatch rule.
  */
 final class PresentationAddressEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/PresentationAddressSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/PresentationAddressSyntaxImpl.java
index 20831ed..c3d2e62 100644
--- a/sdk/src/org/opends/sdk/schema/PresentationAddressSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/PresentationAddressSyntaxImpl.java
@@ -36,12 +36,10 @@
 
 
 
-
 /**
- * This class implements the presentation address attribute syntax,
- * which is defined in RFC 1278. However, because this LDAP syntax is
- * being deprecated, this implementation behaves exactly like the
- * directory string syntax.
+ * This class implements the presentation address attribute syntax, which is
+ * defined in RFC 1278. However, because this LDAP syntax is being deprecated,
+ * this implementation behaves exactly like the directory string syntax.
  */
 final class PresentationAddressSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -92,21 +90,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We will accept any value for this syntax.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/PrintableStringSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/PrintableStringSyntaxImpl.java
index 307e7fc..eb4cba3 100644
--- a/sdk/src/org/opends/sdk/schema/PrintableStringSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/PrintableStringSyntaxImpl.java
@@ -29,7 +29,10 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.
+  WARN_ATTR_SYNTAX_PRINTABLE_STRING_EMPTY_VALUE;
+import static com.sun.opends.sdk.messages.Messages.
+  WARN_ATTR_SYNTAX_PRINTABLE_STRING_ILLEGAL_CHARACTER;
 import static org.opends.sdk.schema.SchemaConstants.*;
 
 import org.opends.sdk.ByteSequence;
@@ -37,28 +40,25 @@
 
 
 
-
 /**
- * This class implements the printable string attribute syntax, which is
- * simply a string of characters from a limited ASCII character set
- * (uppercase and lowercase letters, numeric digits, the space, and a
- * set of various symbols). By default, they will be treated in a
- * case-insensitive manner, and equality, ordering, substring, and
- * approximate matching will be allowed.
+ * This class implements the printable string attribute syntax, which is simply
+ * a string of characters from a limited ASCII character set (uppercase and
+ * lowercase letters, numeric digits, the space, and a set of various symbols).
+ * By default, they will be treated in a case-insensitive manner, and equality,
+ * ordering, substring, and approximate matching will be allowed.
  */
 final class PrintableStringSyntaxImpl extends AbstractSyntaxImpl
 {
 
   /**
-   * Indicates whether the provided character is a valid printable
-   * character.
-   * 
+   * Indicates whether the provided character is a valid printable character.
+   *
    * @param c
    *          The character for which to make the determination.
    * @return <CODE>true</CODE> if the provided character is a printable
    *         character, or <CODE>false</CODE> if not.
    */
-  static boolean isPrintableCharacter(char c)
+  static boolean isPrintableCharacter(final char c)
   {
     switch (c)
     {
@@ -191,29 +191,28 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // Check to see if the provided value was null. If so, then that's
     // not acceptable.
     if (value == null)
     {
 
-      invalidReason
-          .append(WARN_ATTR_SYNTAX_PRINTABLE_STRING_EMPTY_VALUE.get());
+      invalidReason.append(WARN_ATTR_SYNTAX_PRINTABLE_STRING_EMPTY_VALUE.get());
       return false;
     }
 
@@ -224,8 +223,7 @@
     if (valueLength == 0)
     {
 
-      invalidReason
-          .append(WARN_ATTR_SYNTAX_PRINTABLE_STRING_EMPTY_VALUE.get());
+      invalidReason.append(WARN_ATTR_SYNTAX_PRINTABLE_STRING_EMPTY_VALUE.get());
       return false;
     }
 
@@ -238,8 +236,8 @@
       {
 
         invalidReason
-            .append(WARN_ATTR_SYNTAX_PRINTABLE_STRING_ILLEGAL_CHARACTER
-                .get(valueString, String.valueOf(c), i));
+            .append(WARN_ATTR_SYNTAX_PRINTABLE_STRING_ILLEGAL_CHARACTER.get(
+                valueString, String.valueOf(c), i));
         return false;
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/ProtocolInformationEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/ProtocolInformationEqualityMatchingRuleImpl.java
index e7a02d0..7d988fa 100644
--- a/sdk/src/org/opends/sdk/schema/ProtocolInformationEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/ProtocolInformationEqualityMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -36,16 +38,16 @@
 
 
 /**
- * This class implements the protocolInformationMatch matching rule
- * defined in X.520 and referenced in RFC 2252. However, since this
- * matching rule and the associated syntax have been deprecated, this
- * matching rule behaves exactly like the caseIgnoreMatch rule.
+ * This class implements the protocolInformationMatch matching rule defined in
+ * X.520 and referenced in RFC 2252. However, since this matching rule and the
+ * associated syntax have been deprecated, this matching rule behaves exactly
+ * like the caseIgnoreMatch rule.
  */
 final class ProtocolInformationEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/ProtocolInformationSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/ProtocolInformationSyntaxImpl.java
index 46a2722..de40958 100644
--- a/sdk/src/org/opends/sdk/schema/ProtocolInformationSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/ProtocolInformationSyntaxImpl.java
@@ -36,11 +36,10 @@
 
 
 
-
 /**
- * This class implements the protocol information attribute syntax,
- * which is being deprecated. As such, this implementation behaves
- * exactly like the directory string syntax.
+ * This class implements the protocol information attribute syntax, which is
+ * being deprecated. As such, this implementation behaves exactly like the
+ * directory string syntax.
  */
 final class ProtocolInformationSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -92,21 +91,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We will accept any value for this syntax.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/RegexSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/RegexSyntaxImpl.java
index 2a5007b..5481937 100644
--- a/sdk/src/org/opends/sdk/schema/RegexSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/RegexSyntaxImpl.java
@@ -29,8 +29,11 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_LDAPSYNTAX_REGEX_INVALID_VALUE;
+import static org.opends.sdk.schema.SchemaConstants.AMR_DOUBLE_METAPHONE_OID;
+import static org.opends.sdk.schema.SchemaConstants.EMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_OID;
 
 import java.util.regex.Pattern;
 
@@ -44,8 +47,8 @@
 
 /**
  * This class provides a regex mechanism where a new syntax and its
- * corresponding matching rules can be created on-the-fly. A regex
- * syntax is an LDAPSyntaxDescriptionSyntax with X-PATTERN extension.
+ * corresponding matching rules can be created on-the-fly. A regex syntax is an
+ * LDAPSyntaxDescriptionSyntax with X-PATTERN extension.
  */
 final class RegexSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -54,7 +57,7 @@
 
 
 
-  RegexSyntaxImpl(Pattern pattern)
+  RegexSyntaxImpl(final Pattern pattern)
   {
     Validator.ensureNotNull(pattern);
     this.pattern = pattern;
@@ -108,16 +111,15 @@
 
 
 
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     final String strValue = value.toString();
     final boolean matches = pattern.matcher(strValue).matches();
     if (!matches)
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_LDAPSYNTAX_REGEX_INVALID_VALUE.get(strValue,
-              pattern.pattern());
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_LDAPSYNTAX_REGEX_INVALID_VALUE
+          .get(strValue, pattern.pattern());
       invalidReason.append(message);
     }
     return matches;
diff --git a/sdk/src/org/opends/sdk/schema/Schema.java b/sdk/src/org/opends/sdk/schema/Schema.java
index fd6722e..bcd2ea6 100644
--- a/sdk/src/org/opends/sdk/schema/Schema.java
+++ b/sdk/src/org/opends/sdk/schema/Schema.java
@@ -50,8 +50,7 @@
 
 /**
  * This class defines a data structure that holds information about the
- * components of the LDAP schema. It includes the following kinds of
- * elements:
+ * components of the LDAP schema. It includes the following kinds of elements:
  * <UL>
  * <LI>Attribute type definitions</LI>
  * <LI>Object class definitions</LI>
@@ -65,7 +64,7 @@
  */
 public final class Schema
 {
-  private static class EmptyImpl implements Impl
+  private static final class EmptyImpl implements Impl
   {
     private final SchemaCompatOptions options;
 
@@ -78,7 +77,7 @@
 
 
 
-    public AttributeType getAttributeType(String name)
+    public AttributeType getAttributeType(final String name)
     {
       // Construct an placeholder attribute type with the given name,
       // the default matching rule, and the default syntax. The OID of
@@ -89,9 +88,8 @@
       builder.append("-oid");
       final String noid = builder.toString();
 
-      return new AttributeType(noid, Collections.singletonList(name),
-          "", Schema.getDefaultMatchingRule(), Schema
-              .getDefaultSyntax());
+      return new AttributeType(noid, Collections.singletonList(name), "",
+          Schema.getDefaultMatchingRule(), Schema.getDefaultSyntax());
     }
 
 
@@ -103,18 +101,17 @@
 
 
 
-    public List<AttributeType> getAttributeTypesByName(String name)
+    public List<AttributeType> getAttributeTypesByName(final String name)
     {
       return Collections.emptyList();
     }
 
 
 
-    public DITContentRule getDITContentRule(String name)
+    public DITContentRule getDITContentRule(final String name)
         throws UnknownSchemaElementException
     {
-      throw new UnknownSchemaElementException(WARN_DCR_UNKNOWN
-          .get(name));
+      throw new UnknownSchemaElementException(WARN_DCR_UNKNOWN.get(name));
     }
 
 
@@ -126,25 +123,24 @@
 
 
 
-    public Collection<DITContentRule> getDITContentRulesByName(
-        String name)
+    public Collection<DITContentRule> getDITContentRulesByName(final String name)
     {
       return Collections.emptyList();
     }
 
 
 
-    public DITStructureRule getDITStructureRule(int ruleID)
+    public DITStructureRule getDITStructureRule(final int ruleID)
         throws UnknownSchemaElementException
     {
-      throw new UnknownSchemaElementException(WARN_DSR_UNKNOWN
-          .get(String.valueOf(ruleID)));
+      throw new UnknownSchemaElementException(WARN_DSR_UNKNOWN.get(String
+          .valueOf(ruleID)));
     }
 
 
 
     public Collection<DITStructureRule> getDITStructureRulesByName(
-        String name)
+        final String name)
     {
       return Collections.emptyList();
     }
@@ -152,7 +148,7 @@
 
 
     public Collection<DITStructureRule> getDITStructureRulesByNameForm(
-        NameForm nameForm)
+        final NameForm nameForm)
     {
       return Collections.emptyList();
     }
@@ -166,7 +162,7 @@
 
 
 
-    public MatchingRule getMatchingRule(String name)
+    public MatchingRule getMatchingRule(final String name)
         throws UnknownSchemaElementException
     {
       throw new UnknownSchemaElementException(WARN_MR_UNKNOWN.get(name));
@@ -181,14 +177,14 @@
 
 
 
-    public Collection<MatchingRule> getMatchingRulesByName(String name)
+    public Collection<MatchingRule> getMatchingRulesByName(final String name)
     {
       return Collections.emptyList();
     }
 
 
 
-    public MatchingRuleUse getMatchingRuleUse(MatchingRule matchingRule)
+    public MatchingRuleUse getMatchingRuleUse(final MatchingRule matchingRule)
         throws UnknownSchemaElementException
     {
       return getMatchingRuleUse(matchingRule.getOID());
@@ -196,11 +192,10 @@
 
 
 
-    public MatchingRuleUse getMatchingRuleUse(String name)
+    public MatchingRuleUse getMatchingRuleUse(final String name)
         throws UnknownSchemaElementException
     {
-      throw new UnknownSchemaElementException(WARN_MRU_UNKNOWN
-          .get(name));
+      throw new UnknownSchemaElementException(WARN_MRU_UNKNOWN.get(name));
     }
 
 
@@ -213,24 +208,23 @@
 
 
     public Collection<MatchingRuleUse> getMatchingRuleUsesByName(
-        String name)
+        final String name)
     {
       return Collections.emptyList();
     }
 
 
 
-    public NameForm getNameForm(String name)
+    public NameForm getNameForm(final String name)
         throws UnknownSchemaElementException
     {
-      throw new UnknownSchemaElementException(WARN_NAMEFORM_UNKNOWN
-          .get(name));
+      throw new UnknownSchemaElementException(WARN_NAMEFORM_UNKNOWN.get(name));
     }
 
 
 
     public Collection<NameForm> getNameFormByObjectClass(
-        ObjectClass structuralClass)
+        final ObjectClass structuralClass)
     {
       return Collections.emptyList();
     }
@@ -244,14 +238,14 @@
 
 
 
-    public Collection<NameForm> getNameFormsByName(String name)
+    public Collection<NameForm> getNameFormsByName(final String name)
     {
       return Collections.emptyList();
     }
 
 
 
-    public ObjectClass getObjectClass(String name)
+    public ObjectClass getObjectClass(final String name)
         throws UnknownSchemaElementException
     {
       throw new UnknownSchemaElementException(WARN_OBJECTCLASS_UNKNOWN
@@ -267,7 +261,7 @@
 
 
 
-    public Collection<ObjectClass> getObjectClassesByName(String name)
+    public Collection<ObjectClass> getObjectClassesByName(final String name)
     {
       return Collections.emptyList();
     }
@@ -291,7 +285,7 @@
 
 
 
-    public Syntax getSyntax(String numericOID)
+    public Syntax getSyntax(final String numericOID)
     {
       // Fake up a syntax substituted by the default syntax.
       return new Syntax(numericOID);
@@ -313,7 +307,7 @@
 
 
 
-    public boolean hasAttributeType(String name)
+    public boolean hasAttributeType(final String name)
     {
       // In theory a non-strict schema always contains the requested
       // attribute type, so we could always return true. However, we
@@ -324,49 +318,49 @@
 
 
 
-    public boolean hasDITContentRule(String name)
+    public boolean hasDITContentRule(final String name)
     {
       return false;
     }
 
 
 
-    public boolean hasDITStructureRule(int ruleID)
+    public boolean hasDITStructureRule(final int ruleID)
     {
       return false;
     }
 
 
 
-    public boolean hasMatchingRule(String name)
+    public boolean hasMatchingRule(final String name)
     {
       return false;
     }
 
 
 
-    public boolean hasMatchingRuleUse(String name)
+    public boolean hasMatchingRuleUse(final String name)
     {
       return false;
     }
 
 
 
-    public boolean hasNameForm(String name)
+    public boolean hasNameForm(final String name)
     {
       return false;
     }
 
 
 
-    public boolean hasObjectClass(String name)
+    public boolean hasObjectClass(final String name)
     {
       return false;
     }
 
 
 
-    public boolean hasSyntax(String numericOID)
+    public boolean hasSyntax(final String numericOID)
     {
       return false;
     }
@@ -458,13 +452,11 @@
 
 
 
-    NameForm getNameForm(String name)
-        throws UnknownSchemaElementException;
+    NameForm getNameForm(String name) throws UnknownSchemaElementException;
 
 
 
-    Collection<NameForm> getNameFormByObjectClass(
-        ObjectClass structuralClass);
+    Collection<NameForm> getNameFormByObjectClass(ObjectClass structuralClass);
 
 
 
@@ -497,8 +489,7 @@
 
 
 
-    Syntax getSyntax(String numericOID)
-        throws UnknownSchemaElementException;
+    Syntax getSyntax(String numericOID) throws UnknownSchemaElementException;
 
 
 
@@ -547,20 +538,20 @@
 
 
 
-  private static class NonStrictImpl implements Impl
+  private static final class NonStrictImpl implements Impl
   {
     private final Impl strictImpl;
 
 
 
-    private NonStrictImpl(Impl strictImpl)
+    private NonStrictImpl(final Impl strictImpl)
     {
       this.strictImpl = strictImpl;
     }
 
 
 
-    public AttributeType getAttributeType(String name)
+    public AttributeType getAttributeType(final String name)
         throws UnknownSchemaElementException
     {
       if (!strictImpl.hasAttributeType(name))
@@ -569,15 +560,13 @@
         // the default matching rule, and the default syntax. The OID of
         // the attribute will be the normalized OID alias with "-oid"
         // appended to the given name.
-        final StringBuilder builder = new StringBuilder(
-            name.length() + 4);
+        final StringBuilder builder = new StringBuilder(name.length() + 4);
         StaticUtils.toLowerCase(name, builder);
         builder.append("-oid");
         final String noid = builder.toString();
 
-        return new AttributeType(noid, Collections.singletonList(name),
-            "", Schema.getDefaultMatchingRule(), Schema
-                .getDefaultSyntax());
+        return new AttributeType(noid, Collections.singletonList(name), "",
+            Schema.getDefaultMatchingRule(), Schema.getDefaultSyntax());
       }
       return strictImpl.getAttributeType(name);
     }
@@ -591,14 +580,14 @@
 
 
 
-    public List<AttributeType> getAttributeTypesByName(String name)
+    public List<AttributeType> getAttributeTypesByName(final String name)
     {
       return strictImpl.getAttributeTypesByName(name);
     }
 
 
 
-    public DITContentRule getDITContentRule(String name)
+    public DITContentRule getDITContentRule(final String name)
         throws UnknownSchemaElementException
     {
       return strictImpl.getDITContentRule(name);
@@ -613,15 +602,14 @@
 
 
 
-    public Collection<DITContentRule> getDITContentRulesByName(
-        String name)
+    public Collection<DITContentRule> getDITContentRulesByName(final String name)
     {
       return strictImpl.getDITContentRulesByName(name);
     }
 
 
 
-    public DITStructureRule getDITStructureRule(int ruleID)
+    public DITStructureRule getDITStructureRule(final int ruleID)
         throws UnknownSchemaElementException
     {
       return strictImpl.getDITStructureRule(ruleID);
@@ -630,7 +618,7 @@
 
 
     public Collection<DITStructureRule> getDITStructureRulesByName(
-        String name)
+        final String name)
     {
       return strictImpl.getDITStructureRulesByName(name);
     }
@@ -638,7 +626,7 @@
 
 
     public Collection<DITStructureRule> getDITStructureRulesByNameForm(
-        NameForm nameForm)
+        final NameForm nameForm)
     {
       return strictImpl.getDITStructureRulesByNameForm(nameForm);
     }
@@ -652,7 +640,7 @@
 
 
 
-    public MatchingRule getMatchingRule(String name)
+    public MatchingRule getMatchingRule(final String name)
         throws UnknownSchemaElementException
     {
       return strictImpl.getMatchingRule(name);
@@ -667,14 +655,14 @@
 
 
 
-    public Collection<MatchingRule> getMatchingRulesByName(String name)
+    public Collection<MatchingRule> getMatchingRulesByName(final String name)
     {
       return strictImpl.getMatchingRulesByName(name);
     }
 
 
 
-    public MatchingRuleUse getMatchingRuleUse(MatchingRule matchingRule)
+    public MatchingRuleUse getMatchingRuleUse(final MatchingRule matchingRule)
         throws UnknownSchemaElementException
     {
       return strictImpl.getMatchingRuleUse(matchingRule);
@@ -682,7 +670,7 @@
 
 
 
-    public MatchingRuleUse getMatchingRuleUse(String name)
+    public MatchingRuleUse getMatchingRuleUse(final String name)
         throws UnknownSchemaElementException
     {
       return strictImpl.getMatchingRuleUse(name);
@@ -698,14 +686,14 @@
 
 
     public Collection<MatchingRuleUse> getMatchingRuleUsesByName(
-        String name)
+        final String name)
     {
       return strictImpl.getMatchingRuleUsesByName(name);
     }
 
 
 
-    public NameForm getNameForm(String name)
+    public NameForm getNameForm(final String name)
         throws UnknownSchemaElementException
     {
       return strictImpl.getNameForm(name);
@@ -714,7 +702,7 @@
 
 
     public Collection<NameForm> getNameFormByObjectClass(
-        ObjectClass structuralClass)
+        final ObjectClass structuralClass)
     {
       return strictImpl.getNameFormByObjectClass(structuralClass);
     }
@@ -728,14 +716,14 @@
 
 
 
-    public Collection<NameForm> getNameFormsByName(String name)
+    public Collection<NameForm> getNameFormsByName(final String name)
     {
       return strictImpl.getNameFormsByName(name);
     }
 
 
 
-    public ObjectClass getObjectClass(String name)
+    public ObjectClass getObjectClass(final String name)
         throws UnknownSchemaElementException
     {
       return strictImpl.getObjectClass(name);
@@ -750,7 +738,7 @@
 
 
 
-    public Collection<ObjectClass> getObjectClassesByName(String name)
+    public Collection<ObjectClass> getObjectClassesByName(final String name)
     {
       return strictImpl.getObjectClassesByName(name);
     }
@@ -771,7 +759,7 @@
 
 
 
-    public Syntax getSyntax(String numericOID)
+    public Syntax getSyntax(final String numericOID)
     {
       if (!strictImpl.hasSyntax(numericOID))
       {
@@ -796,7 +784,7 @@
 
 
 
-    public boolean hasAttributeType(String name)
+    public boolean hasAttributeType(final String name)
     {
       // In theory a non-strict schema always contains the requested
       // attribute type, so we could always return true. However, we
@@ -807,49 +795,49 @@
 
 
 
-    public boolean hasDITContentRule(String name)
+    public boolean hasDITContentRule(final String name)
     {
       return strictImpl.hasDITContentRule(name);
     }
 
 
 
-    public boolean hasDITStructureRule(int ruleID)
+    public boolean hasDITStructureRule(final int ruleID)
     {
       return strictImpl.hasDITStructureRule(ruleID);
     }
 
 
 
-    public boolean hasMatchingRule(String name)
+    public boolean hasMatchingRule(final String name)
     {
       return strictImpl.hasMatchingRule(name);
     }
 
 
 
-    public boolean hasMatchingRuleUse(String name)
+    public boolean hasMatchingRuleUse(final String name)
     {
       return strictImpl.hasMatchingRuleUse(name);
     }
 
 
 
-    public boolean hasNameForm(String name)
+    public boolean hasNameForm(final String name)
     {
       return strictImpl.hasNameForm(name);
     }
 
 
 
-    public boolean hasObjectClass(String name)
+    public boolean hasObjectClass(final String name)
     {
       return strictImpl.hasObjectClass(name);
     }
 
 
 
-    public boolean hasSyntax(String numericOID)
+    public boolean hasSyntax(final String numericOID)
     {
       return strictImpl.hasSyntax(numericOID);
     }
@@ -864,7 +852,7 @@
 
 
 
-  private static class StrictImpl implements Impl
+  private static final class StrictImpl implements Impl
   {
     private final Map<Integer, DITStructureRule> id2StructureRules;
 
@@ -908,25 +896,26 @@
 
 
 
-    private StrictImpl(String schemaName,
-        Map<String, Syntax> numericOID2Syntaxes,
-        Map<String, MatchingRule> numericOID2MatchingRules,
-        Map<String, MatchingRuleUse> numericOID2MatchingRuleUses,
-        Map<String, AttributeType> numericOID2AttributeTypes,
-        Map<String, ObjectClass> numericOID2ObjectClasses,
-        Map<String, NameForm> numericOID2NameForms,
-        Map<String, DITContentRule> numericOID2ContentRules,
-        Map<Integer, DITStructureRule> id2StructureRules,
-        Map<String, List<MatchingRule>> name2MatchingRules,
-        Map<String, List<MatchingRuleUse>> name2MatchingRuleUses,
-        Map<String, List<AttributeType>> name2AttributeTypes,
-        Map<String, List<ObjectClass>> name2ObjectClasses,
-        Map<String, List<NameForm>> name2NameForms,
-        Map<String, List<DITContentRule>> name2ContentRules,
-        Map<String, List<DITStructureRule>> name2StructureRules,
-        Map<String, List<NameForm>> objectClass2NameForms,
-        Map<String, List<DITStructureRule>> nameForm2StructureRules,
-        SchemaCompatOptions options, List<LocalizableMessage> warnings)
+    private StrictImpl(final String schemaName,
+        final Map<String, Syntax> numericOID2Syntaxes,
+        final Map<String, MatchingRule> numericOID2MatchingRules,
+        final Map<String, MatchingRuleUse> numericOID2MatchingRuleUses,
+        final Map<String, AttributeType> numericOID2AttributeTypes,
+        final Map<String, ObjectClass> numericOID2ObjectClasses,
+        final Map<String, NameForm> numericOID2NameForms,
+        final Map<String, DITContentRule> numericOID2ContentRules,
+        final Map<Integer, DITStructureRule> id2StructureRules,
+        final Map<String, List<MatchingRule>> name2MatchingRules,
+        final Map<String, List<MatchingRuleUse>> name2MatchingRuleUses,
+        final Map<String, List<AttributeType>> name2AttributeTypes,
+        final Map<String, List<ObjectClass>> name2ObjectClasses,
+        final Map<String, List<NameForm>> name2NameForms,
+        final Map<String, List<DITContentRule>> name2ContentRules,
+        final Map<String, List<DITStructureRule>> name2StructureRules,
+        final Map<String, List<NameForm>> objectClass2NameForms,
+        final Map<String, List<DITStructureRule>> nameForm2StructureRules,
+        final SchemaCompatOptions options,
+        final List<LocalizableMessage> warnings)
     {
       this.schemaName = schemaName;
       this.numericOID2Syntaxes = Collections
@@ -943,19 +932,15 @@
           .unmodifiableMap(numericOID2NameForms);
       this.numericOID2ContentRules = Collections
           .unmodifiableMap(numericOID2ContentRules);
-      this.id2StructureRules = Collections
-          .unmodifiableMap(id2StructureRules);
-      this.name2MatchingRules = Collections
-          .unmodifiableMap(name2MatchingRules);
+      this.id2StructureRules = Collections.unmodifiableMap(id2StructureRules);
+      this.name2MatchingRules = Collections.unmodifiableMap(name2MatchingRules);
       this.name2MatchingRuleUses = Collections
           .unmodifiableMap(name2MatchingRuleUses);
       this.name2AttributeTypes = Collections
           .unmodifiableMap(name2AttributeTypes);
-      this.name2ObjectClasses = Collections
-          .unmodifiableMap(name2ObjectClasses);
+      this.name2ObjectClasses = Collections.unmodifiableMap(name2ObjectClasses);
       this.name2NameForms = Collections.unmodifiableMap(name2NameForms);
-      this.name2ContentRules = Collections
-          .unmodifiableMap(name2ContentRules);
+      this.name2ContentRules = Collections.unmodifiableMap(name2ContentRules);
       this.name2StructureRules = Collections
           .unmodifiableMap(name2StructureRules);
       this.objectClass2NameForms = Collections
@@ -968,7 +953,7 @@
 
 
 
-    public AttributeType getAttributeType(String name)
+    public AttributeType getAttributeType(final String name)
         throws UnknownSchemaElementException
     {
       final AttributeType type = numericOID2AttributeTypes.get(name);
@@ -984,11 +969,10 @@
         {
           return attributes.get(0);
         }
-        throw new UnknownSchemaElementException(
-            WARN_ATTR_TYPE_AMBIGIOUS.get(name));
+        throw new UnknownSchemaElementException(WARN_ATTR_TYPE_AMBIGIOUS
+            .get(name));
       }
-      throw new UnknownSchemaElementException(WARN_ATTR_TYPE_UNKNOWN
-          .get(name));
+      throw new UnknownSchemaElementException(WARN_ATTR_TYPE_UNKNOWN.get(name));
     }
 
 
@@ -1000,7 +984,7 @@
 
 
 
-    public List<AttributeType> getAttributeTypesByName(String name)
+    public List<AttributeType> getAttributeTypesByName(final String name)
     {
       final List<AttributeType> attributes = name2AttributeTypes
           .get(StaticUtils.toLowerCase(name));
@@ -1016,7 +1000,7 @@
 
 
 
-    public DITContentRule getDITContentRule(String name)
+    public DITContentRule getDITContentRule(final String name)
         throws UnknownSchemaElementException
     {
       final DITContentRule rule = numericOID2ContentRules.get(name);
@@ -1024,19 +1008,17 @@
       {
         return rule;
       }
-      final List<DITContentRule> rules = name2ContentRules
-          .get(StaticUtils.toLowerCase(name));
+      final List<DITContentRule> rules = name2ContentRules.get(StaticUtils
+          .toLowerCase(name));
       if (rules != null)
       {
         if (rules.size() == 1)
         {
           return rules.get(0);
         }
-        throw new UnknownSchemaElementException(WARN_DCR_AMBIGIOUS
-            .get(name));
+        throw new UnknownSchemaElementException(WARN_DCR_AMBIGIOUS.get(name));
       }
-      throw new UnknownSchemaElementException(WARN_DCR_UNKNOWN
-          .get(name));
+      throw new UnknownSchemaElementException(WARN_DCR_UNKNOWN.get(name));
     }
 
 
@@ -1048,11 +1030,10 @@
 
 
 
-    public Collection<DITContentRule> getDITContentRulesByName(
-        String name)
+    public Collection<DITContentRule> getDITContentRulesByName(final String name)
     {
-      final List<DITContentRule> rules = name2ContentRules
-          .get(StaticUtils.toLowerCase(name));
+      final List<DITContentRule> rules = name2ContentRules.get(StaticUtils
+          .toLowerCase(name));
       if (rules == null)
       {
         return Collections.emptyList();
@@ -1065,14 +1046,14 @@
 
 
 
-    public DITStructureRule getDITStructureRule(int ruleID)
+    public DITStructureRule getDITStructureRule(final int ruleID)
         throws UnknownSchemaElementException
     {
       final DITStructureRule rule = id2StructureRules.get(ruleID);
       if (rule == null)
       {
-        throw new UnknownSchemaElementException(WARN_DSR_UNKNOWN
-            .get(String.valueOf(ruleID)));
+        throw new UnknownSchemaElementException(WARN_DSR_UNKNOWN.get(String
+            .valueOf(ruleID)));
       }
       return rule;
     }
@@ -1080,10 +1061,10 @@
 
 
     public Collection<DITStructureRule> getDITStructureRulesByName(
-        String name)
+        final String name)
     {
-      final List<DITStructureRule> rules = name2StructureRules
-          .get(StaticUtils.toLowerCase(name));
+      final List<DITStructureRule> rules = name2StructureRules.get(StaticUtils
+          .toLowerCase(name));
       if (rules == null)
       {
         return Collections.emptyList();
@@ -1097,10 +1078,10 @@
 
 
     public Collection<DITStructureRule> getDITStructureRulesByNameForm(
-        NameForm nameForm)
+        final NameForm nameForm)
     {
-      final List<DITStructureRule> rules = nameForm2StructureRules
-          .get(nameForm.getOID());
+      final List<DITStructureRule> rules = nameForm2StructureRules.get(nameForm
+          .getOID());
       if (rules == null)
       {
         return Collections.emptyList();
@@ -1120,7 +1101,7 @@
 
 
 
-    public MatchingRule getMatchingRule(String name)
+    public MatchingRule getMatchingRule(final String name)
         throws UnknownSchemaElementException
     {
       final MatchingRule rule = numericOID2MatchingRules.get(name);
@@ -1128,16 +1109,15 @@
       {
         return rule;
       }
-      final List<MatchingRule> rules = name2MatchingRules
-          .get(StaticUtils.toLowerCase(name));
+      final List<MatchingRule> rules = name2MatchingRules.get(StaticUtils
+          .toLowerCase(name));
       if (rules != null)
       {
         if (rules.size() == 1)
         {
           return rules.get(0);
         }
-        throw new UnknownSchemaElementException(WARN_MR_AMBIGIOUS
-            .get(name));
+        throw new UnknownSchemaElementException(WARN_MR_AMBIGIOUS.get(name));
       }
       throw new UnknownSchemaElementException(WARN_MR_UNKNOWN.get(name));
     }
@@ -1151,10 +1131,10 @@
 
 
 
-    public Collection<MatchingRule> getMatchingRulesByName(String name)
+    public Collection<MatchingRule> getMatchingRulesByName(final String name)
     {
-      final List<MatchingRule> rules = name2MatchingRules
-          .get(StaticUtils.toLowerCase(name));
+      final List<MatchingRule> rules = name2MatchingRules.get(StaticUtils
+          .toLowerCase(name));
       if (rules == null)
       {
         return Collections.emptyList();
@@ -1167,7 +1147,7 @@
 
 
 
-    public MatchingRuleUse getMatchingRuleUse(MatchingRule matchingRule)
+    public MatchingRuleUse getMatchingRuleUse(final MatchingRule matchingRule)
         throws UnknownSchemaElementException
     {
       return getMatchingRuleUse(matchingRule.getOID());
@@ -1175,28 +1155,25 @@
 
 
 
-    public MatchingRuleUse getMatchingRuleUse(String name)
+    public MatchingRuleUse getMatchingRuleUse(final String name)
         throws UnknownSchemaElementException
     {
-      final MatchingRuleUse rule = numericOID2MatchingRuleUses
-          .get(name);
+      final MatchingRuleUse rule = numericOID2MatchingRuleUses.get(name);
       if (rule != null)
       {
         return rule;
       }
-      final List<MatchingRuleUse> uses = name2MatchingRuleUses
-          .get(StaticUtils.toLowerCase(name));
+      final List<MatchingRuleUse> uses = name2MatchingRuleUses.get(StaticUtils
+          .toLowerCase(name));
       if (uses != null)
       {
         if (uses.size() == 1)
         {
           return uses.get(0);
         }
-        throw new UnknownSchemaElementException(WARN_MRU_AMBIGIOUS
-            .get(name));
+        throw new UnknownSchemaElementException(WARN_MRU_AMBIGIOUS.get(name));
       }
-      throw new UnknownSchemaElementException(WARN_MRU_UNKNOWN
-          .get(name));
+      throw new UnknownSchemaElementException(WARN_MRU_UNKNOWN.get(name));
     }
 
 
@@ -1209,10 +1186,10 @@
 
 
     public Collection<MatchingRuleUse> getMatchingRuleUsesByName(
-        String name)
+        final String name)
     {
-      final List<MatchingRuleUse> rules = name2MatchingRuleUses
-          .get(StaticUtils.toLowerCase(name));
+      final List<MatchingRuleUse> rules = name2MatchingRuleUses.get(StaticUtils
+          .toLowerCase(name));
       if (rules == null)
       {
         return Collections.emptyList();
@@ -1225,7 +1202,7 @@
 
 
 
-    public NameForm getNameForm(String name)
+    public NameForm getNameForm(final String name)
         throws UnknownSchemaElementException
     {
       final NameForm form = numericOID2NameForms.get(name);
@@ -1244,17 +1221,16 @@
         throw new UnknownSchemaElementException(WARN_NAMEFORM_AMBIGIOUS
             .get(name));
       }
-      throw new UnknownSchemaElementException(WARN_NAMEFORM_UNKNOWN
-          .get(name));
+      throw new UnknownSchemaElementException(WARN_NAMEFORM_UNKNOWN.get(name));
     }
 
 
 
     public Collection<NameForm> getNameFormByObjectClass(
-        ObjectClass structuralClass)
+        final ObjectClass structuralClass)
     {
-      final List<NameForm> forms = objectClass2NameForms
-          .get(structuralClass.getOID());
+      final List<NameForm> forms = objectClass2NameForms.get(structuralClass
+          .getOID());
       if (forms == null)
       {
         return Collections.emptyList();
@@ -1274,7 +1250,7 @@
 
 
 
-    public Collection<NameForm> getNameFormsByName(String name)
+    public Collection<NameForm> getNameFormsByName(final String name)
     {
       final List<NameForm> forms = name2NameForms.get(StaticUtils
           .toLowerCase(name));
@@ -1290,7 +1266,7 @@
 
 
 
-    public ObjectClass getObjectClass(String name)
+    public ObjectClass getObjectClass(final String name)
         throws UnknownSchemaElementException
     {
       final ObjectClass oc = numericOID2ObjectClasses.get(name);
@@ -1298,16 +1274,16 @@
       {
         return oc;
       }
-      final List<ObjectClass> classes = name2ObjectClasses
-          .get(StaticUtils.toLowerCase(name));
+      final List<ObjectClass> classes = name2ObjectClasses.get(StaticUtils
+          .toLowerCase(name));
       if (classes != null)
       {
         if (classes.size() == 1)
         {
           return classes.get(0);
         }
-        throw new UnknownSchemaElementException(
-            WARN_OBJECTCLASS_AMBIGIOUS.get(name));
+        throw new UnknownSchemaElementException(WARN_OBJECTCLASS_AMBIGIOUS
+            .get(name));
       }
       throw new UnknownSchemaElementException(WARN_OBJECTCLASS_UNKNOWN
           .get(name));
@@ -1322,10 +1298,10 @@
 
 
 
-    public Collection<ObjectClass> getObjectClassesByName(String name)
+    public Collection<ObjectClass> getObjectClassesByName(final String name)
     {
-      final List<ObjectClass> classes = name2ObjectClasses
-          .get(StaticUtils.toLowerCase(name));
+      final List<ObjectClass> classes = name2ObjectClasses.get(StaticUtils
+          .toLowerCase(name));
       if (classes == null)
       {
         return Collections.emptyList();
@@ -1352,7 +1328,7 @@
 
 
 
-    public Syntax getSyntax(String numericOID)
+    public Syntax getSyntax(final String numericOID)
         throws UnknownSchemaElementException
     {
       final Syntax syntax = numericOID2Syntaxes.get(numericOID);
@@ -1380,7 +1356,7 @@
 
 
 
-    public boolean hasAttributeType(String name)
+    public boolean hasAttributeType(final String name)
     {
       if (numericOID2AttributeTypes.containsKey(name))
       {
@@ -1393,53 +1369,53 @@
 
 
 
-    public boolean hasDITContentRule(String name)
+    public boolean hasDITContentRule(final String name)
     {
       if (numericOID2ContentRules.containsKey(name))
       {
         return true;
       }
-      final List<DITContentRule> rules = name2ContentRules
-          .get(StaticUtils.toLowerCase(name));
+      final List<DITContentRule> rules = name2ContentRules.get(StaticUtils
+          .toLowerCase(name));
       return rules != null && rules.size() == 1;
     }
 
 
 
-    public boolean hasDITStructureRule(int ruleID)
+    public boolean hasDITStructureRule(final int ruleID)
     {
       return id2StructureRules.containsKey(ruleID);
     }
 
 
 
-    public boolean hasMatchingRule(String name)
+    public boolean hasMatchingRule(final String name)
     {
       if (numericOID2MatchingRules.containsKey(name))
       {
         return true;
       }
-      final List<MatchingRule> rules = name2MatchingRules
-          .get(StaticUtils.toLowerCase(name));
+      final List<MatchingRule> rules = name2MatchingRules.get(StaticUtils
+          .toLowerCase(name));
       return rules != null && rules.size() == 1;
     }
 
 
 
-    public boolean hasMatchingRuleUse(String name)
+    public boolean hasMatchingRuleUse(final String name)
     {
       if (numericOID2MatchingRuleUses.containsKey(name))
       {
         return true;
       }
-      final List<MatchingRuleUse> uses = name2MatchingRuleUses
-          .get(StaticUtils.toLowerCase(name));
+      final List<MatchingRuleUse> uses = name2MatchingRuleUses.get(StaticUtils
+          .toLowerCase(name));
       return uses != null && uses.size() == 1;
     }
 
 
 
-    public boolean hasNameForm(String name)
+    public boolean hasNameForm(final String name)
     {
       if (numericOID2NameForms.containsKey(name))
       {
@@ -1452,20 +1428,20 @@
 
 
 
-    public boolean hasObjectClass(String name)
+    public boolean hasObjectClass(final String name)
     {
       if (numericOID2ObjectClasses.containsKey(name))
       {
         return true;
       }
-      final List<ObjectClass> classes = name2ObjectClasses
-          .get(StaticUtils.toLowerCase(name));
+      final List<ObjectClass> classes = name2ObjectClasses.get(StaticUtils
+          .toLowerCase(name));
       return classes != null && classes.size() == 1;
     }
 
 
 
-    public boolean hasSyntax(String numericOID)
+    public boolean hasSyntax(final String numericOID)
     {
       return numericOID2Syntaxes.containsKey(numericOID);
     }
@@ -1480,53 +1456,39 @@
 
 
 
-  private static final Schema CORE_SCHEMA = CoreSchemaImpl
-      .getInstance();
+  private static final Schema CORE_SCHEMA = CoreSchemaImpl.getInstance();
 
   private static final Schema EMPTY_SCHEMA = new Schema(new EmptyImpl());
 
-  private static volatile Schema DEFAULT_SCHEMA = CoreSchemaImpl
-      .getInstance();
+  private static volatile Schema defaultSchema = CoreSchemaImpl.getInstance();
 
-  private static final AttributeDescription ATTR_ATTRIBUTE_TYPES = AttributeDescription
-      .valueOf("attributeTypes");
+  private static final String ATTR_ATTRIBUTE_TYPES = "attributeTypes";
 
-  private static final AttributeDescription ATTR_DIT_CONTENT_RULES = AttributeDescription
-      .valueOf("dITContentRules");
+  private static final String ATTR_DIT_CONTENT_RULES = "dITContentRules";
 
-  private static final AttributeDescription ATTR_DIT_STRUCTURE_RULES = AttributeDescription
-      .valueOf("dITStructureRules");
+  private static final String ATTR_DIT_STRUCTURE_RULES = "dITStructureRules";
 
-  private static final AttributeDescription ATTR_LDAP_SYNTAXES = AttributeDescription
-      .valueOf("ldapSyntaxes");
+  private static final String ATTR_LDAP_SYNTAXES = "ldapSyntaxes";
 
-  private static final AttributeDescription ATTR_MATCHING_RULE_USE = AttributeDescription
-      .valueOf("matchingRuleUse");
+  private static final String ATTR_MATCHING_RULE_USE = "matchingRuleUse";
 
-  private static final AttributeDescription ATTR_MATCHING_RULES = AttributeDescription
-      .valueOf("matchingRules");
+  private static final String ATTR_MATCHING_RULES = "matchingRules";
 
-  private static final AttributeDescription ATTR_NAME_FORMS = AttributeDescription
-      .valueOf("nameForms");
+  private static final String ATTR_NAME_FORMS = "nameForms";
 
-  private static final AttributeDescription ATTR_OBJECT_CLASSES = AttributeDescription
-      .valueOf("objectClasses");
+  private static final String ATTR_OBJECT_CLASSES = "objectClasses";
 
-  private static final AttributeDescription ATTR_SUBSCHEMA_SUBENTRY = AttributeDescription
-      .valueOf("subschemaSubentry");
+  private static final String ATTR_SUBSCHEMA_SUBENTRY = "subschemaSubentry";
 
   private static final String[] SUBSCHEMA_ATTRS = new String[] {
       ATTR_LDAP_SYNTAXES.toString(), ATTR_ATTRIBUTE_TYPES.toString(),
-      ATTR_DIT_CONTENT_RULES.toString(),
-      ATTR_DIT_STRUCTURE_RULES.toString(),
-      ATTR_MATCHING_RULE_USE.toString(),
-      ATTR_MATCHING_RULES.toString(), ATTR_NAME_FORMS.toString(),
-      ATTR_OBJECT_CLASSES.toString() };
+      ATTR_DIT_CONTENT_RULES.toString(), ATTR_DIT_STRUCTURE_RULES.toString(),
+      ATTR_MATCHING_RULE_USE.toString(), ATTR_MATCHING_RULES.toString(),
+      ATTR_NAME_FORMS.toString(), ATTR_OBJECT_CLASSES.toString() };
 
-  private static final Filter SUBSCHEMA_FILTER = Filter
-      .newEqualityMatchFilter(CoreSchema.getObjectClassAttributeType()
-          .getNameOrOID(), CoreSchema.getSubschemaObjectClass()
-          .getNameOrOID());
+  private static final Filter SUBSCHEMA_FILTER = Filter.newEqualityMatchFilter(
+      CoreSchema.getObjectClassAttributeType().getNameOrOID(), CoreSchema
+          .getSubschemaObjectClass().getNameOrOID());
 
   private static final String[] SUBSCHEMA_SUBENTRY_ATTRS = new String[] { ATTR_SUBSCHEMA_SUBENTRY
       .toString() };
@@ -1534,23 +1496,19 @@
 
 
   /**
-   * Returns the core schema. The core schema is non-strict and contains
-   * the following standard LDAP schema elements:
+   * Returns the core schema. The core schema is non-strict and contains the
+   * following standard LDAP schema elements:
    * <ul>
-   * <li><a href="http://tools.ietf.org/html/rfc4512">RFC 4512 -
-   * Lightweight Directory Access Protocol (LDAP): Directory Information
-   * Models </a>
-   * <li><a href="http://tools.ietf.org/html/rfc4517">RFC 4517 -
-   * Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching
-   * Rules </a>
-   * <li><a href="http://tools.ietf.org/html/rfc4519">RFC 4519 -
-   * Lightweight Directory Access Protocol (LDAP): Schema for User
-   * Applications </a>
-   * <li><a href="http://tools.ietf.org/html/rfc4530">RFC 4530 -
-   * Lightweight Directory Access Protocol (LDAP): entryUUID Operational
-   * Attribute </a>
-   * <li><a href="http://tools.ietf.org/html/rfc3045">RFC 3045 - Storing
-   * Vendor Information in the LDAP root DSE </a>
+   * <li><a href="http://tools.ietf.org/html/rfc4512">RFC 4512 - Lightweight
+   * Directory Access Protocol (LDAP): Directory Information Models </a>
+   * <li><a href="http://tools.ietf.org/html/rfc4517">RFC 4517 - Lightweight
+   * Directory Access Protocol (LDAP): Syntaxes and Matching Rules </a>
+   * <li><a href="http://tools.ietf.org/html/rfc4519">RFC 4519 - Lightweight
+   * Directory Access Protocol (LDAP): Schema for User Applications </a>
+   * <li><a href="http://tools.ietf.org/html/rfc4530">RFC 4530 - Lightweight
+   * Directory Access Protocol (LDAP): entryUUID Operational Attribute </a>
+   * <li><a href="http://tools.ietf.org/html/rfc3045">RFC 3045 - Storing Vendor
+   * Information in the LDAP root DSE </a>
    * <li><a href="http://tools.ietf.org/html/rfc3112">RFC 3112 - LDAP
    * Authentication Password Schema </a>
    * </ul>
@@ -1565,23 +1523,21 @@
 
 
   /**
-   * Returns the default schema which should be used by this
-   * application. The default schema is initially set to the core
-   * schema.
+   * Returns the default schema which should be used by this application. The
+   * default schema is initially set to the core schema.
    *
-   * @return The default schema which should be used by this
-   *         application.
+   * @return The default schema which should be used by this application.
    */
   public static Schema getDefaultSchema()
   {
-    return DEFAULT_SCHEMA;
+    return defaultSchema;
   }
 
 
 
   /**
-   * Returns the empty schema. The empty schema is non-strict and does
-   * not contain any schema elements.
+   * Returns the empty schema. The empty schema is non-strict and does not
+   * contain any schema elements.
    *
    * @return The empty schema.
    */
@@ -1593,49 +1549,47 @@
 
 
   /**
-   * Reads the schema from the Directory Server contained in the named
-   * subschema sub-entry.
+   * Reads the schema from the Directory Server contained in the named subschema
+   * sub-entry.
    * <p>
-   * If the requested schema is not returned by the Directory Server
-   * then the request will fail with an {@link EntryNotFoundException}.
-   * More specifically, the returned future will never return {@code
-   * null}.
+   * If the requested schema is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
+   * specifically, the returned future will never return {@code null}.
    * <p>
-   * Implementations may choose to perform optimizations such as
-   * caching.
+   * This method uses a Search operation to read the schema and does not perform
+   * caching. More specifically, it does not use the
+   * {@link AsynchronousConnection#readSchema} method.
    *
    * @param connection
-   *          A connection to the Directory Server whose schema is to be
-   *          read.
+   *          A connection to the Directory Server whose schema is to be read.
    * @param name
    *          The distinguished name of the subschema sub-entry.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
-   *           If the {@code connection} or {@code name} was {@code
-   *           null}.
+   *           If the {@code connection} or {@code name} was {@code null}.
    */
   public static FutureResult<Schema> readSchema(
-      AsynchronousConnection connection, DN name,
-      ResultHandler<? super Schema> handler)
+      final AsynchronousConnection connection, final DN name,
+      final ResultHandler<? super Schema> handler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException
   {
     final SearchRequest request = getReadSchemaSearchRequest(name);
 
-    final FutureResultTransformer<SearchResultEntry, Schema> future = new FutureResultTransformer<SearchResultEntry, Schema>(
-        handler)
+    final FutureResultTransformer<SearchResultEntry, Schema> future =
+      new FutureResultTransformer<SearchResultEntry, Schema>(handler)
     {
 
-      protected Schema transformResult(SearchResultEntry result)
+      @Override
+      protected Schema transformResult(final SearchResultEntry result)
           throws ErrorResultException
       {
         return valueOf(result);
@@ -1652,34 +1606,36 @@
 
 
   /**
-   * Reads the schema from the Directory Server contained in the named
-   * subschema sub-entry using the provided connection.
+   * Reads the schema from the Directory Server contained in the named subschema
+   * sub-entry using the provided connection.
    * <p>
-   * If the requested schema is not returned by the Directory Server
-   * then the request will fail with an {@link EntryNotFoundException}.
-   * More specifically, this method will never return {@code null}.
+   * If the requested schema is not returned by the Directory Server then the
+   * request will fail with an {@link EntryNotFoundException}. More
+   * specifically, this method will never return {@code null}.
+   * <p>
+   * This method uses a Search operation to read the schema and does not perform
+   * caching. More specifically, it does not use the
+   * {@link Connection#readSchema} method.
    *
    * @param connection
-   *          A connection to the Directory Server whose schema is to be
-   *          read.
+   *          A connection to the Directory Server whose schema is to be read.
    * @param name
    *          The distinguished name of the subschema sub-entry.
    * @return The schema from the Directory Server.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If the connection does not support search operations.
    * @throws IllegalStateException
-   *           If the connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If the connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
-   *           If the {@code connection} or {@code name} was {@code
-   *           null}.
+   *           If the {@code connection} or {@code name} was {@code null}.
    */
-  public static Schema readSchema(Connection connection, DN name)
+  public static Schema readSchema(final Connection connection, final DN name)
       throws ErrorResultException, InterruptedException,
       UnsupportedOperationException, IllegalStateException,
       NullPointerException
@@ -1692,52 +1648,49 @@
 
 
   /**
-   * Reads the schema from the Directory Server which applies to the
-   * named entry.
+   * Reads the schema from the Directory Server which applies to the named
+   * entry.
    * <p>
-   * If the requested entry or its associated schema are not returned by
-   * the Directory Server then the request will fail with an
-   * {@link EntryNotFoundException}. More specifically, the returned
-   * future will never return {@code null}.
+   * If the requested entry or its associated schema are not returned by the
+   * Directory Server then the request will fail with an
+   * {@link EntryNotFoundException}. More specifically, the returned future will
+   * never return {@code null}.
    * <p>
-   * A typical implementation will first read the {@code
-   * subschemaSubentry} attribute of the entry in order to locate the
-   * schema. However, implementations may choose to perform other
-   * optimizations, such as caching.
+   * This implementation first reads the {@code subschemaSubentry} attribute of
+   * the entry in order to identify the schema and then invokes
+   * {@link #readSchema} to read the schema. More specifically, it does not use
+   * the {@link AsynchronousConnection#readSchemaForEntry} method.
    *
    * @param connection
-   *          A connection to the Directory Server whose schema is to be
-   *          read.
+   *          A connection to the Directory Server whose schema is to be read.
    * @param name
-   *          The distinguished name of the entry whose schema is to be
-   *          located.
+   *          The distinguished name of the entry whose schema is to be located.
    * @param handler
-   *          A result handler which can be used to asynchronously
-   *          process the operation result when it is received, may be
-   *          {@code null}.
+   *          A result handler which can be used to asynchronously process the
+   *          operation result when it is received, may be {@code null}.
    * @return A future representing the result of the operation.
    * @throws UnsupportedOperationException
    *           If this connection does not support search operations.
    * @throws IllegalStateException
-   *           If this connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If this connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
-   *           If the {@code connection} or {@code name} was {@code
-   *           null}.
+   *           If the {@code connection} or {@code name} was {@code null}.
    */
   public static FutureResult<Schema> readSchemaForEntry(
       final AsynchronousConnection connection, final DN name,
-      ResultHandler<Schema> handler)
+      final ResultHandler<Schema> handler)
       throws UnsupportedOperationException, IllegalStateException,
       NullPointerException
   {
-    final RecursiveFutureResult<SearchResultEntry, Schema> future = new RecursiveFutureResult<SearchResultEntry, Schema>(
-        handler)
+    final RecursiveFutureResult<SearchResultEntry, Schema> future =
+      new RecursiveFutureResult<SearchResultEntry, Schema>(handler)
     {
 
+      @Override
       protected FutureResult<Schema> chainResult(
-          SearchResultEntry innerResult,
-          ResultHandler<? super Schema> handler)
+          final SearchResultEntry innerResult,
+          final ResultHandler<? super Schema> handler)
           throws ErrorResultException
       {
         final DN subschemaDN = getSubschemaSubentryDN(name, innerResult);
@@ -1756,43 +1709,40 @@
 
 
   /**
-   * Reads the schema from the Directory Server which applies to the
-   * named entry using the provided connection.
+   * Reads the schema from the Directory Server which applies to the named entry
+   * using the provided connection.
    * <p>
-   * If the requested entry or its associated schema are not returned by
-   * the Directory Server then the request will fail with an
-   * {@link EntryNotFoundException}. More specifically, this method will
-   * never return {@code null}.
+   * If the requested entry or its associated schema are not returned by the
+   * Directory Server then the request will fail with an
+   * {@link EntryNotFoundException}. More specifically, this method will never
+   * return {@code null}.
    * <p>
-   * A typical implementation will first read the {@code
-   * subschemaSubentry} attribute of the entry in order to locate the
-   * schema. However, implementations may choose to perform other
-   * optimizations, such as caching.
+   * This implementation first reads the {@code subschemaSubentry} attribute of
+   * the entry in order to identify the schema and then invokes
+   * {@link #readSchema} to read the schema. More specifically, it does not use
+   * the {@link Connection#readSchemaForEntry} method.
    *
    * @param connection
-   *          A connection to the Directory Server whose schema is to be
-   *          read.
+   *          A connection to the Directory Server whose schema is to be read.
    * @param name
-   *          The distinguished name of the entry whose schema is to be
-   *          located.
-   * @return The schema from the Directory Server which applies to the
-   *         named entry.
+   *          The distinguished name of the entry whose schema is to be located.
+   * @return The schema from the Directory Server which applies to the named
+   *         entry.
    * @throws ErrorResultException
-   *           If the result code indicates that the request failed for
-   *           some reason.
+   *           If the result code indicates that the request failed for some
+   *           reason.
    * @throws InterruptedException
    *           If the current thread was interrupted while waiting.
    * @throws UnsupportedOperationException
    *           If the connection does not support search operations.
    * @throws IllegalStateException
-   *           If the connection has already been closed, i.e. if
-   *           {@code isClosed() == true}.
+   *           If the connection has already been closed, i.e. if {@code
+   *           isClosed() == true}.
    * @throws NullPointerException
-   *           If the {@code connection} or {@code name} was {@code
-   *           null}.
+   *           If the {@code connection} or {@code name} was {@code null}.
    */
-  public static Schema readSchemaForEntry(Connection connection, DN name)
-      throws ErrorResultException, InterruptedException,
+  public static Schema readSchemaForEntry(final Connection connection,
+      final DN name) throws ErrorResultException, InterruptedException,
       UnsupportedOperationException, IllegalStateException,
       NullPointerException
   {
@@ -1806,33 +1756,31 @@
 
 
   /**
-   * Sets the default schema which should be used by this application.
-   * The default schema is initially set to the core schema.
+   * Sets the default schema which should be used by this application. The
+   * default schema is initially set to the core schema.
    *
    * @param schema
-   *          The default schema which should be used by this
-   *          application.
+   *          The default schema which should be used by this application.
    */
-  public static void setDefaultSchema(Schema schema)
+  public static void setDefaultSchema(final Schema schema)
   {
-    DEFAULT_SCHEMA = schema;
+    defaultSchema = schema;
   }
 
 
 
   /**
-   * Parses the provided entry as a subschema subentry. Any problems
-   * encountered while parsing the entry can be retrieved using the
-   * returned schema's {@link #getWarnings()} method.
+   * Parses the provided entry as a subschema subentry. Any problems encountered
+   * while parsing the entry can be retrieved using the returned schema's
+   * {@link #getWarnings()} method.
    *
    * @param entry
    *          The subschema subentry to be parsed.
    * @return The parsed schema.
    */
-  public static Schema valueOf(Entry entry)
+  public static Schema valueOf(final Entry entry)
   {
-    final SchemaBuilder builder = new SchemaBuilder(entry.getName()
-        .toString());
+    final SchemaBuilder builder = new SchemaBuilder(entry.getName().toString());
 
     Attribute attr = entry.getAttribute(ATTR_LDAP_SYNTAXES);
     if (attr != null)
@@ -1967,63 +1915,6 @@
 
 
 
-  // Constructs a search request for retrieving the subschemaSubentry
-  // attribute from the named entry.
-  private static SearchRequest getReadSchemaForEntrySearchRequest(DN dn)
-  {
-    return Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT,
-        Filter.getObjectClassPresentFilter(), SUBSCHEMA_SUBENTRY_ATTRS);
-  }
-
-
-
-  // Constructs a search request for retrieving the named subschema
-  // sub-entry.
-  private static SearchRequest getReadSchemaSearchRequest(DN dn)
-  {
-    return Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT,
-        SUBSCHEMA_FILTER, SUBSCHEMA_ATTRS);
-  }
-
-
-
-  private static DN getSubschemaSubentryDN(DN name, final Entry entry)
-      throws ErrorResultException
-  {
-    final Attribute subentryAttr = entry
-        .getAttribute(ATTR_SUBSCHEMA_SUBENTRY);
-
-    if (subentryAttr == null || subentryAttr.isEmpty())
-    {
-      // Did not get the subschema sub-entry attribute.
-      final Result result = Responses.newResult(
-          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
-          .setDiagnosticMessage(
-              ERR_NO_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString())
-                  .toString());
-      throw ErrorResultException.wrap(result);
-    }
-
-    final String dnString = subentryAttr.iterator().next().toString();
-    DN subschemaDN;
-    try
-    {
-      subschemaDN = DN.valueOf(dnString);
-    }
-    catch (final LocalizedIllegalArgumentException e)
-    {
-      final Result result = Responses.newResult(
-          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED)
-          .setDiagnosticMessage(
-              ERR_INVALID_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString(),
-                  dnString, e.getMessageObject()).toString());
-      throw ErrorResultException.wrap(result);
-    }
-    return subschemaDN;
-  }
-
-
-
   static MatchingRule getDefaultMatchingRule()
   {
     return CoreSchema.getOctetStringMatchingRule();
@@ -2038,44 +1929,98 @@
 
 
 
-  private final Impl impl;
-
-
-
-  private Schema(Impl impl)
+  // Constructs a search request for retrieving the subschemaSubentry
+  // attribute from the named entry.
+  private static SearchRequest getReadSchemaForEntrySearchRequest(final DN dn)
   {
-    this.impl = impl;
+    return Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT, Filter
+        .getObjectClassPresentFilter(), SUBSCHEMA_SUBENTRY_ATTRS);
   }
 
 
 
-  Schema(String schemaName, Map<String, Syntax> numericOID2Syntaxes,
-      Map<String, MatchingRule> numericOID2MatchingRules,
-      Map<String, MatchingRuleUse> numericOID2MatchingRuleUses,
-      Map<String, AttributeType> numericOID2AttributeTypes,
-      Map<String, ObjectClass> numericOID2ObjectClasses,
-      Map<String, NameForm> numericOID2NameForms,
-      Map<String, DITContentRule> numericOID2ContentRules,
-      Map<Integer, DITStructureRule> id2StructureRules,
-      Map<String, List<MatchingRule>> name2MatchingRules,
-      Map<String, List<MatchingRuleUse>> name2MatchingRuleUses,
-      Map<String, List<AttributeType>> name2AttributeTypes,
-      Map<String, List<ObjectClass>> name2ObjectClasses,
-      Map<String, List<NameForm>> name2NameForms,
-      Map<String, List<DITContentRule>> name2ContentRules,
-      Map<String, List<DITStructureRule>> name2StructureRules,
-      Map<String, List<NameForm>> objectClass2NameForms,
-      Map<String, List<DITStructureRule>> nameForm2StructureRules,
-      SchemaCompatOptions options, List<LocalizableMessage> warnings)
+  // Constructs a search request for retrieving the named subschema
+  // sub-entry.
+  private static SearchRequest getReadSchemaSearchRequest(final DN dn)
+  {
+    return Requests.newSearchRequest(dn, SearchScope.BASE_OBJECT,
+        SUBSCHEMA_FILTER, SUBSCHEMA_ATTRS);
+  }
+
+
+
+  private static DN getSubschemaSubentryDN(final DN name, final Entry entry)
+      throws ErrorResultException
+  {
+    final Attribute subentryAttr = entry.getAttribute(ATTR_SUBSCHEMA_SUBENTRY);
+
+    if (subentryAttr == null || subentryAttr.isEmpty())
+    {
+      // Did not get the subschema sub-entry attribute.
+      final Result result = Responses.newResult(
+          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED).setDiagnosticMessage(
+          ERR_NO_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString()).toString());
+      throw ErrorResultException.wrap(result);
+    }
+
+    final String dnString = subentryAttr.iterator().next().toString();
+    DN subschemaDN;
+    try
+    {
+      subschemaDN = DN.valueOf(dnString);
+    }
+    catch (final LocalizedIllegalArgumentException e)
+    {
+      final Result result = Responses.newResult(
+          ResultCode.CLIENT_SIDE_NO_RESULTS_RETURNED).setDiagnosticMessage(
+          ERR_INVALID_SUBSCHEMA_SUBENTRY_ATTR.get(name.toString(), dnString,
+              e.getMessageObject()).toString());
+      throw ErrorResultException.wrap(result);
+    }
+    return subschemaDN;
+  }
+
+
+
+  private final Impl impl;
+
+
+
+  Schema(final String schemaName,
+      final Map<String, Syntax> numericOID2Syntaxes,
+      final Map<String, MatchingRule> numericOID2MatchingRules,
+      final Map<String, MatchingRuleUse> numericOID2MatchingRuleUses,
+      final Map<String, AttributeType> numericOID2AttributeTypes,
+      final Map<String, ObjectClass> numericOID2ObjectClasses,
+      final Map<String, NameForm> numericOID2NameForms,
+      final Map<String, DITContentRule> numericOID2ContentRules,
+      final Map<Integer, DITStructureRule> id2StructureRules,
+      final Map<String, List<MatchingRule>> name2MatchingRules,
+      final Map<String, List<MatchingRuleUse>> name2MatchingRuleUses,
+      final Map<String, List<AttributeType>> name2AttributeTypes,
+      final Map<String, List<ObjectClass>> name2ObjectClasses,
+      final Map<String, List<NameForm>> name2NameForms,
+      final Map<String, List<DITContentRule>> name2ContentRules,
+      final Map<String, List<DITStructureRule>> name2StructureRules,
+      final Map<String, List<NameForm>> objectClass2NameForms,
+      final Map<String, List<DITStructureRule>> nameForm2StructureRules,
+      final SchemaCompatOptions options, final List<LocalizableMessage> warnings)
   {
     impl = new StrictImpl(schemaName, numericOID2Syntaxes,
         numericOID2MatchingRules, numericOID2MatchingRuleUses,
         numericOID2AttributeTypes, numericOID2ObjectClasses,
-        numericOID2NameForms, numericOID2ContentRules,
-        id2StructureRules, name2MatchingRules, name2MatchingRuleUses,
-        name2AttributeTypes, name2ObjectClasses, name2NameForms,
-        name2ContentRules, name2StructureRules, objectClass2NameForms,
-        nameForm2StructureRules, options, warnings);
+        numericOID2NameForms, numericOID2ContentRules, id2StructureRules,
+        name2MatchingRules, name2MatchingRuleUses, name2AttributeTypes,
+        name2ObjectClasses, name2NameForms, name2ContentRules,
+        name2StructureRules, objectClass2NameForms, nameForm2StructureRules,
+        options, warnings);
+  }
+
+
+
+  private Schema(final Impl impl)
+  {
+    this.impl = impl;
   }
 
 
@@ -2087,10 +2032,10 @@
    *          The name or OID of the attribute type to retrieve.
    * @return The requested attribute type.
    * @throws UnknownSchemaElementException
-   *           If this is a strict schema and the requested attribute
-   *           type was not found or if the provided name is ambiguous.
+   *           If this is a strict schema and the requested attribute type was
+   *           not found or if the provided name is ambiguous.
    */
-  public AttributeType getAttributeType(String name)
+  public AttributeType getAttributeType(final String name)
       throws UnknownSchemaElementException
   {
     return impl.getAttributeType(name);
@@ -2099,11 +2044,11 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the attribute
-   * types contained in this schema.
+   * Returns an unmodifiable collection containing all of the attribute types
+   * contained in this schema.
    *
-   * @return An unmodifiable collection containing all of the attribute
-   *         types contained in this schema.
+   * @return An unmodifiable collection containing all of the attribute types
+   *         contained in this schema.
    */
   public Collection<AttributeType> getAttributeTypes()
   {
@@ -2113,15 +2058,15 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the attribute
-   * types having the specified name or numeric OID.
+   * Returns an unmodifiable collection containing all of the attribute types
+   * having the specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the attribute types to retrieve.
-   * @return An unmodifiable collection containing all of the attribute
-   *         types having the specified name or numeric OID.
+   * @return An unmodifiable collection containing all of the attribute types
+   *         having the specified name or numeric OID.
    */
-  public List<AttributeType> getAttributeTypesByName(String name)
+  public List<AttributeType> getAttributeTypesByName(final String name)
   {
     return impl.getAttributeTypesByName(name);
   }
@@ -2129,17 +2074,16 @@
 
 
   /**
-   * Returns the DIT content rule with the specified name or numeric
-   * OID.
+   * Returns the DIT content rule with the specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the DIT content rule to retrieve.
    * @return The requested DIT content rule.
    * @throws UnknownSchemaElementException
-   *           If this is a strict schema and the requested DIT content
-   *           rule was not found or if the provided name is ambiguous.
+   *           If this is a strict schema and the requested DIT content rule was
+   *           not found or if the provided name is ambiguous.
    */
-  public DITContentRule getDITContentRule(String name)
+  public DITContentRule getDITContentRule(final String name)
       throws UnknownSchemaElementException
   {
     return impl.getDITContentRule(name);
@@ -2148,11 +2092,11 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the DIT
-   * content rules contained in this schema.
+   * Returns an unmodifiable collection containing all of the DIT content rules
+   * contained in this schema.
    *
-   * @return An unmodifiable collection containing all of the DIT
-   *         content rules contained in this schema.
+   * @return An unmodifiable collection containing all of the DIT content rules
+   *         contained in this schema.
    */
   public Collection<DITContentRule> getDITContentRules()
   {
@@ -2162,15 +2106,15 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the DIT
-   * content rules having the specified name or numeric OID.
+   * Returns an unmodifiable collection containing all of the DIT content rules
+   * having the specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the DIT content rules to retrieve.
-   * @return An unmodifiable collection containing all of the DIT
-   *         content rules having the specified name or numeric OID.
+   * @return An unmodifiable collection containing all of the DIT content rules
+   *         having the specified name or numeric OID.
    */
-  public Collection<DITContentRule> getDITContentRulesByName(String name)
+  public Collection<DITContentRule> getDITContentRulesByName(final String name)
   {
     return impl.getDITContentRulesByName(name);
   }
@@ -2178,17 +2122,16 @@
 
 
   /**
-   * Returns the DIT structure rule with the specified name or numeric
-   * OID.
+   * Returns the DIT structure rule with the specified name or numeric OID.
    *
    * @param ruleID
    *          The ID of the DIT structure rule to retrieve.
    * @return The requested DIT structure rule.
    * @throws UnknownSchemaElementException
-   *           If this is a strict schema and the requested DIT
-   *           structure rule was not found.
+   *           If this is a strict schema and the requested DIT structure rule
+   *           was not found.
    */
-  public DITStructureRule getDITStructureRule(int ruleID)
+  public DITStructureRule getDITStructureRule(final int ruleID)
       throws UnknownSchemaElementException
   {
     return impl.getDITStructureRule(ruleID);
@@ -2197,16 +2140,16 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the DIT
-   * structure rules having the specified name or numeric OID.
+   * Returns an unmodifiable collection containing all of the DIT structure
+   * rules having the specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the DIT structure rules to retrieve.
-   * @return An unmodifiable collection containing all of the DIT
-   *         structure rules having the specified name or numeric OID.
+   * @return An unmodifiable collection containing all of the DIT structure
+   *         rules having the specified name or numeric OID.
    */
   public Collection<DITStructureRule> getDITStructureRulesByName(
-      String name)
+      final String name)
   {
     return impl.getDITStructureRulesByName(name);
   }
@@ -2221,7 +2164,7 @@
    * @return The requested DIT structure rules.
    */
   public Collection<DITStructureRule> getDITStructureRulesByNameForm(
-      NameForm nameForm)
+      final NameForm nameForm)
   {
     return impl.getDITStructureRulesByNameForm(nameForm);
   }
@@ -2229,11 +2172,11 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the DIT
-   * structure rules contained in this schema.
+   * Returns an unmodifiable collection containing all of the DIT structure
+   * rules contained in this schema.
    *
-   * @return An unmodifiable collection containing all of the DIT
-   *         structure rules contained in this schema.
+   * @return An unmodifiable collection containing all of the DIT structure
+   *         rules contained in this schema.
    */
   public Collection<DITStructureRule> getDITStuctureRules()
   {
@@ -2249,10 +2192,10 @@
    *          The name or OID of the matching rule to retrieve.
    * @return The requested matching rule.
    * @throws UnknownSchemaElementException
-   *           If this is a strict schema and the requested matching
-   *           rule was not found or if the provided name is ambiguous.
+   *           If this is a strict schema and the requested matching rule was
+   *           not found or if the provided name is ambiguous.
    */
-  public MatchingRule getMatchingRule(String name)
+  public MatchingRule getMatchingRule(final String name)
       throws UnknownSchemaElementException
   {
     return impl.getMatchingRule(name);
@@ -2261,11 +2204,11 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the matching
-   * rules contained in this schema.
+   * Returns an unmodifiable collection containing all of the matching rules
+   * contained in this schema.
    *
-   * @return An unmodifiable collection containing all of the matching
-   *         rules contained in this schema.
+   * @return An unmodifiable collection containing all of the matching rules
+   *         contained in this schema.
    */
   public Collection<MatchingRule> getMatchingRules()
   {
@@ -2275,15 +2218,15 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the matching
-   * rules having the specified name or numeric OID.
+   * Returns an unmodifiable collection containing all of the matching rules
+   * having the specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the matching rules to retrieve.
-   * @return An unmodifiable collection containing all of the matching
-   *         rules having the specified name or numeric OID.
+   * @return An unmodifiable collection containing all of the matching rules
+   *         having the specified name or numeric OID.
    */
-  public Collection<MatchingRule> getMatchingRulesByName(String name)
+  public Collection<MatchingRule> getMatchingRulesByName(final String name)
   {
     return impl.getMatchingRulesByName(name);
   }
@@ -2291,19 +2234,16 @@
 
 
   /**
-   * Returns the matching rule use associated with the provided matching
-   * rule.
+   * Returns the matching rule use associated with the provided matching rule.
    *
    * @param matchingRule
-   *          The matching rule whose matching rule use is to be
-   *          retrieved.
+   *          The matching rule whose matching rule use is to be retrieved.
    * @return The requested matching rule use.
    * @throws UnknownSchemaElementException
-   *           If this is a strict schema and the requested matching
-   *           rule use was not found or if the provided name is
-   *           ambiguous.
+   *           If this is a strict schema and the requested matching rule use
+   *           was not found or if the provided name is ambiguous.
    */
-  public MatchingRuleUse getMatchingRuleUse(MatchingRule matchingRule)
+  public MatchingRuleUse getMatchingRuleUse(final MatchingRule matchingRule)
       throws UnknownSchemaElementException
   {
     return getMatchingRuleUse(matchingRule.getOID());
@@ -2312,18 +2252,16 @@
 
 
   /**
-   * Returns the matching rule use with the specified name or numeric
-   * OID.
+   * Returns the matching rule use with the specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the matching rule use to retrieve.
    * @return The requested matching rule use.
    * @throws UnknownSchemaElementException
-   *           If this is a strict schema and the requested matching
-   *           rule use was not found or if the provided name is
-   *           ambiguous.
+   *           If this is a strict schema and the requested matching rule use
+   *           was not found or if the provided name is ambiguous.
    */
-  public MatchingRuleUse getMatchingRuleUse(String name)
+  public MatchingRuleUse getMatchingRuleUse(final String name)
       throws UnknownSchemaElementException
   {
     return impl.getMatchingRuleUse(name);
@@ -2332,11 +2270,11 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the matching
-   * rule uses contained in this schema.
+   * Returns an unmodifiable collection containing all of the matching rule uses
+   * contained in this schema.
    *
-   * @return An unmodifiable collection containing all of the matching
-   *         rule uses contained in this schema.
+   * @return An unmodifiable collection containing all of the matching rule uses
+   *         contained in this schema.
    */
   public Collection<MatchingRuleUse> getMatchingRuleUses()
   {
@@ -2346,16 +2284,15 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the matching
-   * rule uses having the specified name or numeric OID.
+   * Returns an unmodifiable collection containing all of the matching rule uses
+   * having the specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the matching rule uses to retrieve.
-   * @return An unmodifiable collection containing all of the matching
-   *         rule uses having the specified name or numeric OID.
+   * @return An unmodifiable collection containing all of the matching rule uses
+   *         having the specified name or numeric OID.
    */
-  public Collection<MatchingRuleUse> getMatchingRuleUsesByName(
-      String name)
+  public Collection<MatchingRuleUse> getMatchingRuleUsesByName(final String name)
   {
     return impl.getMatchingRuleUsesByName(name);
   }
@@ -2369,10 +2306,10 @@
    *          The name or OID of the name form to retrieve.
    * @return The requested name form.
    * @throws UnknownSchemaElementException
-   *           If this is a strict schema and the requested name form
-   *           was not found or if the provided name is ambiguous.
+   *           If this is a strict schema and the requested name form was not
+   *           found or if the provided name is ambiguous.
    */
-  public NameForm getNameForm(String name)
+  public NameForm getNameForm(final String name)
       throws UnknownSchemaElementException
   {
     return impl.getNameForm(name);
@@ -2388,7 +2325,7 @@
    * @return The requested name forms
    */
   public Collection<NameForm> getNameFormByObjectClass(
-      ObjectClass structuralClass)
+      final ObjectClass structuralClass)
   {
     return impl.getNameFormByObjectClass(structuralClass);
   }
@@ -2410,15 +2347,15 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the name forms
-   * having the specified name or numeric OID.
+   * Returns an unmodifiable collection containing all of the name forms having
+   * the specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the name forms to retrieve.
-   * @return An unmodifiable collection containing all of the name forms
-   *         having the specified name or numeric OID.
+   * @return An unmodifiable collection containing all of the name forms having
+   *         the specified name or numeric OID.
    */
-  public Collection<NameForm> getNameFormsByName(String name)
+  public Collection<NameForm> getNameFormsByName(final String name)
   {
     return impl.getNameFormsByName(name);
   }
@@ -2432,10 +2369,10 @@
    *          The name or OID of the object class to retrieve.
    * @return The requested object class.
    * @throws UnknownSchemaElementException
-   *           If this is a strict schema and the requested object class
-   *           was not found or if the provided name is ambiguous.
+   *           If this is a strict schema and the requested object class was not
+   *           found or if the provided name is ambiguous.
    */
-  public ObjectClass getObjectClass(String name)
+  public ObjectClass getObjectClass(final String name)
       throws UnknownSchemaElementException
   {
     return impl.getObjectClass(name);
@@ -2444,11 +2381,11 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the object
-   * classes contained in this schema.
+   * Returns an unmodifiable collection containing all of the object classes
+   * contained in this schema.
    *
-   * @return An unmodifiable collection containing all of the object
-   *         classes contained in this schema.
+   * @return An unmodifiable collection containing all of the object classes
+   *         contained in this schema.
    */
   public Collection<ObjectClass> getObjectClasses()
   {
@@ -2458,15 +2395,15 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the object
-   * classes having the specified name or numeric OID.
+   * Returns an unmodifiable collection containing all of the object classes
+   * having the specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the object classes to retrieve.
-   * @return An unmodifiable collection containing all of the object
-   *         classes having the specified name or numeric OID.
+   * @return An unmodifiable collection containing all of the object classes
+   *         having the specified name or numeric OID.
    */
-  public Collection<ObjectClass> getObjectClassesByName(String name)
+  public Collection<ObjectClass> getObjectClassesByName(final String name)
   {
     return impl.getObjectClassesByName(name);
   }
@@ -2475,9 +2412,9 @@
 
   /**
    * Returns the user-friendly name of this schema which may be used for
-   * debugging purposes. The format of the schema name is not defined
-   * but should contain the distinguished name of the subschema
-   * sub-entry for those schemas retrieved from a Directory Server.
+   * debugging purposes. The format of the schema name is not defined but should
+   * contain the distinguished name of the subschema sub-entry for those schemas
+   * retrieved from a Directory Server.
    *
    * @return The user-friendly name of this schema which may be used for
    *         debugging purposes.
@@ -2496,10 +2433,10 @@
    *          The OID of the syntax to retrieve.
    * @return The requested syntax.
    * @throws UnknownSchemaElementException
-   *           If this is a strict schema and the requested syntax was
-   *           not found or if the provided name is ambiguous.
+   *           If this is a strict schema and the requested syntax was not found
+   *           or if the provided name is ambiguous.
    */
-  public Syntax getSyntax(String numericOID)
+  public Syntax getSyntax(final String numericOID)
       throws UnknownSchemaElementException
   {
     return impl.getSyntax(numericOID);
@@ -2508,11 +2445,11 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the syntaxes
-   * contained in this schema.
+   * Returns an unmodifiable collection containing all of the syntaxes contained
+   * in this schema.
    *
-   * @return An unmodifiable collection containing all of the syntaxes
-   *         contained in this schema.
+   * @return An unmodifiable collection containing all of the syntaxes contained
+   *         in this schema.
    */
   public Collection<Syntax> getSyntaxes()
   {
@@ -2522,11 +2459,11 @@
 
 
   /**
-   * Returns an unmodifiable collection containing all of the warnings
-   * that were detected when this schema was constructed.
+   * Returns an unmodifiable collection containing all of the warnings that were
+   * detected when this schema was constructed.
    *
-   * @return An unmodifiable collection containing all of the warnings
-   *         that were detected when this schema was constructed.
+   * @return An unmodifiable collection containing all of the warnings that were
+   *         detected when this schema was constructed.
    */
   public Collection<LocalizableMessage> getWarnings()
   {
@@ -2536,15 +2473,15 @@
 
 
   /**
-   * Indicates whether or not this schema contains an attribute type
-   * with the specified name or numeric OID.
+   * Indicates whether or not this schema contains an attribute type with the
+   * specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the attribute type.
-   * @return {@code true} if this schema contains an attribute type with
-   *         the specified name or numeric OID, otherwise {@code false}.
+   * @return {@code true} if this schema contains an attribute type with the
+   *         specified name or numeric OID, otherwise {@code false}.
    */
-  public boolean hasAttributeType(String name)
+  public boolean hasAttributeType(final String name)
   {
     return impl.hasAttributeType(name);
   }
@@ -2552,16 +2489,15 @@
 
 
   /**
-   * Indicates whether or not this schema contains a DIT content rule
-   * with the specified name or numeric OID.
+   * Indicates whether or not this schema contains a DIT content rule with the
+   * specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the DIT content rule.
-   * @return {@code true} if this schema contains a DIT content rule
-   *         with the specified name or numeric OID, otherwise {@code
-   *         false}.
+   * @return {@code true} if this schema contains a DIT content rule with the
+   *         specified name or numeric OID, otherwise {@code false}.
    */
-  public boolean hasDITContentRule(String name)
+  public boolean hasDITContentRule(final String name)
   {
     return impl.hasDITContentRule(name);
   }
@@ -2569,15 +2505,15 @@
 
 
   /**
-   * Indicates whether or not this schema contains a DIT structure rule
-   * with the specified rule ID.
+   * Indicates whether or not this schema contains a DIT structure rule with the
+   * specified rule ID.
    *
    * @param ruleID
    *          The ID of the DIT structure rule.
-   * @return {@code true} if this schema contains a DIT structure rule
-   *         with the specified rule ID, otherwise {@code false}.
+   * @return {@code true} if this schema contains a DIT structure rule with the
+   *         specified rule ID, otherwise {@code false}.
    */
-  public boolean hasDITStructureRule(int ruleID)
+  public boolean hasDITStructureRule(final int ruleID)
   {
     return impl.hasDITStructureRule(ruleID);
   }
@@ -2585,15 +2521,15 @@
 
 
   /**
-   * Indicates whether or not this schema contains a matching rule with
-   * the specified name or numeric OID.
+   * Indicates whether or not this schema contains a matching rule with the
+   * specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the matching rule.
-   * @return {@code true} if this schema contains a matching rule with
-   *         the specified name or numeric OID, otherwise {@code false}.
+   * @return {@code true} if this schema contains a matching rule with the
+   *         specified name or numeric OID, otherwise {@code false}.
    */
-  public boolean hasMatchingRule(String name)
+  public boolean hasMatchingRule(final String name)
   {
     return impl.hasMatchingRule(name);
   }
@@ -2601,16 +2537,15 @@
 
 
   /**
-   * Indicates whether or not this schema contains a matching rule use
-   * with the specified name or numeric OID.
+   * Indicates whether or not this schema contains a matching rule use with the
+   * specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the matching rule use.
-   * @return {@code true} if this schema contains a matching rule use
-   *         with the specified name or numeric OID, otherwise {@code
-   *         false}.
+   * @return {@code true} if this schema contains a matching rule use with the
+   *         specified name or numeric OID, otherwise {@code false}.
    */
-  public boolean hasMatchingRuleUse(String name)
+  public boolean hasMatchingRuleUse(final String name)
   {
     return impl.hasMatchingRuleUse(name);
   }
@@ -2623,10 +2558,10 @@
    *
    * @param name
    *          The name or OID of the name form.
-   * @return {@code true} if this schema contains a name form with the
-   *         specified name or numeric OID, otherwise {@code false}.
+   * @return {@code true} if this schema contains a name form with the specified
+   *         name or numeric OID, otherwise {@code false}.
    */
-  public boolean hasNameForm(String name)
+  public boolean hasNameForm(final String name)
   {
     return impl.hasNameForm(name);
   }
@@ -2634,15 +2569,15 @@
 
 
   /**
-   * Indicates whether or not this schema contains an object class with
-   * the specified name or numeric OID.
+   * Indicates whether or not this schema contains an object class with the
+   * specified name or numeric OID.
    *
    * @param name
    *          The name or OID of the object class.
-   * @return {@code true} if this schema contains an object class with
-   *         the specified name or numeric OID, otherwise {@code false}.
+   * @return {@code true} if this schema contains an object class with the
+   *         specified name or numeric OID, otherwise {@code false}.
    */
-  public boolean hasObjectClass(String name)
+  public boolean hasObjectClass(final String name)
   {
     return impl.hasObjectClass(name);
   }
@@ -2650,15 +2585,15 @@
 
 
   /**
-   * Indicates whether or not this schema contains a syntax with the
-   * specified numeric OID.
+   * Indicates whether or not this schema contains a syntax with the specified
+   * numeric OID.
    *
    * @param numericOID
    *          The OID of the syntax.
-   * @return {@code true} if this schema contains a syntax with the
-   *         specified numeric OID, otherwise {@code false}.
+   * @return {@code true} if this schema contains a syntax with the specified
+   *         numeric OID, otherwise {@code false}.
    */
-  public boolean hasSyntax(String numericOID)
+  public boolean hasSyntax(final String numericOID)
   {
     return impl.hasSyntax(numericOID);
   }
@@ -2666,13 +2601,12 @@
 
 
   /**
-   * Indicates whether or not this schema is strict. Attribute type
-   * queries in non-strict schema always succeed: if the requested
-   * attribute type is not found then a temporary attribute type is
-   * created automatically having the Octet String syntax and associated
-   * matching rules. Strict schema, on the other hand, throw an
-   * {@link UnknownSchemaElementException} whenever an attempt is made
-   * to retrieve a non-existent attribute type.
+   * Indicates whether or not this schema is strict. Attribute type queries in
+   * non-strict schema always succeed: if the requested attribute type is not
+   * found then a temporary attribute type is created automatically having the
+   * Octet String syntax and associated matching rules. Strict schema, on the
+   * other hand, throw an {@link UnknownSchemaElementException} whenever an
+   * attempt is made to retrieve a non-existent attribute type.
    *
    * @return {@code true} if this schema is strict.
    */
@@ -2685,12 +2619,11 @@
 
   /**
    * Returns a non-strict view of this schema. Attribute type queries in
-   * non-strict schema always succeed: if the requested attribute type
-   * is not found then a temporary attribute type is created
-   * automatically having the Octet String syntax and associated
-   * matching rules. Strict schema, on the other hand, throw an
-   * {@link UnknownSchemaElementException} whenever an attempt is made
-   * to retrieve a non-existent attribute type.
+   * non-strict schema always succeed: if the requested attribute type is not
+   * found then a temporary attribute type is created automatically having the
+   * Octet String syntax and associated matching rules. Strict schema, on the
+   * other hand, throw an {@link UnknownSchemaElementException} whenever an
+   * attempt is made to retrieve a non-existent attribute type.
    *
    * @return A non-strict view of this schema.
    */
diff --git a/sdk/src/org/opends/sdk/schema/SchemaBuilder.java b/sdk/src/org/opends/sdk/schema/SchemaBuilder.java
index cd54d12..2dcd5ce 100644
--- a/sdk/src/org/opends/sdk/schema/SchemaBuilder.java
+++ b/sdk/src/org/opends/sdk/schema/SchemaBuilder.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk.schema;
@@ -30,7 +30,13 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EXTENSIBLE_OBJECT_OBJECTCLASS_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_GENERIC_ENUM_NAME;
+import static org.opends.sdk.schema.SchemaConstants.SCHEMA_PROPERTY_APPROX_RULE;
+import static org.opends.sdk.schema.SchemaConstants.TOP_OBJECTCLASS_NAME;
+import static org.opends.sdk.schema.SchemaUtils.unmodifiableCopyOfExtraProperties;
+import static org.opends.sdk.schema.SchemaUtils.unmodifiableCopyOfList;
+import static org.opends.sdk.schema.SchemaUtils.unmodifiableCopyOfSet;
 
 import java.util.*;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -47,8 +53,7 @@
 
 
 /**
- * Schema builders should be used for incremental construction of new
- * schemas.
+ * Schema builders should be used for incremental construction of new schemas.
  */
 public final class SchemaBuilder
 {
@@ -111,15 +116,15 @@
 
 
   /**
-   * Creates a new schema builder containing all of the schema elements
-   * from the provided schema and its compatibility options.
-   * 
+   * Creates a new schema builder containing all of the schema elements from the
+   * provided schema and its compatibility options.
+   *
    * @param schema
    *          The initial contents of the schema builder.
    * @throws NullPointerException
    *           If {@code schema} was {@code null}.
    */
-  public SchemaBuilder(Schema schema) throws NullPointerException
+  public SchemaBuilder(final Schema schema) throws NullPointerException
   {
     initBuilder(schema.getSchemaName());
     setSchemaCompatOptions(schema.getSchemaCompatOptions());
@@ -131,12 +136,12 @@
   /**
    * Creates a new schema builder with no schema elements and default
    * compatibility options.
-   * 
+   *
    * @param schemaName
-   *          The user-friendly name of this schema which may be used
-   *          for debugging purposes.
+   *          The user-friendly name of this schema which may be used for
+   *          debugging purposes.
    */
-  public SchemaBuilder(String schemaName)
+  public SchemaBuilder(final String schemaName)
   {
     initBuilder(schemaName);
   }
@@ -145,25 +150,24 @@
 
   /**
    * Adds the provided attribute type definition to this schema builder.
-   * 
+   *
    * @param definition
    *          The attribute type definition.
    * @param overwrite
-   *          {@code true} if any existing attribute type with the same
-   *          OID should be overwritten.
+   *          {@code true} if any existing attribute type with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
-   * @throws LocalizedIllegalArgumentException
-   *           If the provided attribute type definition could not be
-   *           parsed.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
+   * @throws LocalizedIllegalArgumentException
+   *           If the provided attribute type definition could not be parsed.
    * @throws NullPointerException
    *           If {@code definition} was {@code null}.
    */
-  public SchemaBuilder addAttributeType(String definition,
-      boolean overwrite) throws LocalizedIllegalArgumentException,
-      ConflictingSchemaElementException
+  public SchemaBuilder addAttributeType(final String definition,
+      final boolean overwrite) throws ConflictingSchemaElementException,
+      LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(definition);
     try
@@ -213,8 +217,7 @@
       boolean isCollective = false;
       boolean isNoUserModification = false;
       AttributeUsage attributeUsage = AttributeUsage.USER_APPLICATIONS;
-      Map<String, List<String>> extraProperties = Collections
-          .emptyMap();
+      Map<String, List<String>> extraProperties = Collections.emptyMap();
 
       // At this point, we should have a pretty specific syntax that
       // describes what may come next, but some of the components are
@@ -368,8 +371,7 @@
           {
             extraProperties = new HashMap<String, List<String>>();
           }
-          extraProperties.put(tokenName, SchemaUtils
-              .readExtensions(reader));
+          extraProperties.put(tokenName, SchemaUtils.readExtensions(reader));
         }
         else
         {
@@ -386,19 +388,23 @@
         approximateMatchingRule = approxRules.get(0);
       }
 
-      final AttributeType attrType = new AttributeType(oid, names,
-          description, isObsolete, superiorType, equalityMatchingRule,
-          orderingMatchingRule, substringMatchingRule,
-          approximateMatchingRule, syntax, isSingleValue, isCollective,
-          isNoUserModification, attributeUsage, extraProperties,
-          definition);
+      if (!extraProperties.isEmpty())
+      {
+        extraProperties = Collections.unmodifiableMap(extraProperties);
+      }
+
+      final AttributeType attrType = new AttributeType(oid, names, description,
+          isObsolete, superiorType, equalityMatchingRule, orderingMatchingRule,
+          substringMatchingRule, approximateMatchingRule, syntax,
+          isSingleValue, isCollective, isNoUserModification, attributeUsage,
+          extraProperties, definition);
 
       addAttributeType(attrType, overwrite);
     }
     catch (final DecodeException e)
     {
-      throw new LocalizedIllegalArgumentException(e.getMessageObject(),
-          e.getCause());
+      throw new LocalizedIllegalArgumentException(e.getMessageObject(), e
+          .getCause());
     }
     return this;
   }
@@ -407,7 +413,7 @@
 
   /**
    * Adds the provided attribute type definition to this schema builder.
-   * 
+   *
    * @param oid
    *          The OID of the attribute type definition.
    * @param names
@@ -420,63 +426,65 @@
    * @param superiorType
    *          The OID of the superior attribute type definition.
    * @param equalityMatchingRule
-   *          The OID of the equality matching rule, which may be
-   *          {@code null} indicating that the superior attribute type's
-   *          matching rule should be used or, if none is defined, the
-   *          default matching rule associated with the syntax.
+   *          The OID of the equality matching rule, which may be {@code null}
+   *          indicating that the superior attribute type's matching rule should
+   *          be used or, if none is defined, the default matching rule
+   *          associated with the syntax.
    * @param orderingMatchingRule
-   *          The OID of the ordering matching rule, which may be
-   *          {@code null} indicating that the superior attribute type's
-   *          matching rule should be used or, if none is defined, the
-   *          default matching rule associated with the syntax.
+   *          The OID of the ordering matching rule, which may be {@code null}
+   *          indicating that the superior attribute type's matching rule should
+   *          be used or, if none is defined, the default matching rule
+   *          associated with the syntax.
    * @param substringMatchingRule
-   *          The OID of the substring matching rule, which may be
-   *          {@code null} indicating that the superior attribute type's
-   *          matching rule should be used or, if none is defined, the
-   *          default matching rule associated with the syntax.
+   *          The OID of the substring matching rule, which may be {@code null}
+   *          indicating that the superior attribute type's matching rule should
+   *          be used or, if none is defined, the default matching rule
+   *          associated with the syntax.
    * @param approximateMatchingRule
-   *          The OID of the approximate matching rule, which may be
-   *          {@code null} indicating that the superior attribute type's
-   *          matching rule should be used or, if none is defined, the
-   *          default matching rule associated with the syntax.
+   *          The OID of the approximate matching rule, which may be {@code
+   *          null} indicating that the superior attribute type's matching rule
+   *          should be used or, if none is defined, the default matching rule
+   *          associated with the syntax.
    * @param syntax
    *          The OID of the syntax definition.
    * @param singleValue
-   *          {@code true} if the attribute type definition is
-   *          single-valued, otherwise {@code false}.
+   *          {@code true} if the attribute type definition is single-valued,
+   *          otherwise {@code false}.
    * @param collective
-   *          {@code true} if the attribute type definition is a
-   *          collective attribute, otherwise {@code false}.
+   *          {@code true} if the attribute type definition is a collective
+   *          attribute, otherwise {@code false}.
    * @param noUserModification
-   *          {@code true} if the attribute type definition is
-   *          read-only, otherwise {@code false}.
+   *          {@code true} if the attribute type definition is read-only,
+   *          otherwise {@code false}.
    * @param attributeUsage
    *          The intended use of the attribute type definition.
    * @param extraProperties
    *          A map containing additional properties associated with the
    *          attribute type definition.
    * @param overwrite
-   *          {@code true} if any existing attribute type with the same
-   *          OID should be overwritten.
+   *          {@code true} if any existing attribute type with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    */
-  public SchemaBuilder addAttributeType(String oid, List<String> names,
-      String description, boolean obsolete, String superiorType,
-      String equalityMatchingRule, String orderingMatchingRule,
-      String substringMatchingRule, String approximateMatchingRule,
-      String syntax, boolean singleValue, boolean collective,
-      boolean noUserModification, AttributeUsage attributeUsage,
-      Map<String, List<String>> extraProperties, boolean overwrite)
+  public SchemaBuilder addAttributeType(final String oid,
+      final List<String> names, final String description,
+      final boolean obsolete, final String superiorType,
+      final String equalityMatchingRule, final String orderingMatchingRule,
+      final String substringMatchingRule, final String approximateMatchingRule,
+      final String syntax, final boolean singleValue, final boolean collective,
+      final boolean noUserModification, final AttributeUsage attributeUsage,
+      final Map<String, List<String>> extraProperties, final boolean overwrite)
       throws ConflictingSchemaElementException
   {
-    final AttributeType attrType = new AttributeType(oid, names,
-        description, obsolete, superiorType, equalityMatchingRule,
-        orderingMatchingRule, substringMatchingRule,
+    final AttributeType attrType = new AttributeType(oid,
+        unmodifiableCopyOfList(names), description, obsolete, superiorType,
+        equalityMatchingRule, orderingMatchingRule, substringMatchingRule,
         approximateMatchingRule, syntax, singleValue, collective,
-        noUserModification, attributeUsage, extraProperties, null);
+        noUserModification, attributeUsage,
+        unmodifiableCopyOfExtraProperties(extraProperties), null);
     addAttributeType(attrType, overwrite);
     return this;
   }
@@ -484,27 +492,25 @@
 
 
   /**
-   * Adds the provided DIT content rule definition to this schema
-   * builder.
-   * 
+   * Adds the provided DIT content rule definition to this schema builder.
+   *
    * @param definition
    *          The DIT content rule definition.
    * @param overwrite
-   *          {@code true} if any existing DIT content rule with the
-   *          same OID should be overwritten.
+   *          {@code true} if any existing DIT content rule with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
-   * @throws LocalizedIllegalArgumentException
-   *           If the provided DIT content rule definition could not be
-   *           parsed.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
+   * @throws LocalizedIllegalArgumentException
+   *           If the provided DIT content rule definition could not be parsed.
    * @throws NullPointerException
    *           If {@code definition} was {@code null}.
    */
-  public SchemaBuilder addDITContentRule(String definition,
-      boolean overwrite) throws LocalizedIllegalArgumentException,
-      ConflictingSchemaElementException
+  public SchemaBuilder addDITContentRule(final String definition,
+      final boolean overwrite) throws ConflictingSchemaElementException,
+      LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(definition);
     try
@@ -548,8 +554,7 @@
       Set<String> optionalAttributes = Collections.emptySet();
       Set<String> prohibitedAttributes = Collections.emptySet();
       Set<String> requiredAttributes = Collections.emptySet();
-      Map<String, List<String>> extraProperties = Collections
-          .emptyMap();
+      Map<String, List<String>> extraProperties = Collections.emptyMap();
 
       // At this point, we should have a pretty specific syntax that
       // describes what may come next, but some of the components are
@@ -613,8 +618,7 @@
           {
             extraProperties = new HashMap<String, List<String>>();
           }
-          extraProperties.put(tokenName, SchemaUtils
-              .readExtensions(reader));
+          extraProperties.put(tokenName, SchemaUtils.readExtensions(reader));
         }
         else
         {
@@ -624,16 +628,20 @@
         }
       }
 
-      final DITContentRule rule = new DITContentRule(structuralClass,
-          names, description, isObsolete, auxiliaryClasses,
-          optionalAttributes, prohibitedAttributes, requiredAttributes,
-          extraProperties, definition);
+      if (!extraProperties.isEmpty())
+      {
+        extraProperties = Collections.unmodifiableMap(extraProperties);
+      }
+
+      final DITContentRule rule = new DITContentRule(structuralClass, names,
+          description, isObsolete, auxiliaryClasses, optionalAttributes,
+          prohibitedAttributes, requiredAttributes, extraProperties, definition);
       addDITContentRule(rule, overwrite);
     }
     catch (final DecodeException e)
     {
-      throw new LocalizedIllegalArgumentException(e.getMessageObject(),
-          e.getCause());
+      throw new LocalizedIllegalArgumentException(e.getMessageObject(), e
+          .getCause());
     }
     return this;
   }
@@ -641,54 +649,57 @@
 
 
   /**
-   * Adds the provided DIT content rule definition to this schema
-   * builder.
-   * 
+   * Adds the provided DIT content rule definition to this schema builder.
+   *
    * @param structuralClass
-   *          The name of the structural object class to which the DIT
-   *          content rule applies.
+   *          The name of the structural object class to which the DIT content
+   *          rule applies.
    * @param names
-   *          The user-friendly names of the DIT content rule
-   *          definition.
+   *          The user-friendly names of the DIT content rule definition.
    * @param description
    *          The description of the DIT content rule definition.
    * @param obsolete
-   *          {@code true} if the DIT content rule definition is
-   *          obsolete, otherwise {@code false}.
+   *          {@code true} if the DIT content rule definition is obsolete,
+   *          otherwise {@code false}.
    * @param auxiliaryClasses
-   *          A list of auxiliary object classes that entries subject to
-   *          the DIT content rule may belong to.
+   *          A list of auxiliary object classes that entries subject to the DIT
+   *          content rule may belong to.
    * @param optionalAttributes
-   *          A list of attribute types that entries subject to the DIT
-   *          content rule may contain.
+   *          A list of attribute types that entries subject to the DIT content
+   *          rule may contain.
    * @param prohibitedAttributes
-   *          A list of attribute types that entries subject to the DIT
-   *          content rule must not contain.
+   *          A list of attribute types that entries subject to the DIT content
+   *          rule must not contain.
    * @param requiredAttributes
-   *          A list of attribute types that entries subject to the DIT
-   *          content rule must contain.
+   *          A list of attribute types that entries subject to the DIT content
+   *          rule must contain.
    * @param extraProperties
-   *          A map containing additional properties associated with the
-   *          DIT content rule definition.
+   *          A map containing additional properties associated with the DIT
+   *          content rule definition.
    * @param overwrite
-   *          {@code true} if any existing DIT content rule with the
-   *          same OID should be overwritten.
+   *          {@code true} if any existing DIT content rule with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    */
-  public SchemaBuilder addDITContentRule(String structuralClass,
-      List<String> names, String description, boolean obsolete,
-      Set<String> auxiliaryClasses, Set<String> optionalAttributes,
-      Set<String> prohibitedAttributes, Set<String> requiredAttributes,
-      Map<String, List<String>> extraProperties, boolean overwrite)
+  public SchemaBuilder addDITContentRule(final String structuralClass,
+      final List<String> names, final String description,
+      final boolean obsolete, final Set<String> auxiliaryClasses,
+      final Set<String> optionalAttributes,
+      final Set<String> prohibitedAttributes,
+      final Set<String> requiredAttributes,
+      final Map<String, List<String>> extraProperties, final boolean overwrite)
       throws ConflictingSchemaElementException
   {
     final DITContentRule rule = new DITContentRule(structuralClass,
-        names, description, obsolete, auxiliaryClasses,
-        optionalAttributes, prohibitedAttributes, requiredAttributes,
-        extraProperties, null);
+        unmodifiableCopyOfList(names), description, obsolete,
+        unmodifiableCopyOfSet(auxiliaryClasses),
+        unmodifiableCopyOfSet(optionalAttributes),
+        unmodifiableCopyOfSet(prohibitedAttributes),
+        unmodifiableCopyOfSet(requiredAttributes),
+        unmodifiableCopyOfExtraProperties(extraProperties), null);
     addDITContentRule(rule, overwrite);
     return this;
   }
@@ -696,43 +707,43 @@
 
 
   /**
-   * Adds the provided DIT structure rule definition to this schema
-   * builder.
-   * 
+   * Adds the provided DIT structure rule definition to this schema builder.
+   *
    * @param ruleID
    *          The rule identifier of the DIT structure rule.
    * @param names
-   *          The user-friendly names of the DIT structure rule
-   *          definition.
+   *          The user-friendly names of the DIT structure rule definition.
    * @param description
    *          The description of the DIT structure rule definition.
    * @param obsolete
-   *          {@code true} if the DIT structure rule definition is
-   *          obsolete, otherwise {@code false}.
+   *          {@code true} if the DIT structure rule definition is obsolete,
+   *          otherwise {@code false}.
    * @param nameForm
    *          The name form associated with the DIT structure rule.
    * @param superiorRules
    *          A list of superior rules (by rule id).
    * @param extraProperties
-   *          A map containing additional properties associated with the
-   *          DIT structure rule definition.
+   *          A map containing additional properties associated with the DIT
+   *          structure rule definition.
    * @param overwrite
-   *          {@code true} if any existing DIT structure rule with the
-   *          same OID should be overwritten.
+   *          {@code true} if any existing DIT structure rule with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    */
-  public SchemaBuilder addDITStructureRule(Integer ruleID,
-      List<String> names, String description, boolean obsolete,
-      String nameForm, Set<Integer> superiorRules,
-      Map<String, List<String>> extraProperties, boolean overwrite)
+  public SchemaBuilder addDITStructureRule(final Integer ruleID,
+      final List<String> names, final String description,
+      final boolean obsolete, final String nameForm,
+      final Set<Integer> superiorRules,
+      final Map<String, List<String>> extraProperties, final boolean overwrite)
       throws ConflictingSchemaElementException
   {
-    final DITStructureRule rule = new DITStructureRule(ruleID, names,
-        description, obsolete, nameForm, superiorRules,
-        extraProperties, null);
+    final DITStructureRule rule = new DITStructureRule(ruleID,
+        unmodifiableCopyOfList(names), description, obsolete, nameForm,
+        unmodifiableCopyOfSet(superiorRules),
+        unmodifiableCopyOfExtraProperties(extraProperties), null);
     addDITStructureRule(rule, overwrite);
     return this;
   }
@@ -740,27 +751,26 @@
 
 
   /**
-   * Adds the provided DIT structure rule definition to this schema
-   * builder.
-   * 
+   * Adds the provided DIT structure rule definition to this schema builder.
+   *
    * @param definition
    *          The DIT structure rule definition.
    * @param overwrite
-   *          {@code true} if any existing DIT structure rule with the
-   *          same OID should be overwritten.
+   *          {@code true} if any existing DIT structure rule with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
-   * @throws LocalizedIllegalArgumentException
-   *           If the provided DIT structure rule definition could not
-   *           be parsed.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
+   * @throws LocalizedIllegalArgumentException
+   *           If the provided DIT structure rule definition could not be
+   *           parsed.
    * @throws NullPointerException
    *           If {@code definition} was {@code null}.
    */
-  public SchemaBuilder addDITStructureRule(String definition,
-      boolean overwrite) throws LocalizedIllegalArgumentException,
-      ConflictingSchemaElementException
+  public SchemaBuilder addDITStructureRule(final String definition,
+      final boolean overwrite) throws ConflictingSchemaElementException,
+      LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(definition);
     try
@@ -802,8 +812,7 @@
       boolean isObsolete = false;
       String nameForm = null;
       Set<Integer> superiorRules = Collections.emptySet();
-      Map<String, List<String>> extraProperties = Collections
-          .emptyMap();
+      Map<String, List<String>> extraProperties = Collections.emptyMap();
 
       // At this point, we should have a pretty specific syntax that
       // describes what may come next, but some of the components are
@@ -859,8 +868,7 @@
           {
             extraProperties = new HashMap<String, List<String>>();
           }
-          extraProperties.put(tokenName, SchemaUtils
-              .readExtensions(reader));
+          extraProperties.put(tokenName, SchemaUtils.readExtensions(reader));
         }
         else
         {
@@ -877,15 +885,20 @@
         throw new LocalizedIllegalArgumentException(message);
       }
 
+      if (!extraProperties.isEmpty())
+      {
+        extraProperties = Collections.unmodifiableMap(extraProperties);
+      }
+
       final DITStructureRule rule = new DITStructureRule(ruleID, names,
-          description, isObsolete, nameForm, superiorRules,
-          extraProperties, definition);
+          description, isObsolete, nameForm, superiorRules, extraProperties,
+          definition);
       addDITStructureRule(rule, overwrite);
     }
     catch (final DecodeException e)
     {
-      throw new LocalizedIllegalArgumentException(e.getMessageObject(),
-          e.getCause());
+      throw new LocalizedIllegalArgumentException(e.getMessageObject(), e
+          .getCause());
     }
     return this;
   }
@@ -893,40 +906,38 @@
 
 
   /**
-   * Adds the provided enumeration syntax definition to this schema
-   * builder.
-   * 
+   * Adds the provided enumeration syntax definition to this schema builder.
+   *
    * @param oid
    *          The OID of the enumeration syntax definition.
    * @param description
    *          The description of the enumeration syntax definition.
    * @param overwrite
-   *          {@code true} if any existing syntax with the same OID
-   *          should be overwritten.
+   *          {@code true} if any existing syntax with the same OID should be
+   *          overwritten.
    * @param enumerations
-   *          The range of values which attribute values must match in
-   *          order to be valid.
+   *          The range of values which attribute values must match in order to
+   *          be valid.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    */
-  public SchemaBuilder addEnumerationSyntax(String oid,
-      String description, boolean overwrite, String... enumerations)
-      throws ConflictingSchemaElementException
+  public SchemaBuilder addEnumerationSyntax(final String oid,
+      final String description, final boolean overwrite,
+      final String... enumerations) throws ConflictingSchemaElementException
   {
     Validator.ensureNotNull((Object) enumerations);
 
     final EnumSyntaxImpl enumImpl = new EnumSyntaxImpl(oid, Arrays
         .asList(enumerations));
     final Syntax enumSyntax = new Syntax(oid, description, Collections
-        .singletonMap("X-ENUM", Arrays.asList(enumerations)), null,
-        enumImpl);
+        .singletonMap("X-ENUM", Arrays.asList(enumerations)), null, enumImpl);
     final MatchingRule enumOMR = new MatchingRule(enumImpl
         .getOrderingMatchingRule(), Collections
         .singletonList(OMR_GENERIC_ENUM_NAME + oid), "", false, oid,
-        CoreSchemaImpl.OPENDS_ORIGIN, null,
-        new EnumOrderingMatchingRule(enumImpl));
+        CoreSchemaImpl.OPENDS_ORIGIN, null, new EnumOrderingMatchingRule(
+            enumImpl));
 
     addSyntax(enumSyntax, overwrite);
     try
@@ -944,25 +955,24 @@
 
   /**
    * Adds the provided matching rule definition to this schema builder.
-   * 
+   *
    * @param definition
    *          The matching rule definition.
    * @param overwrite
-   *          {@code true} if any existing matching rule with the same
-   *          OID should be overwritten.
+   *          {@code true} if any existing matching rule with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
-   * @throws LocalizedIllegalArgumentException
-   *           If the provided matching rule definition could not be
-   *           parsed.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
+   * @throws LocalizedIllegalArgumentException
+   *           If the provided matching rule definition could not be parsed.
    * @throws NullPointerException
    *           If {@code definition} was {@code null}.
    */
-  public SchemaBuilder addMatchingRule(String definition,
-      boolean overwrite) throws LocalizedIllegalArgumentException,
-      ConflictingSchemaElementException
+  public SchemaBuilder addMatchingRule(final String definition,
+      final boolean overwrite) throws ConflictingSchemaElementException,
+      LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(definition);
     try
@@ -977,8 +987,7 @@
       {
         // This means that the value was empty or contained only
         // whitespace. That is illegal.
-        final LocalizableMessage message = ERR_ATTR_SYNTAX_MR_EMPTY_VALUE
-            .get();
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_MR_EMPTY_VALUE.get();
         throw new LocalizedIllegalArgumentException(message);
       }
 
@@ -1003,8 +1012,7 @@
       String description = "".intern();
       boolean isObsolete = false;
       String syntax = null;
-      Map<String, List<String>> extraProperties = Collections
-          .emptyMap();
+      Map<String, List<String>> extraProperties = Collections.emptyMap();
 
       // At this point, we should have a pretty specific syntax that
       // describes what may come next, but some of the components are
@@ -1056,8 +1064,7 @@
           {
             extraProperties = new HashMap<String, List<String>>();
           }
-          extraProperties.put(tokenName, SchemaUtils
-              .readExtensions(reader));
+          extraProperties.put(tokenName, SchemaUtils.readExtensions(reader));
         }
         else
         {
@@ -1075,14 +1082,18 @@
         throw new LocalizedIllegalArgumentException(message);
       }
 
-      addMatchingRule(new MatchingRule(oid, names, description,
-          isObsolete, syntax, extraProperties, definition, null),
-          overwrite);
+      if (!extraProperties.isEmpty())
+      {
+        extraProperties = Collections.unmodifiableMap(extraProperties);
+      }
+
+      addMatchingRule(new MatchingRule(oid, names, description, isObsolete,
+          syntax, extraProperties, definition, null), overwrite);
     }
     catch (final DecodeException e)
     {
-      throw new LocalizedIllegalArgumentException(e.getMessageObject(),
-          e.getCause());
+      throw new LocalizedIllegalArgumentException(e.getMessageObject(), e
+          .getCause());
     }
     return this;
   }
@@ -1091,7 +1102,7 @@
 
   /**
    * Adds the provided matching rule definition to this schema builder.
-   * 
+   *
    * @param oid
    *          The OID of the matching rule definition.
    * @param names
@@ -1109,22 +1120,24 @@
    * @param implementation
    *          The implementation of the matching rule.
    * @param overwrite
-   *          {@code true} if any existing matching rule with the same
-   *          OID should be overwritten.
+   *          {@code true} if any existing matching rule with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    */
-  public SchemaBuilder addMatchingRule(String oid, List<String> names,
-      String description, boolean obsolete, String assertionSyntax,
-      Map<String, List<String>> extraProperties,
-      MatchingRuleImpl implementation, boolean overwrite)
+  public SchemaBuilder addMatchingRule(final String oid,
+      final List<String> names, final String description,
+      final boolean obsolete, final String assertionSyntax,
+      final Map<String, List<String>> extraProperties,
+      final MatchingRuleImpl implementation, final boolean overwrite)
       throws ConflictingSchemaElementException
   {
     Validator.ensureNotNull(implementation);
-    final MatchingRule matchingRule = new MatchingRule(oid, names,
-        description, obsolete, assertionSyntax, extraProperties, null,
+    final MatchingRule matchingRule = new MatchingRule(oid,
+        unmodifiableCopyOfList(names), description, obsolete, assertionSyntax,
+        unmodifiableCopyOfExtraProperties(extraProperties), null,
         implementation);
     addMatchingRule(matchingRule, overwrite);
     return this;
@@ -1133,27 +1146,25 @@
 
 
   /**
-   * Adds the provided matching rule use definition to this schema
-   * builder.
-   * 
+   * Adds the provided matching rule use definition to this schema builder.
+   *
    * @param definition
    *          The matching rule use definition.
    * @param overwrite
-   *          {@code true} if any existing matching rule use with the
-   *          same OID should be overwritten.
+   *          {@code true} if any existing matching rule use with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
-   * @throws LocalizedIllegalArgumentException
-   *           If the provided matching rule use definition could not be
-   *           parsed.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
+   * @throws LocalizedIllegalArgumentException
+   *           If the provided matching rule use definition could not be parsed.
    * @throws NullPointerException
    *           If {@code definition} was {@code null}.
    */
-  public SchemaBuilder addMatchingRuleUse(String definition,
-      boolean overwrite) throws LocalizedIllegalArgumentException,
-      ConflictingSchemaElementException
+  public SchemaBuilder addMatchingRuleUse(final String definition,
+      final boolean overwrite) throws ConflictingSchemaElementException,
+      LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(definition);
     try
@@ -1194,8 +1205,7 @@
       String description = "".intern();
       boolean isObsolete = false;
       Set<String> attributes = null;
-      Map<String, List<String>> extraProperties = Collections
-          .emptyMap();
+      Map<String, List<String>> extraProperties = Collections.emptyMap();
 
       // At this point, we should have a pretty specific syntax that
       // describes what may come next, but some of the components are
@@ -1247,8 +1257,7 @@
           {
             extraProperties = new HashMap<String, List<String>>();
           }
-          extraProperties.put(tokenName, SchemaUtils
-              .readExtensions(reader));
+          extraProperties.put(tokenName, SchemaUtils.readExtensions(reader));
         }
         else
         {
@@ -1266,15 +1275,19 @@
         throw new LocalizedIllegalArgumentException(message);
       }
 
-      final MatchingRuleUse use = new MatchingRuleUse(oid, names,
-          description, isObsolete, attributes, extraProperties,
-          definition);
+      if (!extraProperties.isEmpty())
+      {
+        extraProperties = Collections.unmodifiableMap(extraProperties);
+      }
+
+      final MatchingRuleUse use = new MatchingRuleUse(oid, names, description,
+          isObsolete, attributes, extraProperties, definition);
       addMatchingRuleUse(use, overwrite);
     }
     catch (final DecodeException e)
     {
-      throw new LocalizedIllegalArgumentException(e.getMessageObject(),
-          e.getCause());
+      throw new LocalizedIllegalArgumentException(e.getMessageObject(), e
+          .getCause());
     }
     return this;
   }
@@ -1282,40 +1295,40 @@
 
 
   /**
-   * Adds the provided matching rule use definition to this schema
-   * builder.
-   * 
+   * Adds the provided matching rule use definition to this schema builder.
+   *
    * @param oid
    *          The OID of the matching rule use definition.
    * @param names
-   *          The user-friendly names of the matching rule use
-   *          definition.
+   *          The user-friendly names of the matching rule use definition.
    * @param description
    *          The description of the matching rule use definition.
    * @param obsolete
-   *          {@code true} if the matching rule use definition is
-   *          obsolete, otherwise {@code false}.
+   *          {@code true} if the matching rule use definition is obsolete,
+   *          otherwise {@code false}.
    * @param attributeOIDs
    *          The list of attribute types the matching rule applies to.
    * @param extraProperties
    *          A map containing additional properties associated with the
    *          matching rule use definition.
    * @param overwrite
-   *          {@code true} if any existing matching rule use with the
-   *          same OID should be overwritten.
+   *          {@code true} if any existing matching rule use with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    */
-  public SchemaBuilder addMatchingRuleUse(String oid,
-      List<String> names, String description, boolean obsolete,
-      Set<String> attributeOIDs,
-      Map<String, List<String>> extraProperties, boolean overwrite)
+  public SchemaBuilder addMatchingRuleUse(final String oid,
+      final List<String> names, final String description,
+      final boolean obsolete, final Set<String> attributeOIDs,
+      final Map<String, List<String>> extraProperties, final boolean overwrite)
       throws ConflictingSchemaElementException
   {
-    final MatchingRuleUse use = new MatchingRuleUse(oid, names,
-        description, obsolete, attributeOIDs, extraProperties, null);
+    final MatchingRuleUse use = new MatchingRuleUse(oid,
+        unmodifiableCopyOfList(names), description, obsolete,
+        unmodifiableCopyOfSet(attributeOIDs),
+        unmodifiableCopyOfExtraProperties(extraProperties), null);
     addMatchingRuleUse(use, overwrite);
     return this;
   }
@@ -1324,24 +1337,24 @@
 
   /**
    * Adds the provided name form definition to this schema builder.
-   * 
+   *
    * @param definition
    *          The name form definition.
    * @param overwrite
-   *          {@code true} if any existing name form with the same OID
-   *          should be overwritten.
+   *          {@code true} if any existing name form with the same OID should be
+   *          overwritten.
    * @return A reference to this schema builder.
+   * @throws ConflictingSchemaElementException
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    * @throws LocalizedIllegalArgumentException
    *           If the provided name form definition could not be parsed.
-   * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
    * @throws NullPointerException
    *           If {@code definition} was {@code null}.
    */
-  public SchemaBuilder addNameForm(String definition, boolean overwrite)
-      throws LocalizedIllegalArgumentException,
-      ConflictingSchemaElementException
+  public SchemaBuilder addNameForm(final String definition,
+      final boolean overwrite) throws ConflictingSchemaElementException,
+      LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(definition);
     try
@@ -1384,8 +1397,7 @@
       String structuralClass = null;
       Set<String> optionalAttributes = Collections.emptySet();
       Set<String> requiredAttributes = null;
-      Map<String, List<String>> extraProperties = Collections
-          .emptyMap();
+      Map<String, List<String>> extraProperties = Collections.emptyMap();
 
       // At this point, we should have a pretty specific syntax that
       // describes what may come next, but some of the components are
@@ -1445,8 +1457,7 @@
           {
             extraProperties = new HashMap<String, List<String>>();
           }
-          extraProperties.put(tokenName, SchemaUtils
-              .readExtensions(reader));
+          extraProperties.put(tokenName, SchemaUtils.readExtensions(reader));
         }
         else
         {
@@ -1472,15 +1483,20 @@
         throw new LocalizedIllegalArgumentException(message);
       }
 
+      if (!extraProperties.isEmpty())
+      {
+        extraProperties = Collections.unmodifiableMap(extraProperties);
+      }
+
       final NameForm nameForm = new NameForm(oid, names, description,
-          isObsolete, structuralClass, requiredAttributes,
-          optionalAttributes, extraProperties, definition);
+          isObsolete, structuralClass, requiredAttributes, optionalAttributes,
+          extraProperties, definition);
       addNameForm(nameForm, overwrite);
     }
     catch (final DecodeException e)
     {
-      throw new LocalizedIllegalArgumentException(e.getMessageObject(),
-          e.getCause());
+      throw new LocalizedIllegalArgumentException(e.getMessageObject(), e
+          .getCause());
     }
     return this;
   }
@@ -1489,7 +1505,7 @@
 
   /**
    * Adds the provided name form definition to this schema builder.
-   * 
+   *
    * @param oid
    *          The OID of the name form definition.
    * @param names
@@ -1497,36 +1513,39 @@
    * @param description
    *          The description of the name form definition.
    * @param obsolete
-   *          {@code true} if the name form definition is obsolete,
-   *          otherwise {@code false}.
+   *          {@code true} if the name form definition is obsolete, otherwise
+   *          {@code false}.
    * @param structuralClass
    *          The structural object class this rule applies to.
    * @param requiredAttributes
-   *          A list of naming attribute types that entries subject to
-   *          the name form must contain.
+   *          A list of naming attribute types that entries subject to the name
+   *          form must contain.
    * @param optionalAttributes
-   *          A list of naming attribute types that entries subject to
-   *          the name form may contain.
+   *          A list of naming attribute types that entries subject to the name
+   *          form may contain.
    * @param extraProperties
-   *          A map containing additional properties associated with the
-   *          name form definition.
+   *          A map containing additional properties associated with the name
+   *          form definition.
    * @param overwrite
-   *          {@code true} if any existing name form use with the same
-   *          OID should be overwritten.
+   *          {@code true} if any existing name form use with the same OID
+   *          should be overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    */
-  public SchemaBuilder addNameForm(String oid, List<String> names,
-      String description, boolean obsolete, String structuralClass,
-      Set<String> requiredAttributes, Set<String> optionalAttributes,
-      Map<String, List<String>> extraProperties, boolean overwrite)
+  public SchemaBuilder addNameForm(final String oid, final List<String> names,
+      final String description, final boolean obsolete,
+      final String structuralClass, final Set<String> requiredAttributes,
+      final Set<String> optionalAttributes,
+      final Map<String, List<String>> extraProperties, final boolean overwrite)
       throws ConflictingSchemaElementException
   {
-    final NameForm nameForm = new NameForm(oid, names, description,
-        obsolete, structuralClass, requiredAttributes,
-        optionalAttributes, extraProperties, null);
+    final NameForm nameForm = new NameForm(oid, unmodifiableCopyOfList(names),
+        description, obsolete, structuralClass,
+        unmodifiableCopyOfSet(requiredAttributes),
+        unmodifiableCopyOfSet(optionalAttributes),
+        unmodifiableCopyOfExtraProperties(extraProperties), null);
     addNameForm(nameForm, overwrite);
     return this;
   }
@@ -1535,25 +1554,24 @@
 
   /**
    * Adds the provided object class definition to this schema builder.
-   * 
+   *
    * @param definition
    *          The object class definition.
    * @param overwrite
-   *          {@code true} if any existing object class with the same
-   *          OID should be overwritten.
+   *          {@code true} if any existing object class with the same OID should
+   *          be overwritten.
    * @return A reference to this schema builder.
-   * @throws LocalizedIllegalArgumentException
-   *           If the provided object class definition could not be
-   *           parsed.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
+   * @throws LocalizedIllegalArgumentException
+   *           If the provided object class definition could not be parsed.
    * @throws NullPointerException
    *           If {@code definition} was {@code null}.
    */
-  public SchemaBuilder addObjectClass(String definition,
-      boolean overwrite) throws LocalizedIllegalArgumentException,
-      ConflictingSchemaElementException
+  public SchemaBuilder addObjectClass(final String definition,
+      final boolean overwrite) throws ConflictingSchemaElementException,
+      LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(definition);
     try
@@ -1597,8 +1615,7 @@
       Set<String> requiredAttributes = Collections.emptySet();
       Set<String> optionalAttributes = Collections.emptySet();
       ObjectClassType objectClassType = ObjectClassType.STRUCTURAL;
-      Map<String, List<String>> extraProperties = Collections
-          .emptyMap();
+      Map<String, List<String>> extraProperties = Collections.emptyMap();
 
       // At this point, we should have a pretty specific syntax that
       // describes what may come next, but some of the components are
@@ -1678,8 +1695,7 @@
           {
             extraProperties = new HashMap<String, List<String>>();
           }
-          extraProperties.put(tokenName, SchemaUtils
-              .readExtensions(reader));
+          extraProperties.put(tokenName, SchemaUtils.readExtensions(reader));
         }
         else
         {
@@ -1691,8 +1707,7 @@
 
       if (oid.equals(EXTENSIBLE_OBJECT_OBJECTCLASS_OID))
       {
-        addObjectClass(new ObjectClass(description, extraProperties),
-            overwrite);
+        addObjectClass(new ObjectClass(description, extraProperties), overwrite);
       }
       else
       {
@@ -1702,16 +1717,20 @@
           superiorClasses = Collections.singleton(TOP_OBJECTCLASS_NAME);
         }
 
-        addObjectClass(new ObjectClass(oid, names, description,
-            isObsolete, superiorClasses, requiredAttributes,
-            optionalAttributes, objectClassType, extraProperties,
-            definition), overwrite);
+        if (!extraProperties.isEmpty())
+        {
+          extraProperties = Collections.unmodifiableMap(extraProperties);
+        }
+
+        addObjectClass(new ObjectClass(oid, names, description, isObsolete,
+            superiorClasses, requiredAttributes, optionalAttributes,
+            objectClassType, extraProperties, definition), overwrite);
       }
     }
     catch (final DecodeException e)
     {
-      throw new LocalizedIllegalArgumentException(e.getMessageObject(),
-          e.getCause());
+      throw new LocalizedIllegalArgumentException(e.getMessageObject(), e
+          .getCause());
     }
     return this;
   }
@@ -1720,7 +1739,7 @@
 
   /**
    * Adds the provided object class definition to this schema builder.
-   * 
+   *
    * @param oid
    *          The OID of the object class definition.
    * @param names
@@ -1728,8 +1747,8 @@
    * @param description
    *          The description of the object class definition.
    * @param obsolete
-   *          {@code true} if the object class definition is obsolete,
-   *          otherwise {@code false}.
+   *          {@code true} if the object class definition is obsolete, otherwise
+   *          {@code false}.
    * @param superiorClassOIDs
    *          A list of direct superclasses of the object class.
    * @param requiredAttributeOIDs
@@ -1739,28 +1758,29 @@
    * @param objectClassType
    *          The type of the object class.
    * @param extraProperties
-   *          A map containing additional properties associated with the
-   *          object class definition.
+   *          A map containing additional properties associated with the object
+   *          class definition.
    * @param overwrite
-   *          {@code true} if any existing object class with the same
-   *          OID should be overwritten.
+   *          {@code true} if any existing object class with the same OID should
+   *          be overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    */
-  public SchemaBuilder addObjectClass(String oid, List<String> names,
-      String description, boolean obsolete,
-      Set<String> superiorClassOIDs, Set<String> requiredAttributeOIDs,
-      Set<String> optionalAttributeOIDs,
-      ObjectClassType objectClassType,
-      Map<String, List<String>> extraProperties, boolean overwrite)
+  public SchemaBuilder addObjectClass(final String oid,
+      final List<String> names, final String description,
+      final boolean obsolete, Set<String> superiorClassOIDs,
+      final Set<String> requiredAttributeOIDs,
+      final Set<String> optionalAttributeOIDs,
+      final ObjectClassType objectClassType,
+      final Map<String, List<String>> extraProperties, final boolean overwrite)
       throws ConflictingSchemaElementException
   {
     if (oid.equals(EXTENSIBLE_OBJECT_OBJECTCLASS_OID))
     {
-      addObjectClass(new ObjectClass(description, extraProperties),
-          overwrite);
+      addObjectClass(new ObjectClass(description,
+          unmodifiableCopyOfExtraProperties(extraProperties)), overwrite);
     }
     else
     {
@@ -1770,11 +1790,11 @@
         superiorClassOIDs = Collections.singleton(TOP_OBJECTCLASS_NAME);
       }
 
-      addObjectClass(
-          new ObjectClass(oid, names, description, obsolete,
-              superiorClassOIDs, requiredAttributeOIDs,
-              optionalAttributeOIDs, objectClassType, extraProperties,
-              null), overwrite);
+      addObjectClass(new ObjectClass(oid, unmodifiableCopyOfList(names),
+          description, obsolete, unmodifiableCopyOfSet(superiorClassOIDs),
+          unmodifiableCopyOfSet(requiredAttributeOIDs),
+          unmodifiableCopyOfSet(optionalAttributeOIDs), objectClassType,
+          unmodifiableCopyOfExtraProperties(extraProperties), null), overwrite);
     }
     return this;
   }
@@ -1783,53 +1803,54 @@
 
   /**
    * Adds the provided pattern syntax definition to this schema builder.
-   * 
+   *
    * @param oid
    *          The OID of the pattern syntax definition.
    * @param description
    *          The description of the pattern syntax definition.
    * @param pattern
-   *          The regular expression pattern which attribute values must
-   *          match in order to be valid.
+   *          The regular expression pattern which attribute values must match
+   *          in order to be valid.
    * @param overwrite
-   *          {@code true} if any existing syntax with the same OID
-   *          should be overwritten.
+   *          {@code true} if any existing syntax with the same OID should be
+   *          overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    */
-  public SchemaBuilder addPatternSyntax(String oid, String description,
-      Pattern pattern, boolean overwrite)
+  public SchemaBuilder addPatternSyntax(final String oid,
+      final String description, final Pattern pattern, final boolean overwrite)
       throws ConflictingSchemaElementException
   {
     Validator.ensureNotNull(pattern);
 
-    addSyntax(new Syntax(oid, description, Collections.singletonMap(
-        "X-PATTERN", Collections.singletonList(pattern.toString())),
-        null, null), overwrite);
+    addSyntax(
+        new Syntax(oid, description, Collections.singletonMap("X-PATTERN",
+            Collections.singletonList(pattern.toString())), null, null),
+        overwrite);
     return this;
   }
 
 
 
   /**
-   * Adds all of the schema elements in the provided schema to this
-   * schema builder.
-   * 
+   * Adds all of the schema elements in the provided schema to this schema
+   * builder.
+   *
    * @param schema
    *          The schema to be copied into this schema builder.
    * @param overwrite
-   *          {@code true} if existing schema elements with the same
-   *          conflicting OIDs should be overwritten.
+   *          {@code true} if existing schema elements with the same conflicting
+   *          OIDs should be overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and conflicting
-   *           schema elements were found.
+   *           If {@code overwrite} was {@code false} and conflicting schema
+   *           elements were found.
    * @throws NullPointerException
    *           If {@code schema} was {@code null}.
    */
-  public SchemaBuilder addSchema(Schema schema, boolean overwrite)
+  public SchemaBuilder addSchema(final Schema schema, final boolean overwrite)
       throws ConflictingSchemaElementException, NullPointerException
   {
     Validator.ensureNotNull(schema);
@@ -1843,8 +1864,7 @@
       addMatchingRule(matchingRule.duplicate(), overwrite);
     }
 
-    for (final MatchingRuleUse matchingRuleUse : schema
-        .getMatchingRuleUses())
+    for (final MatchingRuleUse matchingRuleUse : schema.getMatchingRuleUses())
     {
       addMatchingRuleUse(matchingRuleUse.duplicate(), overwrite);
     }
@@ -1869,8 +1889,7 @@
       addDITContentRule(contentRule.duplicate(), overwrite);
     }
 
-    for (final DITStructureRule structureRule : schema
-        .getDITStuctureRules())
+    for (final DITStructureRule structureRule : schema.getDITStuctureRules())
     {
       addDITStructureRule(structureRule.duplicate(), overwrite);
     }
@@ -1881,33 +1900,30 @@
 
 
   /**
-   * Adds the provided substitution syntax definition to this schema
-   * builder.
-   * 
+   * Adds the provided substitution syntax definition to this schema builder.
+   *
    * @param oid
    *          The OID of the substitution syntax definition.
    * @param description
    *          The description of the substitution syntax definition.
    * @param substituteSyntax
-   *          The OID of the syntax whose implementation should be
-   *          substituted.
+   *          The OID of the syntax whose implementation should be substituted.
    * @param overwrite
-   *          {@code true} if any existing syntax with the same OID
-   *          should be overwritten.
+   *          {@code true} if any existing syntax with the same OID should be
+   *          overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    */
-  public SchemaBuilder addSubstitutionSyntax(String oid,
-      String description, String substituteSyntax, boolean overwrite)
-      throws ConflictingSchemaElementException
+  public SchemaBuilder addSubstitutionSyntax(final String oid,
+      final String description, final String substituteSyntax,
+      final boolean overwrite) throws ConflictingSchemaElementException
   {
     Validator.ensureNotNull(substituteSyntax);
 
-    addSyntax(new Syntax(oid, description, Collections.singletonMap(
-        "X-SUBST", Collections.singletonList(substituteSyntax)), null,
-        null), overwrite);
+    addSyntax(new Syntax(oid, description, Collections.singletonMap("X-SUBST",
+        Collections.singletonList(substituteSyntax)), null, null), overwrite);
     return this;
   }
 
@@ -1915,24 +1931,24 @@
 
   /**
    * Adds the provided syntax definition to this schema builder.
-   * 
+   *
    * @param definition
    *          The syntax definition.
    * @param overwrite
-   *          {@code true} if any existing syntax with the same OID
-   *          should be overwritten.
+   *          {@code true} if any existing syntax with the same OID should be
+   *          overwritten.
    * @return A reference to this schema builder.
+   * @throws ConflictingSchemaElementException
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    * @throws LocalizedIllegalArgumentException
    *           If the provided syntax definition could not be parsed.
-   * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
    * @throws NullPointerException
    *           If {@code definition} was {@code null}.
    */
-  public SchemaBuilder addSyntax(String definition, boolean overwrite)
-      throws LocalizedIllegalArgumentException,
-      ConflictingSchemaElementException
+  public SchemaBuilder addSyntax(final String definition,
+      final boolean overwrite) throws ConflictingSchemaElementException,
+      LocalizedIllegalArgumentException, NullPointerException
   {
     Validator.ensureNotNull(definition);
     try
@@ -1970,8 +1986,7 @@
       final String oid = SchemaUtils.readOID(reader);
 
       String description = "".intern();
-      Map<String, List<String>> extraProperties = Collections
-          .emptyMap();
+      Map<String, List<String>> extraProperties = Collections.emptyMap();
 
       // At this point, we should have a pretty specific syntax that
       // describes what may come next, but some of the components are
@@ -2007,8 +2022,7 @@
           {
             extraProperties = new HashMap<String, List<String>>();
           }
-          extraProperties.put(tokenName, SchemaUtils
-              .readExtensions(reader));
+          extraProperties.put(tokenName, SchemaUtils.readExtensions(reader));
         }
         else
         {
@@ -2018,21 +2032,26 @@
         }
       }
 
+      if (!extraProperties.isEmpty())
+      {
+        extraProperties = Collections.unmodifiableMap(extraProperties);
+      }
+
       // See if it is a enum syntax
       for (final Map.Entry<String, List<String>> property : extraProperties
           .entrySet())
       {
         if (property.getKey().equalsIgnoreCase("x-enum"))
         {
-          final EnumSyntaxImpl enumImpl = new EnumSyntaxImpl(oid,
-              property.getValue());
+          final EnumSyntaxImpl enumImpl = new EnumSyntaxImpl(oid, property
+              .getValue());
           final Syntax enumSyntax = new Syntax(oid, description,
               extraProperties, definition, enumImpl);
           final MatchingRule enumOMR = new MatchingRule(enumImpl
               .getOrderingMatchingRule(), Collections
-              .singletonList(OMR_GENERIC_ENUM_NAME + oid), "", false,
-              oid, CoreSchemaImpl.OPENDS_ORIGIN, null,
-              new EnumOrderingMatchingRule(enumImpl));
+              .singletonList(OMR_GENERIC_ENUM_NAME + oid), "", false, oid,
+              CoreSchemaImpl.OPENDS_ORIGIN, null, new EnumOrderingMatchingRule(
+                  enumImpl));
 
           addSyntax(enumSyntax, overwrite);
           addMatchingRule(enumOMR, overwrite);
@@ -2040,13 +2059,14 @@
         }
       }
 
-      addSyntax(new Syntax(oid, description, extraProperties,
-          definition, null), overwrite);
+      addSyntax(
+          new Syntax(oid, description, extraProperties, definition, null),
+          overwrite);
     }
     catch (final DecodeException e)
     {
-      throw new LocalizedIllegalArgumentException(e.getMessageObject(),
-          e.getCause());
+      throw new LocalizedIllegalArgumentException(e.getMessageObject(), e
+          .getCause());
     }
     return this;
   }
@@ -2055,32 +2075,33 @@
 
   /**
    * Adds the provided syntax definition to this schema builder.
-   * 
+   *
    * @param oid
    *          The OID of the syntax definition.
    * @param description
    *          The description of the syntax definition.
    * @param extraProperties
-   *          A map containing additional properties associated with the
-   *          syntax definition.
+   *          A map containing additional properties associated with the syntax
+   *          definition.
    * @param implementation
    *          The implementation of the syntax.
    * @param overwrite
-   *          {@code true} if any existing syntax with the same OID
-   *          should be overwritten.
+   *          {@code true} if any existing syntax with the same OID should be
+   *          overwritten.
    * @return A reference to this schema builder.
    * @throws ConflictingSchemaElementException
-   *           If {@code overwrite} was {@code false} and a conflicting
-   *           schema element was found.
+   *           If {@code overwrite} was {@code false} and a conflicting schema
+   *           element was found.
    * @throws NullPointerException
    *           If {@code definition} was {@code null}.
    */
-  public SchemaBuilder addSyntax(String oid, String description,
-      Map<String, List<String>> extraProperties,
-      SyntaxImpl implementation, boolean overwrite)
-      throws ConflictingSchemaElementException
+  public SchemaBuilder addSyntax(final String oid, final String description,
+      final Map<String, List<String>> extraProperties,
+      final SyntaxImpl implementation, final boolean overwrite)
+      throws ConflictingSchemaElementException, NullPointerException
   {
-    addSyntax(new Syntax(oid, description, extraProperties, null,
+    addSyntax(new Syntax(oid, description,
+        unmodifiableCopyOfExtraProperties(extraProperties), null,
         implementation), overwrite);
     return this;
   }
@@ -2089,12 +2110,12 @@
 
   /**
    * Removes the named attribute type from this schema builder.
-   * 
+   *
    * @param name
    *          The name or OID of the attribute type to be removed.
    * @return {@code true} if the attribute type was found.
    */
-  public boolean removeAttributeType(String name)
+  public boolean removeAttributeType(final String name)
   {
     if (schema.hasAttributeType(name))
     {
@@ -2108,12 +2129,12 @@
 
   /**
    * Removes the named DIT content rule from this schema builder.
-   * 
+   *
    * @param name
    *          The name or OID of the DIT content rule to be removed.
    * @return {@code true} if the DIT content rule was found.
    */
-  public boolean removeDITContentRule(String name)
+  public boolean removeDITContentRule(final String name)
   {
     if (schema.hasDITContentRule(name))
     {
@@ -2127,12 +2148,12 @@
 
   /**
    * Removes the specified DIT structure rule from this schema builder.
-   * 
+   *
    * @param ruleID
    *          The ID of the DIT structure rule to be removed.
    * @return {@code true} if the DIT structure rule was found.
    */
-  public boolean removeDITStructureRule(Integer ruleID)
+  public boolean removeDITStructureRule(final Integer ruleID)
   {
     if (schema.hasDITStructureRule(ruleID))
     {
@@ -2146,12 +2167,12 @@
 
   /**
    * Removes the named matching rule from this schema builder.
-   * 
+   *
    * @param name
    *          The name or OID of the matching rule to be removed.
    * @return {@code true} if the matching rule was found.
    */
-  public boolean removeMatchingRule(String name)
+  public boolean removeMatchingRule(final String name)
   {
     if (schema.hasMatchingRule(name))
     {
@@ -2165,12 +2186,12 @@
 
   /**
    * Removes the named matching rule use from this schema builder.
-   * 
+   *
    * @param name
    *          The name or OID of the matching rule use to be removed.
    * @return {@code true} if the matching rule use was found.
    */
-  public boolean removeMatchingRuleUse(String name)
+  public boolean removeMatchingRuleUse(final String name)
   {
     if (schema.hasMatchingRuleUse(name))
     {
@@ -2184,12 +2205,12 @@
 
   /**
    * Removes the named name form from this schema builder.
-   * 
+   *
    * @param name
    *          The name or OID of the name form to be removed.
    * @return {@code true} if the name form was found.
    */
-  public boolean removeNameForm(String name)
+  public boolean removeNameForm(final String name)
   {
     if (schema.hasNameForm(name))
     {
@@ -2203,12 +2224,12 @@
 
   /**
    * Removes the named object class from this schema builder.
-   * 
+   *
    * @param name
    *          The name or OID of the object class to be removed.
    * @return {@code true} if the object class was found.
    */
-  public boolean removeObjectClass(String name)
+  public boolean removeObjectClass(final String name)
   {
     if (schema.hasObjectClass(name))
     {
@@ -2222,12 +2243,12 @@
 
   /**
    * Removes the named syntax from this schema builder.
-   * 
+   *
    * @param numericOID
    *          The name of the syntax to be removed.
    * @return {@code true} if the syntax was found.
    */
-  public boolean removeSyntax(String numericOID)
+  public boolean removeSyntax(final String numericOID)
   {
     if (schema.hasSyntax(numericOID))
     {
@@ -2240,20 +2261,19 @@
 
 
   /**
-   * Sets the schema compatibility options for this schema builder. The
-   * schema builder maintains its own set of compatibility options, so
-   * subsequent changes to the provided set of options will not impact
-   * this schema builder.
-   * 
+   * Sets the schema compatibility options for this schema builder. The schema
+   * builder maintains its own set of compatibility options, so subsequent
+   * changes to the provided set of options will not impact this schema builder.
+   *
    * @param options
-   *          The set of schema compatibility options that this schema
-   *          builder should use.
+   *          The set of schema compatibility options that this schema builder
+   *          should use.
    * @return A reference to this schema builder.
    * @throws NullPointerException
    *           If {@code options} was {@code null}.
    */
-  public SchemaBuilder setSchemaCompatOptions(
-      SchemaCompatOptions options) throws NullPointerException
+  public SchemaBuilder setSchemaCompatOptions(final SchemaCompatOptions options)
+      throws NullPointerException
   {
     Validator.ensureNotNull(options);
     this.options.assign(options);
@@ -2263,16 +2283,16 @@
 
 
   /**
-   * Returns a {@code Schema} containing all of the schema elements
-   * contained in this schema builder as well as the same set of schema
-   * compatibility options.
+   * Returns a {@code Schema} containing all of the schema elements contained in
+   * this schema builder as well as the same set of schema compatibility
+   * options.
    * <p>
-   * When this method returns this schema builder is empty and contains
-   * a default set of compatibility options.
-   * 
-   * @return A {@code Schema} containing all of the schema elements
-   *         contained in this schema builder as well as the same set of
-   *         schema compatibility options
+   * When this method returns this schema builder is empty and contains a
+   * default set of compatibility options.
+   *
+   * @return A {@code Schema} containing all of the schema elements contained in
+   *         this schema builder as well as the same set of schema compatibility
+   *         options
    */
   public Schema toSchema()
   {
@@ -2284,14 +2304,20 @@
 
 
 
-  private synchronized void addAttributeType(AttributeType attribute,
-      boolean overwrite) throws ConflictingSchemaElementException
+  void addWarning(final LocalizableMessage warning)
+  {
+    warnings.add(warning);
+  }
+
+
+
+  private void addAttributeType(final AttributeType attribute,
+      final boolean overwrite) throws ConflictingSchemaElementException
   {
     AttributeType conflictingAttribute;
     if (numericOID2AttributeTypes.containsKey(attribute.getOID()))
     {
-      conflictingAttribute = numericOID2AttributeTypes.get(attribute
-          .getOID());
+      conflictingAttribute = numericOID2AttributeTypes.get(attribute.getOID());
       if (!overwrite)
       {
         final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_ATTRIBUTE_OID
@@ -2309,8 +2335,8 @@
       List<AttributeType> attrs;
       if ((attrs = name2AttributeTypes.get(lowerName)) == null)
       {
-        name2AttributeTypes.put(lowerName, Collections
-            .singletonList(attribute));
+        name2AttributeTypes
+            .put(lowerName, Collections.singletonList(attribute));
       }
       else if (attrs.size() == 1)
       {
@@ -2327,12 +2353,11 @@
 
 
 
-  private synchronized void addDITContentRule(DITContentRule rule,
-      boolean overwrite) throws ConflictingSchemaElementException
+  private void addDITContentRule(final DITContentRule rule,
+      final boolean overwrite) throws ConflictingSchemaElementException
   {
     DITContentRule conflictingRule;
-    if (numericOID2ContentRules.containsKey(rule
-        .getStructuralClassOID()))
+    if (numericOID2ContentRules.containsKey(rule.getStructuralClassOID()))
     {
       conflictingRule = numericOID2ContentRules.get(rule
           .getStructuralClassOID());
@@ -2353,8 +2378,7 @@
       List<DITContentRule> rules;
       if ((rules = name2ContentRules.get(lowerName)) == null)
       {
-        name2ContentRules.put(lowerName, Collections
-            .singletonList(rule));
+        name2ContentRules.put(lowerName, Collections.singletonList(rule));
       }
       else if (rules.size() == 1)
       {
@@ -2371,8 +2395,8 @@
 
 
 
-  private synchronized void addDITStructureRule(DITStructureRule rule,
-      boolean overwrite) throws ConflictingSchemaElementException
+  private void addDITStructureRule(final DITStructureRule rule,
+      final boolean overwrite) throws ConflictingSchemaElementException
   {
     DITStructureRule conflictingRule;
     if (id2StructureRules.containsKey(rule.getRuleID()))
@@ -2381,8 +2405,8 @@
       if (!overwrite)
       {
         final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_DIT_STRUCTURE_RULE_ID
-            .get(rule.getNameOrRuleID(), rule.getRuleID(),
-                conflictingRule.getNameOrRuleID());
+            .get(rule.getNameOrRuleID(), rule.getRuleID(), conflictingRule
+                .getNameOrRuleID());
         throw new ConflictingSchemaElementException(message);
       }
       removeDITStructureRule(conflictingRule);
@@ -2395,8 +2419,7 @@
       List<DITStructureRule> rules;
       if ((rules = name2StructureRules.get(lowerName)) == null)
       {
-        name2StructureRules.put(lowerName, Collections
-            .singletonList(rule));
+        name2StructureRules.put(lowerName, Collections.singletonList(rule));
       }
       else if (rules.size() == 1)
       {
@@ -2413,8 +2436,8 @@
 
 
 
-  private synchronized void addMatchingRule(MatchingRule rule,
-      boolean overwrite) throws ConflictingSchemaElementException
+  private void addMatchingRule(final MatchingRule rule, final boolean overwrite)
+      throws ConflictingSchemaElementException
   {
     MatchingRule conflictingRule;
     if (numericOID2MatchingRules.containsKey(rule.getOID()))
@@ -2422,9 +2445,8 @@
       conflictingRule = numericOID2MatchingRules.get(rule.getOID());
       if (!overwrite)
       {
-        final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_MR_OID
-            .get(rule.getNameOrOID(), rule.getOID(), conflictingRule
-                .getNameOrOID());
+        final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_MR_OID.get(
+            rule.getNameOrOID(), rule.getOID(), conflictingRule.getNameOrOID());
         throw new ConflictingSchemaElementException(message);
       }
       removeMatchingRule(conflictingRule);
@@ -2437,8 +2459,7 @@
       List<MatchingRule> rules;
       if ((rules = name2MatchingRules.get(lowerName)) == null)
       {
-        name2MatchingRules.put(lowerName, Collections
-            .singletonList(rule));
+        name2MatchingRules.put(lowerName, Collections.singletonList(rule));
       }
       else if (rules.size() == 1)
       {
@@ -2455,20 +2476,19 @@
 
 
 
-  private synchronized void addMatchingRuleUse(MatchingRuleUse use,
-      boolean overwrite) throws ConflictingSchemaElementException
+  private void addMatchingRuleUse(final MatchingRuleUse use,
+      final boolean overwrite) throws ConflictingSchemaElementException
   {
     MatchingRuleUse conflictingUse;
-    if (numericOID2MatchingRuleUses.containsKey(use
-        .getMatchingRuleOID()))
+    if (numericOID2MatchingRuleUses.containsKey(use.getMatchingRuleOID()))
     {
-      conflictingUse = numericOID2MatchingRuleUses.get(use
-          .getMatchingRuleOID());
+      conflictingUse = numericOID2MatchingRuleUses
+          .get(use.getMatchingRuleOID());
       if (!overwrite)
       {
         final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_MATCHING_RULE_USE
-            .get(use.getNameOrOID(), use.getMatchingRuleOID(),
-                conflictingUse.getNameOrOID());
+            .get(use.getNameOrOID(), use.getMatchingRuleOID(), conflictingUse
+                .getNameOrOID());
         throw new ConflictingSchemaElementException(message);
       }
       removeMatchingRuleUse(conflictingUse);
@@ -2481,8 +2501,7 @@
       List<MatchingRuleUse> uses;
       if ((uses = name2MatchingRuleUses.get(lowerName)) == null)
       {
-        name2MatchingRuleUses.put(lowerName, Collections
-            .singletonList(use));
+        name2MatchingRuleUses.put(lowerName, Collections.singletonList(use));
       }
       else if (uses.size() == 1)
       {
@@ -2499,7 +2518,7 @@
 
 
 
-  private synchronized void addNameForm(NameForm form, boolean overwrite)
+  private void addNameForm(final NameForm form, final boolean overwrite)
       throws ConflictingSchemaElementException
   {
     NameForm conflictingForm;
@@ -2540,8 +2559,8 @@
 
 
 
-  private synchronized void addObjectClass(ObjectClass oc,
-      boolean overwrite) throws ConflictingSchemaElementException
+  private void addObjectClass(final ObjectClass oc, final boolean overwrite)
+      throws ConflictingSchemaElementException
   {
     ObjectClass conflictingOC;
     if (numericOID2ObjectClasses.containsKey(oc.getOID()))
@@ -2550,8 +2569,7 @@
       if (!overwrite)
       {
         final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_OBJECTCLASS_OID
-            .get(oc.getNameOrOID(), oc.getOID(), conflictingOC
-                .getNameOrOID());
+            .get(oc.getNameOrOID(), oc.getOID(), conflictingOC.getNameOrOID());
         throw new ConflictingSchemaElementException(message);
       }
       removeObjectClass(conflictingOC);
@@ -2564,8 +2582,7 @@
       List<ObjectClass> classes;
       if ((classes = name2ObjectClasses.get(lowerName)) == null)
       {
-        name2ObjectClasses
-            .put(lowerName, Collections.singletonList(oc));
+        name2ObjectClasses.put(lowerName, Collections.singletonList(oc));
       }
       else if (classes.size() == 1)
       {
@@ -2582,7 +2599,7 @@
 
 
 
-  private synchronized void addSyntax(Syntax syntax, boolean overwrite)
+  private void addSyntax(final Syntax syntax, final boolean overwrite)
       throws ConflictingSchemaElementException
   {
     Syntax conflictingSyntax;
@@ -2592,8 +2609,7 @@
       if (!overwrite)
       {
         final LocalizableMessage message = ERR_SCHEMA_CONFLICTING_SYNTAX_OID
-            .get(syntax.toString(), syntax.getOID(), conflictingSyntax
-                .getOID());
+            .get(syntax.toString(), syntax.getOID(), conflictingSyntax.getOID());
         throw new ConflictingSchemaElementException(message);
       }
       removeSyntax(conflictingSyntax);
@@ -2605,22 +2621,22 @@
 
   private void initBuilder(String schemaName)
   {
-    numericOID2Syntaxes = new HashMap<String, Syntax>();
-    numericOID2MatchingRules = new HashMap<String, MatchingRule>();
-    numericOID2MatchingRuleUses = new HashMap<String, MatchingRuleUse>();
-    numericOID2AttributeTypes = new HashMap<String, AttributeType>();
-    numericOID2ObjectClasses = new HashMap<String, ObjectClass>();
-    numericOID2NameForms = new HashMap<String, NameForm>();
-    numericOID2ContentRules = new HashMap<String, DITContentRule>();
-    id2StructureRules = new HashMap<Integer, DITStructureRule>();
+    numericOID2Syntaxes = new LinkedHashMap<String, Syntax>();
+    numericOID2MatchingRules = new LinkedHashMap<String, MatchingRule>();
+    numericOID2MatchingRuleUses = new LinkedHashMap<String, MatchingRuleUse>();
+    numericOID2AttributeTypes = new LinkedHashMap<String, AttributeType>();
+    numericOID2ObjectClasses = new LinkedHashMap<String, ObjectClass>();
+    numericOID2NameForms = new LinkedHashMap<String, NameForm>();
+    numericOID2ContentRules = new LinkedHashMap<String, DITContentRule>();
+    id2StructureRules = new LinkedHashMap<Integer, DITStructureRule>();
 
-    name2MatchingRules = new HashMap<String, List<MatchingRule>>();
-    name2MatchingRuleUses = new HashMap<String, List<MatchingRuleUse>>();
-    name2AttributeTypes = new HashMap<String, List<AttributeType>>();
-    name2ObjectClasses = new HashMap<String, List<ObjectClass>>();
-    name2NameForms = new HashMap<String, List<NameForm>>();
-    name2ContentRules = new HashMap<String, List<DITContentRule>>();
-    name2StructureRules = new HashMap<String, List<DITStructureRule>>();
+    name2MatchingRules = new LinkedHashMap<String, List<MatchingRule>>();
+    name2MatchingRuleUses = new LinkedHashMap<String, List<MatchingRuleUse>>();
+    name2AttributeTypes = new LinkedHashMap<String, List<AttributeType>>();
+    name2ObjectClasses = new LinkedHashMap<String, List<ObjectClass>>();
+    name2NameForms = new LinkedHashMap<String, List<NameForm>>();
+    name2ContentRules = new LinkedHashMap<String, List<DITContentRule>>();
+    name2StructureRules = new LinkedHashMap<String, List<DITStructureRule>>();
 
     objectClass2NameForms = new HashMap<String, List<NameForm>>();
     nameForm2StructureRules = new HashMap<String, List<DITStructureRule>>();
@@ -2629,31 +2645,28 @@
 
     if (schemaName == null)
     {
-      schemaName = String.format("Schema#%d", nextSchemaID
-          .getAndIncrement());
+      schemaName = String.format("Schema#%d", nextSchemaID.getAndIncrement());
     }
 
     schema = new Schema(schemaName, numericOID2Syntaxes,
         numericOID2MatchingRules, numericOID2MatchingRuleUses,
         numericOID2AttributeTypes, numericOID2ObjectClasses,
-        numericOID2NameForms, numericOID2ContentRules,
-        id2StructureRules, name2MatchingRules, name2MatchingRuleUses,
-        name2AttributeTypes, name2ObjectClasses, name2NameForms,
-        name2ContentRules, name2StructureRules, objectClass2NameForms,
-        nameForm2StructureRules, options, warnings);
+        numericOID2NameForms, numericOID2ContentRules, id2StructureRules,
+        name2MatchingRules, name2MatchingRuleUses, name2AttributeTypes,
+        name2ObjectClasses, name2NameForms, name2ContentRules,
+        name2StructureRules, objectClass2NameForms, nameForm2StructureRules,
+        options, warnings);
   }
 
 
 
-  private synchronized void removeAttributeType(
-      AttributeType attributeType)
+  private void removeAttributeType(final AttributeType attributeType)
   {
     numericOID2AttributeTypes.remove(attributeType.getOID());
     for (final String name : attributeType.getNames())
     {
       final String lowerName = StaticUtils.toLowerCase(name);
-      final List<AttributeType> attributes = name2AttributeTypes
-          .get(lowerName);
+      final List<AttributeType> attributes = name2AttributeTypes.get(lowerName);
       if (attributes != null && attributes.contains(attributeType))
       {
         if (attributes.size() <= 1)
@@ -2670,14 +2683,13 @@
 
 
 
-  private synchronized void removeDITContentRule(DITContentRule rule)
+  private void removeDITContentRule(final DITContentRule rule)
   {
     numericOID2ContentRules.remove(rule.getStructuralClassOID());
     for (final String name : rule.getNames())
     {
       final String lowerName = StaticUtils.toLowerCase(name);
-      final List<DITContentRule> rules = name2ContentRules
-          .get(lowerName);
+      final List<DITContentRule> rules = name2ContentRules.get(lowerName);
       if (rules != null && rules.contains(rule))
       {
         if (rules.size() <= 1)
@@ -2694,14 +2706,13 @@
 
 
 
-  private synchronized void removeDITStructureRule(DITStructureRule rule)
+  private void removeDITStructureRule(final DITStructureRule rule)
   {
     id2StructureRules.remove(rule.getRuleID());
     for (final String name : rule.getNames())
     {
       final String lowerName = StaticUtils.toLowerCase(name);
-      final List<DITStructureRule> rules = name2StructureRules
-          .get(lowerName);
+      final List<DITStructureRule> rules = name2StructureRules.get(lowerName);
       if (rules != null && rules.contains(rule))
       {
         if (rules.size() <= 1)
@@ -2718,14 +2729,13 @@
 
 
 
-  private synchronized void removeMatchingRule(MatchingRule rule)
+  private void removeMatchingRule(final MatchingRule rule)
   {
     numericOID2MatchingRules.remove(rule.getOID());
     for (final String name : rule.getNames())
     {
       final String lowerName = StaticUtils.toLowerCase(name);
-      final List<MatchingRule> rules = name2MatchingRules
-          .get(lowerName);
+      final List<MatchingRule> rules = name2MatchingRules.get(lowerName);
       if (rules != null && rules.contains(rule))
       {
         if (rules.size() <= 1)
@@ -2742,14 +2752,13 @@
 
 
 
-  private synchronized void removeMatchingRuleUse(MatchingRuleUse use)
+  private void removeMatchingRuleUse(final MatchingRuleUse use)
   {
     numericOID2MatchingRuleUses.remove(use.getMatchingRuleOID());
     for (final String name : use.getNames())
     {
       final String lowerName = StaticUtils.toLowerCase(name);
-      final List<MatchingRuleUse> uses = name2MatchingRuleUses
-          .get(lowerName);
+      final List<MatchingRuleUse> uses = name2MatchingRuleUses.get(lowerName);
       if (uses != null && uses.contains(use))
       {
         if (uses.size() <= 1)
@@ -2766,7 +2775,7 @@
 
 
 
-  private synchronized void removeNameForm(NameForm form)
+  private void removeNameForm(final NameForm form)
   {
     numericOID2NameForms.remove(form.getOID());
     name2NameForms.remove(form.getOID());
@@ -2790,15 +2799,14 @@
 
 
 
-  private synchronized void removeObjectClass(ObjectClass oc)
+  private void removeObjectClass(final ObjectClass oc)
   {
     numericOID2ObjectClasses.remove(oc.getOID());
     name2ObjectClasses.remove(oc.getOID());
     for (final String name : oc.getNames())
     {
       final String lowerName = StaticUtils.toLowerCase(name);
-      final List<ObjectClass> classes = name2ObjectClasses
-          .get(lowerName);
+      final List<ObjectClass> classes = name2ObjectClasses.get(lowerName);
       if (classes != null && classes.contains(oc))
       {
         if (classes.size() <= 1)
@@ -2815,14 +2823,14 @@
 
 
 
-  private synchronized void removeSyntax(Syntax syntax)
+  private void removeSyntax(final Syntax syntax)
   {
     numericOID2Syntaxes.remove(syntax.getOID());
   }
 
 
 
-  private synchronized void validate()
+  private void validate()
   {
     // Verify all references in all elements
     for (final Syntax syntax : numericOID2Syntaxes.values().toArray(
@@ -2835,14 +2843,13 @@
       catch (final SchemaException e)
       {
         removeSyntax(syntax);
-        warnings.add(ERR_SYNTAX_VALIDATION_FAIL.get(syntax.toString(),
-            e.toString()));
+        warnings.add(ERR_SYNTAX_VALIDATION_FAIL.get(syntax.toString(), e
+            .toString()));
       }
     }
 
-    for (final MatchingRule rule : numericOID2MatchingRules.values()
-        .toArray(
-            new MatchingRule[numericOID2MatchingRules.values().size()]))
+    for (final MatchingRule rule : numericOID2MatchingRules.values().toArray(
+        new MatchingRule[numericOID2MatchingRules.values().size()]))
     {
       try
       {
@@ -2851,15 +2858,12 @@
       catch (final SchemaException e)
       {
         removeMatchingRule(rule);
-        warnings.add(ERR_MR_VALIDATION_FAIL.get(rule.toString(), e
-            .toString()));
+        warnings.add(ERR_MR_VALIDATION_FAIL.get(rule.toString(), e.toString()));
       }
     }
 
-    for (final AttributeType attribute : numericOID2AttributeTypes
-        .values()
-        .toArray(
-            new AttributeType[numericOID2AttributeTypes.values().size()]))
+    for (final AttributeType attribute : numericOID2AttributeTypes.values()
+        .toArray(new AttributeType[numericOID2AttributeTypes.values().size()]))
     {
       try
       {
@@ -2868,14 +2872,13 @@
       catch (final SchemaException e)
       {
         removeAttributeType(attribute);
-        warnings.add(ERR_ATTR_TYPE_VALIDATION_FAIL.get(attribute
-            .toString(), e.toString()));
+        warnings.add(ERR_ATTR_TYPE_VALIDATION_FAIL.get(attribute.toString(), e
+            .toString()));
       }
     }
 
-    for (final ObjectClass oc : numericOID2ObjectClasses.values()
-        .toArray(
-            new ObjectClass[numericOID2ObjectClasses.values().size()]))
+    for (final ObjectClass oc : numericOID2ObjectClasses.values().toArray(
+        new ObjectClass[numericOID2ObjectClasses.values().size()]))
     {
       try
       {
@@ -2884,15 +2887,13 @@
       catch (final SchemaException e)
       {
         removeObjectClass(oc);
-        warnings.add(ERR_OC_VALIDATION_FAIL.get(oc.toString(), e
-            .toString()));
+        warnings.add(ERR_OC_VALIDATION_FAIL.get(oc.toString(), e.toString()));
       }
     }
 
-    for (final MatchingRuleUse use : numericOID2MatchingRuleUses
-        .values().toArray(
-            new MatchingRuleUse[numericOID2MatchingRuleUses.values()
-                .size()]))
+    for (final MatchingRuleUse use : numericOID2MatchingRuleUses.values()
+        .toArray(
+            new MatchingRuleUse[numericOID2MatchingRuleUses.values().size()]))
     {
       try
       {
@@ -2901,8 +2902,7 @@
       catch (final SchemaException e)
       {
         removeMatchingRuleUse(use);
-        warnings.add(ERR_MRU_VALIDATION_FAIL.get(use.toString(), e
-            .toString()));
+        warnings.add(ERR_MRU_VALIDATION_FAIL.get(use.toString(), e.toString()));
       }
     }
 
@@ -2918,8 +2918,7 @@
         final String ocOID = form.getStructuralClass().getOID();
         if ((forms = objectClass2NameForms.get(ocOID)) == null)
         {
-          objectClass2NameForms.put(ocOID, Collections
-              .singletonList(form));
+          objectClass2NameForms.put(ocOID, Collections.singletonList(form));
         }
         else if (forms.size() == 1)
         {
@@ -2935,15 +2934,13 @@
       catch (final SchemaException e)
       {
         removeNameForm(form);
-        warnings.add(ERR_NAMEFORM_VALIDATION_FAIL.get(form.toString(),
-            e.toString()));
+        warnings.add(ERR_NAMEFORM_VALIDATION_FAIL.get(form.toString(), e
+            .toString()));
       }
     }
 
-    for (final DITContentRule rule : numericOID2ContentRules
-        .values()
-        .toArray(
-            new DITContentRule[numericOID2ContentRules.values().size()]))
+    for (final DITContentRule rule : numericOID2ContentRules.values().toArray(
+        new DITContentRule[numericOID2ContentRules.values().size()]))
     {
       try
       {
@@ -2952,14 +2949,13 @@
       catch (final SchemaException e)
       {
         removeDITContentRule(rule);
-        warnings.add(ERR_DCR_VALIDATION_FAIL.get(rule.toString(), e
-            .toString()));
+        warnings
+            .add(ERR_DCR_VALIDATION_FAIL.get(rule.toString(), e.toString()));
       }
     }
 
-    for (final DITStructureRule rule : id2StructureRules.values()
-        .toArray(
-            new DITStructureRule[id2StructureRules.values().size()]))
+    for (final DITStructureRule rule : id2StructureRules.values().toArray(
+        new DITStructureRule[id2StructureRules.values().size()]))
     {
       try
       {
@@ -2970,8 +2966,7 @@
         final String ocOID = rule.getNameForm().getOID();
         if ((rules = nameForm2StructureRules.get(ocOID)) == null)
         {
-          nameForm2StructureRules.put(ocOID, Collections
-              .singletonList(rule));
+          nameForm2StructureRules.put(ocOID, Collections.singletonList(rule));
         }
         else if (rules.size() == 1)
         {
@@ -2987,17 +2982,9 @@
       catch (final SchemaException e)
       {
         removeDITStructureRule(rule);
-        warnings.add(ERR_DSR_VALIDATION_FAIL.get(rule.toString(), e
-            .toString()));
+        warnings
+            .add(ERR_DSR_VALIDATION_FAIL.get(rule.toString(), e.toString()));
       }
     }
-
-  }
-
-
-
-  void addWarning(LocalizableMessage warning)
-  {
-    warnings.add(warning);
   }
 }
diff --git a/sdk/src/org/opends/sdk/schema/SchemaCompatOptions.java b/sdk/src/org/opends/sdk/schema/SchemaCompatOptions.java
index e4bfc0e..fd57a1c 100644
--- a/sdk/src/org/opends/sdk/schema/SchemaCompatOptions.java
+++ b/sdk/src/org/opends/sdk/schema/SchemaCompatOptions.java
@@ -30,19 +30,19 @@
 
 
 /**
- * This class provides various schema compatibility options which may be
- * used to facilitate interoperability with legacy LDAP applications.
+ * This class provides various schema compatibility options which may be used to
+ * facilitate interoperability with legacy LDAP applications.
  */
 public final class SchemaCompatOptions
 {
   /**
    * Creates a copy of the provided schema compatibility options.
-   * 
+   *
    * @param options
    *          The options to be copied.
    * @return The copy of the provided schema compatibility options.
    */
-  public static SchemaCompatOptions copyOf(SchemaCompatOptions options)
+  public static SchemaCompatOptions copyOf(final SchemaCompatOptions options)
   {
     return defaultOptions().assign(options);
   }
@@ -50,9 +50,8 @@
 
 
   /**
-   * Creates a new set of schema compatibility options with default
-   * settings.
-   * 
+   * Creates a new set of schema compatibility options with default settings.
+   *
    * @return The new schema compatibility options.
    */
   public static SchemaCompatOptions defaultOptions()
@@ -60,6 +59,8 @@
     return new SchemaCompatOptions();
   }
 
+
+
   private boolean isTelephoneNumberSyntaxStrict = false;
 
   private boolean isZeroLengthDirectoryStringsAllowed = false;
@@ -75,14 +76,13 @@
 
 
   /**
-   * Indicates whether or not the Telephone Number syntax should ensure
-   * that all values conform to the E.123 international telephone number
-   * format. By default this compatibility option is set to {@code
-   * false}.
-   * 
-   * @return {@code true} if the Telephone Number syntax should ensure
-   *         that all values conform to the E.123 international
-   *         telephone number format, or {@code false} if not.
+   * Indicates whether or not the Telephone Number syntax should ensure that all
+   * values conform to the E.123 international telephone number format. By
+   * default this compatibility option is set to {@code false}.
+   *
+   * @return {@code true} if the Telephone Number syntax should ensure that all
+   *         values conform to the E.123 international telephone number format,
+   *         or {@code false} if not.
    */
   public boolean isTelephoneNumberSyntaxStrict()
   {
@@ -94,13 +94,13 @@
   /**
    * Indicates whether or not zero-length values will be allowed by the
    * Directory String syntax. This is technically forbidden by the LDAP
-   * specification, but it was allowed in earlier versions of the
-   * server, and the discussion of the directory string syntax in RFC
-   * 2252 does not explicitly state that they are not allowed. By
-   * default this compatibility option is set to {@code false}.
-   * 
-   * @return {@code true} if zero-length values will be allowed by the
-   *         Directory String syntax, or {@code false} if not.
+   * specification, but it was allowed in earlier versions of the server, and
+   * the discussion of the directory string syntax in RFC 2252 does not
+   * explicitly state that they are not allowed. By default this compatibility
+   * option is set to {@code false}.
+   *
+   * @return {@code true} if zero-length values will be allowed by the Directory
+   *         String syntax, or {@code false} if not.
    */
   public boolean isZeroLengthDirectoryStringsAllowed()
   {
@@ -110,19 +110,18 @@
 
 
   /**
-   * Indicates whether or not the Telephone Number syntax should ensure
-   * that all values conform to the E.123 international telephone number
-   * format. By default this compatibility option is set to {@code
-   * false}.
-   * 
+   * Indicates whether or not the Telephone Number syntax should ensure that all
+   * values conform to the E.123 international telephone number format. By
+   * default this compatibility option is set to {@code false}.
+   *
    * @param isStrict
-   *          {@code true} if the Telephone Number syntax should ensure
-   *          that all values conform to the E.123 international
-   *          telephone number format, or {@code false} if not.
+   *          {@code true} if the Telephone Number syntax should ensure that all
+   *          values conform to the E.123 international telephone number format,
+   *          or {@code false} if not.
    * @return A reference to this {@code SchemaCompat}.
    */
   public SchemaCompatOptions setTelephoneNumberSyntaxStrict(
-      boolean isStrict)
+      final boolean isStrict)
   {
     this.isTelephoneNumberSyntaxStrict = isStrict;
     return this;
@@ -133,18 +132,18 @@
   /**
    * Specifies whether or not zero-length values will be allowed by the
    * Directory String syntax. This is technically forbidden by the LDAP
-   * specification, but it was allowed in earlier versions of the
-   * server, and the discussion of the directory string syntax in RFC
-   * 2252 does not explicitly state that they are not allowed. By
-   * default this compatibility option is set to {@code false}.
-   * 
+   * specification, but it was allowed in earlier versions of the server, and
+   * the discussion of the directory string syntax in RFC 2252 does not
+   * explicitly state that they are not allowed. By default this compatibility
+   * option is set to {@code false}.
+   *
    * @param isAllowed
    *          {@code true} if zero-length values will be allowed by the
    *          Directory String syntax, or {@code false} if not.
    * @return A reference to this {@code SchemaCompat}.
    */
   public SchemaCompatOptions setZeroLengthDirectoryStringsAllowed(
-      boolean isAllowed)
+      final boolean isAllowed)
   {
     this.isZeroLengthDirectoryStringsAllowed = isAllowed;
     return this;
@@ -153,10 +152,9 @@
 
 
   // Assigns the provided options to this set of options.
-  SchemaCompatOptions assign(SchemaCompatOptions options)
+  SchemaCompatOptions assign(final SchemaCompatOptions options)
   {
-    return setTelephoneNumberSyntaxStrict(
-        options.isTelephoneNumberSyntaxStrict)
+    return setTelephoneNumberSyntaxStrict(options.isTelephoneNumberSyntaxStrict)
         .setZeroLengthDirectoryStringsAllowed(
             options.isZeroLengthDirectoryStringsAllowed);
   }
diff --git a/sdk/src/org/opends/sdk/schema/SchemaConstants.java b/sdk/src/org/opends/sdk/schema/SchemaConstants.java
index accba25..9f0fcab 100644
--- a/sdk/src/org/opends/sdk/schema/SchemaConstants.java
+++ b/sdk/src/org/opends/sdk/schema/SchemaConstants.java
@@ -33,138 +33,129 @@
 
 
 /**
- * This class defines a number of constants used by Directory Server
- * schema elements, like matching rules, syntaxes, attribute types, and
- * objectclasses.
+ * This class defines a number of constants used by Directory Server schema
+ * elements, like matching rules, syntaxes, attribute types, and objectclasses.
  */
-class SchemaConstants
+final class SchemaConstants
 {
   /**
-   * The IANA-assigned base OID for all things under the OpenDS
-   * umbrella.
+   * The IANA-assigned base OID for all things under the OpenDS umbrella.
    */
   public static final String OID_OPENDS_BASE = "1.3.6.1.4.1.26027";
 
   /**
-   * The base OID that will be used for the OpenDS Directory Server
-   * project.
+   * The base OID that will be used for the OpenDS Directory Server project.
    */
-  public static final String OID_OPENDS_SERVER_BASE =
-      OID_OPENDS_BASE + ".1";
+  public static final String OID_OPENDS_SERVER_BASE = OID_OPENDS_BASE + ".1";
 
   /**
-   * The base OID that will be used for OpenDS Directory Server
-   * attribute type definitions.
+   * The base OID that will be used for OpenDS Directory Server attribute type
+   * definitions.
    */
   public static final String OID_OPENDS_SERVER_ATTRIBUTE_TYPE_BASE =
-      OID_OPENDS_SERVER_BASE + ".1";
+    OID_OPENDS_SERVER_BASE + ".1";
 
   /**
-   * The base OID that will be used for OpenDS Directory Server object
-   * class definitions.
+   * The base OID that will be used for OpenDS Directory Server object class
+   * definitions.
    */
   public static final String OID_OPENDS_SERVER_OBJECT_CLASS_BASE =
-      OID_OPENDS_SERVER_BASE + ".2";
+    OID_OPENDS_SERVER_BASE + ".2";
 
   /**
-   * The base OID that will be used for OpenDS Directory Server
-   * attribute syntax definitions.
+   * The base OID that will be used for OpenDS Directory Server attribute syntax
+   * definitions.
    */
   public static final String OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE =
-      OID_OPENDS_SERVER_BASE + ".3";
+    OID_OPENDS_SERVER_BASE + ".3";
 
   /**
-   * The base OID that will be used for OpenDS Directory Server matching
-   * rule definitions.
+   * The base OID that will be used for OpenDS Directory Server matching rule
+   * definitions.
    */
   public static final String OID_OPENDS_SERVER_MATCHING_RULE_BASE =
-      OID_OPENDS_SERVER_BASE + ".4";
+    OID_OPENDS_SERVER_BASE + ".4";
 
   /**
    * The base OID that will be used for OpenDS Directory Server control
    * definitions.
    */
   public static final String OID_OPENDS_SERVER_CONTROL_BASE =
-      OID_OPENDS_SERVER_BASE + ".5";
+    OID_OPENDS_SERVER_BASE + ".5";
 
   /**
    * The base OID that will be used for OpenDS Directory Server extended
    * operation definitions.
    */
   public static final String OID_OPENDS_SERVER_EXTENDED_OPERATION_BASE =
-      OID_OPENDS_SERVER_BASE + ".6";
+    OID_OPENDS_SERVER_BASE + ".6";
 
   /**
-   * The base OID that will be used for general-purpose (i.e., "other")
-   * types of OIDs that need to be allocated for the OpenDS Directory
-   * Server.
+   * The base OID that will be used for general-purpose (i.e., "other") types of
+   * OIDs that need to be allocated for the OpenDS Directory Server.
    */
   public static final String OID_OPENDS_SERVER_GENERAL_USE_BASE =
-      OID_OPENDS_SERVER_BASE + ".9";
+    OID_OPENDS_SERVER_BASE + ".9";
 
   /**
-   * The base OID that will be used for temporary or experimental OIDs
-   * within the OpenDS Directory Server.
+   * The base OID that will be used for temporary or experimental OIDs within
+   * the OpenDS Directory Server.
    */
   public static final String OID_OPENDS_SERVER_EXPERIMENTAL_BASE =
-      OID_OPENDS_SERVER_BASE + ".999";
+    OID_OPENDS_SERVER_BASE + ".999";
 
   /**
    * The description for the doubleMetaphoneApproximateMatch approximate
    * matching rule.
    */
   public static final String AMR_DOUBLE_METAPHONE_DESCRIPTION =
-      "Double Metaphone Approximate Match";
+    "Double Metaphone Approximate Match";
 
   /**
-   * The name for the doubleMetaphoneApproximateMatch approximate
-   * matching rule.
+   * The name for the doubleMetaphoneApproximateMatch approximate matching rule.
    */
   public static final String AMR_DOUBLE_METAPHONE_NAME =
-      "ds-mr-double-metaphone-approx";
+    "ds-mr-double-metaphone-approx";
 
   /**
-   * The OID for the doubleMetaphoneApproximateMatch approximate
-   * matching rule.
+   * The OID for the doubleMetaphoneApproximateMatch approximate matching rule.
    */
   public static final String AMR_DOUBLE_METAPHONE_OID =
-      OID_OPENDS_SERVER_MATCHING_RULE_BASE + ".1";
+    OID_OPENDS_SERVER_MATCHING_RULE_BASE + ".1";
 
   /**
    * The description for the authPasswordExactMatch matching rule.
    */
   public static final String EMR_AUTH_PASSWORD_EXACT_DESCRIPTION =
-      "authentication password exact matching rule";
+    "authentication password exact matching rule";
 
   /**
    * The name for the authPasswordExactMatch equality matching rule.
    */
   public static final String EMR_AUTH_PASSWORD_EXACT_NAME =
-      "authPasswordExactMatch";
+    "authPasswordExactMatch";
 
   /**
    * The OID for the authPasswordExactMatch equality matching rule.
    */
   public static final String EMR_AUTH_PASSWORD_EXACT_OID =
-      "1.3.6.1.4.1.4203.1.2.2";
+    "1.3.6.1.4.1.4203.1.2.2";
 
   /**
    * The description for the authPasswordMatch matching rule.
    */
   public static final String EMR_AUTH_PASSWORD_DESCRIPTION =
-      "authentication password matching rule";
+    "authentication password matching rule";
 
   /**
    * The name for the authPasswordMatch equality matching rule.
    */
-  public static final String EMR_AUTH_PASSWORD_NAME =
-      "authPasswordMatch";
+  public static final String EMR_AUTH_PASSWORD_NAME = "authPasswordMatch";
 
   /**
    * The OID for the authPasswordMatch equality matching rule.
    */
-  public static final String EMR_AUTH_PASSWORD_OID =
-      "1.3.6.1.4.1.4203.1.2.3";
+  public static final String EMR_AUTH_PASSWORD_OID = "1.3.6.1.4.1.4203.1.2.3";
 
   /**
    * The name for the bitStringMatch equality matching rule.
@@ -199,14 +190,13 @@
   /**
    * The name for the caseExactIA5Match equality matching rule.
    */
-  public static final String EMR_CASE_EXACT_IA5_NAME =
-      "caseExactIA5Match";
+  public static final String EMR_CASE_EXACT_IA5_NAME = "caseExactIA5Match";
 
   /**
    * The OID for the caseExactIA5Match equality matching rule.
    */
   public static final String EMR_CASE_EXACT_IA5_OID =
-      "1.3.6.1.4.1.1466.109.114.1";
+    "1.3.6.1.4.1.1466.109.114.1";
 
   /**
    * The name for the caseIgnoreMatch equality matching rule.
@@ -221,20 +211,18 @@
   /**
    * The name for the caseIgnoreIA5Match equality matching rule.
    */
-  public static final String EMR_CASE_IGNORE_IA5_NAME =
-      "caseIgnoreIA5Match";
+  public static final String EMR_CASE_IGNORE_IA5_NAME = "caseIgnoreIA5Match";
 
   /**
    * The OID for the caseIgnoreIA5Match equality matching rule.
    */
   public static final String EMR_CASE_IGNORE_IA5_OID =
-      "1.3.6.1.4.1.1466.109.114.2";
+    "1.3.6.1.4.1.1466.109.114.2";
 
   /**
    * The name for the caseIgnoreListMatch equality matching rule.
    */
-  public static final String EMR_CASE_IGNORE_LIST_NAME =
-      "caseIgnoreListMatch";
+  public static final String EMR_CASE_IGNORE_LIST_NAME = "caseIgnoreListMatch";
 
   /**
    * The OID for the caseIgnoreListMatch equality matching rule.
@@ -242,18 +230,16 @@
   public static final String EMR_CASE_IGNORE_LIST_OID = "2.5.13.11";
 
   /**
-   * The name for the directoryStringFirstComponentMatch equality
-   * matching rule.
+   * The name for the directoryStringFirstComponentMatch equality matching rule.
    */
   public static final String EMR_DIRECTORY_STRING_FIRST_COMPONENT_NAME =
-      "directoryStringFirstComponentMatch";
+    "directoryStringFirstComponentMatch";
 
   /**
-   * The OID for the directoryStringFirstComponentMatch equality
-   * matching rule.
+   * The OID for the directoryStringFirstComponentMatch equality matching rule.
    */
   public static final String EMR_DIRECTORY_STRING_FIRST_COMPONENT_OID =
-      "2.5.13.31";
+    "2.5.13.31";
 
   /**
    * The name for the distinguishedNameMatch equality matching rule.
@@ -268,8 +254,7 @@
   /**
    * The name for the generalizedTimeMatch equality matching rule.
    */
-  public static final String EMR_GENERALIZED_TIME_NAME =
-      "generalizedTimeMatch";
+  public static final String EMR_GENERALIZED_TIME_NAME = "generalizedTimeMatch";
 
   /**
    * The OID for the generalizedTimeMatch equality matching rule.
@@ -290,13 +275,12 @@
    * The name for the integerFirstComponentMatch equality matching rule.
    */
   public static final String EMR_INTEGER_FIRST_COMPONENT_NAME =
-      "integerFirstComponentMatch";
+    "integerFirstComponentMatch";
 
   /**
    * The OID for the integerFirstComponentMatch equality matching rule.
    */
-  public static final String EMR_INTEGER_FIRST_COMPONENT_OID =
-      "2.5.13.29";
+  public static final String EMR_INTEGER_FIRST_COMPONENT_OID = "2.5.13.29";
 
   /**
    * The name for the keywordMatch equality matching rule.
@@ -311,8 +295,7 @@
   /**
    * The name for the numericStringMatch equality matching rule.
    */
-  public static final String EMR_NUMERIC_STRING_NAME =
-      "numericStringMatch";
+  public static final String EMR_NUMERIC_STRING_NAME = "numericStringMatch";
 
   /**
    * The OID for the numericStringMatch equality matching rule.
@@ -340,15 +323,14 @@
   public static final String EMR_OID_OID = "2.5.13.0";
 
   /**
-   * The name for the objectIdentifierFirstComponentMatch equality
-   * matching rule.
+   * The name for the objectIdentifierFirstComponentMatch equality matching
+   * rule.
    */
   public static final String EMR_OID_FIRST_COMPONENT_NAME =
-      "objectIdentifierFirstComponentMatch";
+    "objectIdentifierFirstComponentMatch";
 
   /**
-   * The OID for the objectIdentifierFirstComponentMatch equality
-   * matching rule.
+   * The OID for the objectIdentifierFirstComponentMatch equality matching rule.
    */
   public static final String EMR_OID_FIRST_COMPONENT_OID = "2.5.13.30";
 
@@ -356,7 +338,7 @@
    * The name for the presentationAddressMatch equality matching rule.
    */
   public static final String EMR_PRESENTATION_ADDRESS_NAME =
-      "presentationAddressMatch";
+    "presentationAddressMatch";
 
   /**
    * The OID for the presentationAddressMatch equality matching rule.
@@ -367,7 +349,7 @@
    * The name for the protocolInformationMatch equality matching rule.
    */
   public static final String EMR_PROTOCOL_INFORMATION_NAME =
-      "protocolInformationMatch";
+    "protocolInformationMatch";
 
   /**
    * The OID for the protocolInformationMatch equality matching rule.
@@ -377,8 +359,7 @@
   /**
    * The name for the telephoneNumberMatch equality matching rule.
    */
-  public static final String EMR_TELEPHONE_NAME =
-      "telephoneNumberMatch";
+  public static final String EMR_TELEPHONE_NAME = "telephoneNumberMatch";
 
   /**
    * The OID for the telephoneNumberMatch equality matching rule.
@@ -388,8 +369,7 @@
   /**
    * The name for the uniqueMemberMatch equality matching rule.
    */
-  public static final String EMR_UNIQUE_MEMBER_NAME =
-      "uniqueMemberMatch";
+  public static final String EMR_UNIQUE_MEMBER_NAME = "uniqueMemberMatch";
 
   /**
    * The OID for the uniqueMemberMatch equality matching rule.
@@ -400,37 +380,37 @@
    * The description for the userPasswordExactMatch matching rule.
    */
   public static final String EMR_USER_PASSWORD_EXACT_DESCRIPTION =
-      "user password exact matching rule";
+    "user password exact matching rule";
 
   /**
    * The name for the userPasswordExactMatch equality matching rule.
    */
   public static final String EMR_USER_PASSWORD_EXACT_NAME =
-      "ds-mr-user-password-exact";
+    "ds-mr-user-password-exact";
 
   /**
    * The OID for the userPasswordExactMatch equality matching rule.
    */
   public static final String EMR_USER_PASSWORD_EXACT_OID =
-      OID_OPENDS_SERVER_MATCHING_RULE_BASE + ".2";
+    OID_OPENDS_SERVER_MATCHING_RULE_BASE + ".2";
 
   /**
    * The description for the userPasswordMatch matching rule.
    */
   public static final String EMR_USER_PASSWORD_DESCRIPTION =
-      "user password matching rule";
+    "user password matching rule";
 
   /**
    * The name for the userPasswordMatch equality matching rule.
    */
   public static final String EMR_USER_PASSWORD_NAME =
-      "ds-mr-user-password-equality";
+    "ds-mr-user-password-equality";
 
   /**
    * The OID for the userPasswordMatch equality matching rule.
    */
   public static final String EMR_USER_PASSWORD_OID =
-      OID_OPENDS_SERVER_MATCHING_RULE_BASE + ".3";
+    OID_OPENDS_SERVER_MATCHING_RULE_BASE + ".3";
 
   /**
    * The name for the uuidMatch equality matching rule.
@@ -455,8 +435,7 @@
   /**
    * The name for the caseExactOrderingMatch ordering matching rule.
    */
-  public static final String OMR_CASE_EXACT_NAME =
-      "caseExactOrderingMatch";
+  public static final String OMR_CASE_EXACT_NAME = "caseExactOrderingMatch";
 
   /**
    * The OID for the caseExactOrderingMatch ordering matching rule.
@@ -466,8 +445,7 @@
   /**
    * The name for the caseIgnoreOrderingMatch ordering matching rule.
    */
-  public static final String OMR_CASE_IGNORE_NAME =
-      "caseIgnoreOrderingMatch";
+  public static final String OMR_CASE_IGNORE_NAME = "caseIgnoreOrderingMatch";
 
   /**
    * The OID for the caseIgnoreOrderingMatch ordering matching rule.
@@ -475,15 +453,13 @@
   public static final String OMR_CASE_IGNORE_OID = "2.5.13.3";
 
   /**
-   * The name for the generalizedTimeOrderingMatch ordering matching
-   * rule.
+   * The name for the generalizedTimeOrderingMatch ordering matching rule.
    */
   public static final String OMR_GENERALIZED_TIME_NAME =
-      "generalizedTimeOrderingMatch";
+    "generalizedTimeOrderingMatch";
 
   /**
-   * The OID for the generalizedTimeOrderingMatch ordering matching
-   * rule.
+   * The OID for the generalizedTimeOrderingMatch ordering matching rule.
    */
   public static final String OMR_GENERALIZED_TIME_OID = "2.5.13.28";
 
@@ -501,7 +477,7 @@
    * The name for the numericStringOrderingMatch ordering matching rule.
    */
   public static final String OMR_NUMERIC_STRING_NAME =
-      "numericStringOrderingMatch";
+    "numericStringOrderingMatch";
 
   /**
    * The OID for the numericStringOrderingMatch ordering matching rule.
@@ -511,8 +487,7 @@
   /**
    * The name for the octetStringOrderingMatch ordering matching rule.
    */
-  public static final String OMR_OCTET_STRING_NAME =
-      "octetStringOrderingMatch";
+  public static final String OMR_OCTET_STRING_NAME = "octetStringOrderingMatch";
 
   /**
    * The OID for the octetStringOrderingMatch ordering matching rule.
@@ -532,20 +507,17 @@
   /**
    * The name for the enumOrderingMatch ordering matching rule.
    */
-  public static final String OMR_GENERIC_ENUM_NAME =
-      "enumOrderingMatch";
+  public static final String OMR_GENERIC_ENUM_NAME = "enumOrderingMatch";
 
   /**
    * The oid for the generic enum syntax ordering matching rule.
    */
-  public static final String OMR_OID_GENERIC_ENUM =
-      "1.3.6.1.4.1.26027.1.4.8";
+  public static final String OMR_OID_GENERIC_ENUM = "1.3.6.1.4.1.26027.1.4.8";
 
   /**
    * The name for the caseExactSubstringsMatch substring matching rule.
    */
-  public static final String SMR_CASE_EXACT_NAME =
-      "caseExactSubstringsMatch";
+  public static final String SMR_CASE_EXACT_NAME = "caseExactSubstringsMatch";
 
   /**
    * The OID for the caseExactSubstringsMatch substring matching rule.
@@ -553,25 +525,22 @@
   public static final String SMR_CASE_EXACT_OID = "2.5.13.7";
 
   /**
-   * The name for the caseExactIA5SubstringsMatch substring matching
-   * rule.
+   * The name for the caseExactIA5SubstringsMatch substring matching rule.
    */
   public static final String SMR_CASE_EXACT_IA5_NAME =
-      "caseExactIA5SubstringsMatch";
+    "caseExactIA5SubstringsMatch";
 
   /**
-   * The OID for the caseExactIA5SubstringsMatch substring matching
-   * rule. // FIXME -- This needs to be updated once a real OID is
-   * assigned.
+   * The OID for the caseExactIA5SubstringsMatch substring matching rule. //
+   * FIXME -- This needs to be updated once a real OID is assigned.
    */
   public static final String SMR_CASE_EXACT_IA5_OID =
-      OID_OPENDS_SERVER_MATCHING_RULE_BASE + ".902";
+    OID_OPENDS_SERVER_MATCHING_RULE_BASE + ".902";
 
   /**
    * The name for the caseIgnoreSubstringsMatch substring matching rule.
    */
-  public static final String SMR_CASE_IGNORE_NAME =
-      "caseIgnoreSubstringsMatch";
+  public static final String SMR_CASE_IGNORE_NAME = "caseIgnoreSubstringsMatch";
 
   /**
    * The OID for the caseIgnoreSubstringsMatch substring matching rule.
@@ -579,51 +548,44 @@
   public static final String SMR_CASE_IGNORE_OID = "2.5.13.4";
 
   /**
-   * The name for the caseIgnoreIA5SubstringsMatch substring matching
-   * rule.
+   * The name for the caseIgnoreIA5SubstringsMatch substring matching rule.
    */
   public static final String SMR_CASE_IGNORE_IA5_NAME =
-      "caseIgnoreIA5SubstringsMatch";
+    "caseIgnoreIA5SubstringsMatch";
 
   /**
-   * The OID for the caseIgnoreIA5SubstringsMatch substring matching
-   * rule.
+   * The OID for the caseIgnoreIA5SubstringsMatch substring matching rule.
    */
   public static final String SMR_CASE_IGNORE_IA5_OID =
-      "1.3.6.1.4.1.1466.109.114.3";
+    "1.3.6.1.4.1.1466.109.114.3";
 
   /**
-   * The name for the caseIgnoreListSubstringsMatch substring matching
-   * rule.
+   * The name for the caseIgnoreListSubstringsMatch substring matching rule.
    */
   public static final String SMR_CASE_IGNORE_LIST_NAME =
-      "caseIgnoreListSubstringsMatch";
+    "caseIgnoreListSubstringsMatch";
 
   /**
-   * The OID for the caseIgnoreListSubstringsMatch substring matching
-   * rule.
+   * The OID for the caseIgnoreListSubstringsMatch substring matching rule.
    */
   public static final String SMR_CASE_IGNORE_LIST_OID = "2.5.13.12";
 
   /**
-   * The name for the numericStringSubstringsMatch substring matching
-   * rule.
+   * The name for the numericStringSubstringsMatch substring matching rule.
    */
   public static final String SMR_NUMERIC_STRING_NAME =
-      "numericStringSubstringsMatch";
+    "numericStringSubstringsMatch";
 
   /**
-   * The OID for the numericStringSubstringsMatch substring matching
-   * rule.
+   * The OID for the numericStringSubstringsMatch substring matching rule.
    */
   public static final String SMR_NUMERIC_STRING_OID = "2.5.13.10";
 
   /**
-   * The name for the octetStringSubstringsMatch substring matching
-   * rule.
+   * The name for the octetStringSubstringsMatch substring matching rule.
    */
   public static final String SMR_OCTET_STRING_NAME =
-      "octetStringSubstringsMatch";
+    "octetStringSubstringsMatch";
 
   /**
    * The OID for the octetStringSubstringsMatch substring matching rule.
@@ -631,15 +593,13 @@
   public static final String SMR_OCTET_STRING_OID = "2.5.13.19";
 
   /**
-   * The name for the telephoneNumberSubstringsMatch substring matching
-   * rule.
+   * The name for the telephoneNumberSubstringsMatch substring matching rule.
    */
   public static final String SMR_TELEPHONE_NAME =
-      "telephoneNumberSubstringsMatch";
+    "telephoneNumberSubstringsMatch";
 
   /**
-   * The OID for the telephoneNumberSubstringsMatch substring matching
-   * rule.
+   * The OID for the telephoneNumberSubstringsMatch substring matching rule.
    */
   public static final String SMR_TELEPHONE_OID = "2.5.13.21";
 
@@ -647,75 +607,71 @@
    * The OID for the absolute subtree specification attribute syntax.
    */
   public static final String SYNTAX_ABSOLUTE_SUBTREE_SPECIFICATION_OID =
-      OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".3";
+    OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".3";
 
   /**
-   * The description for the absolute subtree specification attribute
-   * syntax.
+   * The description for the absolute subtree specification attribute syntax.
    */
   public static final String SYNTAX_ABSOLUTE_SUBTREE_SPECIFICATION_DESCRIPTION =
-      "Absolute Subtree Specification";
+    "Absolute Subtree Specification";
 
   /**
    * The name for the absolute subtree specification attribute syntax.
    */
   public static final String SYNTAX_ABSOLUTE_SUBTREE_SPECIFICATION_NAME =
-      "ds-absolute-subtree-specification";
+    "ds-absolute-subtree-specification";
 
   /**
    * The OID for the aci attribute syntax.
    */
   public static final String SYNTAX_ACI_OID =
-      OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".4";
+    OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".4";
 
   /**
    * The description for aci attribute syntax.
    */
   public static final String SYNTAX_ACI_DESCRIPTION =
-      "Sun-defined Access Control Information";
+    "Sun-defined Access Control Information";
 
   /**
    * The name for the aci attribute syntax.
    */
-  public static final String SYNTAX_ACI_NAME =
-      "ds-syntax-dseecompat-aci";
+  public static final String SYNTAX_ACI_NAME = "ds-syntax-dseecompat-aci";
 
   /**
-   * The description for the attribute type description attribute
-   * syntax.
+   * The description for the attribute type description attribute syntax.
    */
   public static final String SYNTAX_ATTRIBUTE_TYPE_DESCRIPTION =
-      "Attribute Type Description";
+    "Attribute Type Description";
 
   /**
    * The name for the attribute type description attribute syntax.
    */
   public static final String SYNTAX_ATTRIBUTE_TYPE_NAME =
-      "AttributeTypeDescription";
+    "AttributeTypeDescription";
 
   /**
    * The OID for the attribute type description attribute syntax.
    */
   public static final String SYNTAX_ATTRIBUTE_TYPE_OID =
-      "1.3.6.1.4.1.1466.115.121.1.3";
+    "1.3.6.1.4.1.1466.115.121.1.3";
 
   /**
    * The description for the auth password attribute syntax.
    */
   public static final String SYNTAX_AUTH_PASSWORD_DESCRIPTION =
-      "Authentication Password Syntax";
+    "Authentication Password Syntax";
 
   /**
    * The name for the auth password attribute syntax.
    */
   public static final String SYNTAX_AUTH_PASSWORD_NAME =
-      "AuthenticationPasswordSyntax";
+    "AuthenticationPasswordSyntax";
 
   /**
    * The OID for the auth password attribute syntax.
    */
-  public static final String SYNTAX_AUTH_PASSWORD_OID =
-      "1.3.6.1.4.1.4203.1.1.2";
+  public static final String SYNTAX_AUTH_PASSWORD_OID = "1.3.6.1.4.1.4203.1.1.2";
 
   /**
    * The description for the binary attribute syntax.
@@ -730,14 +686,12 @@
   /**
    * The OID for the binary attribute syntax.
    */
-  public static final String SYNTAX_BINARY_OID =
-      "1.3.6.1.4.1.1466.115.121.1.5";
+  public static final String SYNTAX_BINARY_OID = "1.3.6.1.4.1.1466.115.121.1.5";
 
   /**
    * The description for the bit string attribute syntax.
    */
-  public static final String SYNTAX_BIT_STRING_DESCRIPTION =
-      "Bit String";
+  public static final String SYNTAX_BIT_STRING_DESCRIPTION = "Bit String";
 
   /**
    * The name for the bit string attribute syntax.
@@ -747,8 +701,7 @@
   /**
    * The OID for the bit string attribute syntax.
    */
-  public static final String SYNTAX_BIT_STRING_OID =
-      "1.3.6.1.4.1.1466.115.121.1.6";
+  public static final String SYNTAX_BIT_STRING_OID = "1.3.6.1.4.1.1466.115.121.1.6";
 
   /**
    * The description for the Boolean attribute syntax.
@@ -763,14 +716,12 @@
   /**
    * The OID for the Boolean attribute syntax.
    */
-  public static final String SYNTAX_BOOLEAN_OID =
-      "1.3.6.1.4.1.1466.115.121.1.7";
+  public static final String SYNTAX_BOOLEAN_OID = "1.3.6.1.4.1.1466.115.121.1.7";
 
   /**
    * The description for the certificate attribute syntax.
    */
-  public static final String SYNTAX_CERTIFICATE_DESCRIPTION =
-      "Certificate";
+  public static final String SYNTAX_CERTIFICATE_DESCRIPTION = "Certificate";
 
   /**
    * The name for the certificate attribute syntax.
@@ -781,13 +732,12 @@
    * The OID for the certificate attribute syntax.
    */
   public static final String SYNTAX_CERTIFICATE_OID =
-      "1.3.6.1.4.1.1466.115.121.1.8";
+    "1.3.6.1.4.1.1466.115.121.1.8";
 
   /**
    * The description for the certificate list attribute syntax.
    */
-  public static final String SYNTAX_CERTLIST_DESCRIPTION =
-      "Certificate List";
+  public static final String SYNTAX_CERTLIST_DESCRIPTION = "Certificate List";
 
   /**
    * The name for the certificate list attribute syntax.
@@ -798,13 +748,12 @@
    * The OID for the certificate list attribute syntax.
    */
   public static final String SYNTAX_CERTLIST_OID =
-      "1.3.6.1.4.1.1466.115.121.1.9";
+    "1.3.6.1.4.1.1466.115.121.1.9";
 
   /**
    * The description for the certificate pair attribute syntax.
    */
-  public static final String SYNTAX_CERTPAIR_DESCRIPTION =
-      "Certificate Pair";
+  public static final String SYNTAX_CERTPAIR_DESCRIPTION = "Certificate Pair";
 
   /**
    * The name for the certificate pair attribute syntax.
@@ -815,99 +764,94 @@
    * The OID for the certificate pair attribute syntax.
    */
   public static final String SYNTAX_CERTPAIR_OID =
-      "1.3.6.1.4.1.1466.115.121.1.10";
+    "1.3.6.1.4.1.1466.115.121.1.10";
 
   /**
    * The description for the country string attribute syntax.
    */
   public static final String SYNTAX_COUNTRY_STRING_DESCRIPTION =
-      "Country String";
+    "Country String";
 
   /**
    * The name for the country string attribute syntax.
    */
-  public static final String SYNTAX_COUNTRY_STRING_NAME =
-      "CountryString";
+  public static final String SYNTAX_COUNTRY_STRING_NAME = "CountryString";
 
   /**
    * The OID for the country string attribute syntax.
    */
   public static final String SYNTAX_COUNTRY_STRING_OID =
-      "1.3.6.1.4.1.1466.115.121.1.11";
+    "1.3.6.1.4.1.1466.115.121.1.11";
 
   /**
    * The description for the delivery method attribute syntax.
    */
   public static final String SYNTAX_DELIVERY_METHOD_DESCRIPTION =
-      "Delivery Method";
+    "Delivery Method";
 
   /**
    * The name for the delivery method attribute syntax.
    */
-  public static final String SYNTAX_DELIVERY_METHOD_NAME =
-      "DeliveryMethod";
+  public static final String SYNTAX_DELIVERY_METHOD_NAME = "DeliveryMethod";
 
   /**
    * The OID for the delivery method attribute syntax.
    */
   public static final String SYNTAX_DELIVERY_METHOD_OID =
-      "1.3.6.1.4.1.1466.115.121.1.14";
+    "1.3.6.1.4.1.1466.115.121.1.14";
 
   /**
    * The description for the Directory String attribute syntax.
    */
   public static final String SYNTAX_DIRECTORY_STRING_DESCRIPTION =
-      "Directory String";
+    "Directory String";
 
   /**
    * The name for the Directory String attribute syntax.
    */
-  public static final String SYNTAX_DIRECTORY_STRING_NAME =
-      "DirectoryString";
+  public static final String SYNTAX_DIRECTORY_STRING_NAME = "DirectoryString";
 
   /**
    * The OID for the Directory String attribute syntax.
    */
   public static final String SYNTAX_DIRECTORY_STRING_OID =
-      "1.3.6.1.4.1.1466.115.121.1.15";
+    "1.3.6.1.4.1.1466.115.121.1.15";
 
   /**
-   * The description for the DIT content rule description attribute
-   * syntax.
+   * The description for the DIT content rule description attribute syntax.
    */
   public static final String SYNTAX_DIT_CONTENT_RULE_DESCRIPTION =
-      "DIT Content Rule Description";
+    "DIT Content Rule Description";
 
   /**
    * The name for the DIT content rule description attribute syntax.
    */
   public static final String SYNTAX_DIT_CONTENT_RULE_NAME =
-      "DITContentRuleDescription";
+    "DITContentRuleDescription";
 
   /**
    * The OID for the DIT content rule description attribute syntax.
    */
   public static final String SYNTAX_DIT_CONTENT_RULE_OID =
-      "1.3.6.1.4.1.1466.115.121.1.16";
+    "1.3.6.1.4.1.1466.115.121.1.16";
 
   /**
-   * The description for the DIT structure rule description attribute
-   * syntax.
+   * The description for the DIT structure rule description attribute syntax.
    */
   public static final String SYNTAX_DIT_STRUCTURE_RULE_DESCRIPTION =
-      "DIT Structure Rule Description";
+    "DIT Structure Rule Description";
 
   /**
    * The name for the DIT structure rule description attribute syntax.
    */
   public static final String SYNTAX_DIT_STRUCTURE_RULE_NAME =
-      "DITStructureRuleDescription";
+    "DITStructureRuleDescription";
 
   /**
    * The OID for the DIT structure rule description attribute syntax.
    */
   public static final String SYNTAX_DIT_STRUCTURE_RULE_OID =
-      "1.3.6.1.4.1.1466.115.121.1.17";
+    "1.3.6.1.4.1.1466.115.121.1.17";
 
   /**
    * The description for the distinguished name attribute syntax.
@@ -922,45 +866,41 @@
   /**
    * The OID for the distinguished name attribute syntax.
    */
-  public static final String SYNTAX_DN_OID =
-      "1.3.6.1.4.1.1466.115.121.1.12";
+  public static final String SYNTAX_DN_OID = "1.3.6.1.4.1.1466.115.121.1.12";
 
   /**
    * The description for the enhanced guide attribute syntax.
    */
   public static final String SYNTAX_ENHANCED_GUIDE_DESCRIPTION =
-      "Enhanced Guide";
+    "Enhanced Guide";
 
   /**
    * The name for the enhanced guide attribute syntax.
    */
-  public static final String SYNTAX_ENHANCED_GUIDE_NAME =
-      "EnhancedGuide";
+  public static final String SYNTAX_ENHANCED_GUIDE_NAME = "EnhancedGuide";
 
   /**
    * The OID for the enhanced guide attribute syntax.
    */
   public static final String SYNTAX_ENHANCED_GUIDE_OID =
-      "1.3.6.1.4.1.1466.115.121.1.21";
+    "1.3.6.1.4.1.1466.115.121.1.21";
 
   /**
-   * The description for the facsimile telephone number attribute
-   * syntax.
+   * The description for the facsimile telephone number attribute syntax.
    */
   public static final String SYNTAX_FAXNUMBER_DESCRIPTION =
-      "Facsimile Telephone Number";
+    "Facsimile Telephone Number";
 
   /**
    * The name for the facsimile telephone number attribute syntax.
    */
-  public static final String SYNTAX_FAXNUMBER_NAME =
-      "FacsimileTelephoneNumber";
+  public static final String SYNTAX_FAXNUMBER_NAME = "FacsimileTelephoneNumber";
 
   /**
    * The OID for the facsimile telephone number attribute syntax.
    */
   public static final String SYNTAX_FAXNUMBER_OID =
-      "1.3.6.1.4.1.1466.115.121.1.22";
+    "1.3.6.1.4.1.1466.115.121.1.22";
 
   /**
    * The description for the fax attribute syntax.
@@ -975,26 +915,24 @@
   /**
    * The OID for the fax attribute syntax.
    */
-  public static final String SYNTAX_FAX_OID =
-      "1.3.6.1.4.1.1466.115.121.1.23";
+  public static final String SYNTAX_FAX_OID = "1.3.6.1.4.1.1466.115.121.1.23";
 
   /**
    * The description for the generalized time attribute syntax.
    */
   public static final String SYNTAX_GENERALIZED_TIME_DESCRIPTION =
-      "Generalized Time";
+    "Generalized Time";
 
   /**
    * The name for the generalized time attribute syntax.
    */
-  public static final String SYNTAX_GENERALIZED_TIME_NAME =
-      "GeneralizedTime";
+  public static final String SYNTAX_GENERALIZED_TIME_NAME = "GeneralizedTime";
 
   /**
    * The OID for the generalized time attribute syntax.
    */
   public static final String SYNTAX_GENERALIZED_TIME_OID =
-      "1.3.6.1.4.1.1466.115.121.1.24";
+    "1.3.6.1.4.1.1466.115.121.1.24";
 
   /**
    * The description for the guide attribute syntax.
@@ -1009,14 +947,12 @@
   /**
    * The OID for the guide attribute syntax.
    */
-  public static final String SYNTAX_GUIDE_OID =
-      "1.3.6.1.4.1.1466.115.121.1.25";
+  public static final String SYNTAX_GUIDE_OID = "1.3.6.1.4.1.1466.115.121.1.25";
 
   /**
    * The description for the IA5 string attribute syntax.
    */
-  public static final String SYNTAX_IA5_STRING_DESCRIPTION =
-      "IA5 String";
+  public static final String SYNTAX_IA5_STRING_DESCRIPTION = "IA5 String";
 
   /**
    * The name for the IA5 string attribute syntax.
@@ -1027,7 +963,7 @@
    * The OID for the IA5 string attribute syntax.
    */
   public static final String SYNTAX_IA5_STRING_OID =
-      "1.3.6.1.4.1.1466.115.121.1.26";
+    "1.3.6.1.4.1.1466.115.121.1.26";
 
   /**
    * The description for the integer attribute syntax.
@@ -1043,7 +979,7 @@
    * The OID for the integer attribute syntax.
    */
   public static final String SYNTAX_INTEGER_OID =
-      "1.3.6.1.4.1.1466.115.121.1.27";
+    "1.3.6.1.4.1.1466.115.121.1.27";
 
   /**
    * The description for the JPEG attribute syntax.
@@ -1058,141 +994,134 @@
   /**
    * The OID for the JPEG attribute syntax.
    */
-  public static final String SYNTAX_JPEG_OID =
-      "1.3.6.1.4.1.1466.115.121.1.28";
+  public static final String SYNTAX_JPEG_OID = "1.3.6.1.4.1.1466.115.121.1.28";
 
   /**
    * The description for the LDAP syntax description attribute syntax.
    */
   public static final String SYNTAX_LDAP_SYNTAX_DESCRIPTION =
-      "LDAP Syntax Description";
+    "LDAP Syntax Description";
 
   /**
    * The name for the LDAP syntax description attribute syntax.
    */
-  public static final String SYNTAX_LDAP_SYNTAX_NAME =
-      "LDAPSyntaxDescription";
+  public static final String SYNTAX_LDAP_SYNTAX_NAME = "LDAPSyntaxDescription";
 
   /**
    * The OID for the LDAP syntax description attribute syntax.
    */
   public static final String SYNTAX_LDAP_SYNTAX_OID =
-      "1.3.6.1.4.1.1466.115.121.1.54";
+    "1.3.6.1.4.1.1466.115.121.1.54";
 
   /**
    * The description for the matching rule description attribute syntax.
    */
   public static final String SYNTAX_MATCHING_RULE_DESCRIPTION =
-      "Matching Rule Description";
+    "Matching Rule Description";
 
   /**
    * The name for the matching rule description attribute syntax.
    */
   public static final String SYNTAX_MATCHING_RULE_NAME =
-      "MatchingRuleDescription";
+    "MatchingRuleDescription";
 
   /**
    * The OID for the matching rule description attribute syntax.
    */
   public static final String SYNTAX_MATCHING_RULE_OID =
-      "1.3.6.1.4.1.1466.115.121.1.30";
+    "1.3.6.1.4.1.1466.115.121.1.30";
 
   /**
-   * The description for the matching rule use description attribute
-   * syntax.
+   * The description for the matching rule use description attribute syntax.
    */
   public static final String SYNTAX_MATCHING_RULE_USE_DESCRIPTION =
-      "Matching Rule Use Description";
+    "Matching Rule Use Description";
 
   /**
    * The name for the matching rule use description attribute syntax.
    */
   public static final String SYNTAX_MATCHING_RULE_USE_NAME =
-      "MatchingRuleUseDescription";
+    "MatchingRuleUseDescription";
 
   /**
    * The OID for the matching rule use description attribute syntax.
    */
   public static final String SYNTAX_MATCHING_RULE_USE_OID =
-      "1.3.6.1.4.1.1466.115.121.1.31";
+    "1.3.6.1.4.1.1466.115.121.1.31";
 
   /**
    * The description for the name and optional uid attribute syntax.
    */
   public static final String SYNTAX_NAME_AND_OPTIONAL_UID_DESCRIPTION =
-      "Name and Optional UID";
+    "Name and Optional UID";
 
   /**
    * The name for the name and optional uid attribute syntax.
    */
   public static final String SYNTAX_NAME_AND_OPTIONAL_UID_NAME =
-      "NameAndOptionalUID";
+    "NameAndOptionalUID";
 
   /**
    * The OID for the name and optional uid attribute syntax.
    */
   public static final String SYNTAX_NAME_AND_OPTIONAL_UID_OID =
-      "1.3.6.1.4.1.1466.115.121.1.34";
+    "1.3.6.1.4.1.1466.115.121.1.34";
 
   /**
    * The description for the name form description attribute syntax.
    */
   public static final String SYNTAX_NAME_FORM_DESCRIPTION =
-      "Name Form Description";
+    "Name Form Description";
 
   /**
    * The name for the name form description attribute syntax.
    */
-  public static final String SYNTAX_NAME_FORM_NAME =
-      "NameFormDescription";
+  public static final String SYNTAX_NAME_FORM_NAME = "NameFormDescription";
 
   /**
    * The OID for the name form description attribute syntax.
    */
   public static final String SYNTAX_NAME_FORM_OID =
-      "1.3.6.1.4.1.1466.115.121.1.35";
+    "1.3.6.1.4.1.1466.115.121.1.35";
 
   /**
    * The description for the numeric string attribute syntax.
    */
   public static final String SYNTAX_NUMERIC_STRING_DESCRIPTION =
-      "Numeric String";
+    "Numeric String";
 
   /**
    * The name for the numeric string attribute syntax.
    */
-  public static final String SYNTAX_NUMERIC_STRING_NAME =
-      "NumericString";
+  public static final String SYNTAX_NUMERIC_STRING_NAME = "NumericString";
 
   /**
    * The OID for the numeric string attribute syntax.
    */
   public static final String SYNTAX_NUMERIC_STRING_OID =
-      "1.3.6.1.4.1.1466.115.121.1.36";
+    "1.3.6.1.4.1.1466.115.121.1.36";
 
   /**
    * The description for the object class description attribute syntax.
    */
   public static final String SYNTAX_OBJECTCLASS_DESCRIPTION =
-      "Object Class Description";
+    "Object Class Description";
 
   /**
    * The name for the object class description attribute syntax.
    */
-  public static final String SYNTAX_OBJECTCLASS_NAME =
-      "ObjectClassDescription";
+  public static final String SYNTAX_OBJECTCLASS_NAME = "ObjectClassDescription";
 
   /**
    * The OID for the object class description attribute syntax.
    */
   public static final String SYNTAX_OBJECTCLASS_OID =
-      "1.3.6.1.4.1.1466.115.121.1.37";
+    "1.3.6.1.4.1.1466.115.121.1.37";
 
   /**
    * The description for the octet string attribute syntax.
    */
-  public static final String SYNTAX_OCTET_STRING_DESCRIPTION =
-      "Octet String";
+  public static final String SYNTAX_OCTET_STRING_DESCRIPTION = "Octet String";
 
   /**
    * The name for the octet string attribute syntax.
@@ -1203,7 +1132,7 @@
    * The OID for the octet string attribute syntax.
    */
   public static final String SYNTAX_OCTET_STRING_OID =
-      "1.3.6.1.4.1.1466.115.121.1.40";
+    "1.3.6.1.4.1.1466.115.121.1.40";
 
   /**
    * The description for the object identifier attribute syntax.
@@ -1218,14 +1147,12 @@
   /**
    * The OID for the object identifier attribute syntax.
    */
-  public static final String SYNTAX_OID_OID =
-      "1.3.6.1.4.1.1466.115.121.1.38";
+  public static final String SYNTAX_OID_OID = "1.3.6.1.4.1.1466.115.121.1.38";
 
   /**
    * The description for the other mailbox attribute syntax.
    */
-  public static final String SYNTAX_OTHER_MAILBOX_DESCRIPTION =
-      "Other Mailbox";
+  public static final String SYNTAX_OTHER_MAILBOX_DESCRIPTION = "Other Mailbox";
 
   /**
    * The name for the other mailbox attribute syntax.
@@ -1236,161 +1163,156 @@
    * The OID for the other mailbox attribute syntax.
    */
   public static final String SYNTAX_OTHER_MAILBOX_OID =
-      "1.3.6.1.4.1.1466.115.121.1.39";
+    "1.3.6.1.4.1.1466.115.121.1.39";
 
   /**
    * The description for the postal address attribute syntax.
    */
   public static final String SYNTAX_POSTAL_ADDRESS_DESCRIPTION =
-      "Postal Address";
+    "Postal Address";
 
   /**
    * The name for the postal address attribute syntax.
    */
-  public static final String SYNTAX_POSTAL_ADDRESS_NAME =
-      "PostalAddress";
+  public static final String SYNTAX_POSTAL_ADDRESS_NAME = "PostalAddress";
 
   /**
    * The OID for the postal address attribute syntax.
    */
   public static final String SYNTAX_POSTAL_ADDRESS_OID =
-      "1.3.6.1.4.1.1466.115.121.1.41";
+    "1.3.6.1.4.1.1466.115.121.1.41";
 
   /**
    * The description for the presentation address attribute syntax.
    */
   public static final String SYNTAX_PRESENTATION_ADDRESS_DESCRIPTION =
-      "Presentation Address";
+    "Presentation Address";
 
   /**
    * The name for the presentation address attribute syntax.
    */
   public static final String SYNTAX_PRESENTATION_ADDRESS_NAME =
-      "PresentationAddress";
+    "PresentationAddress";
 
   /**
    * The OID for the presentation address attribute syntax.
    */
   public static final String SYNTAX_PRESENTATION_ADDRESS_OID =
-      "1.3.6.1.4.1.1466.115.121.1.43";
+    "1.3.6.1.4.1.1466.115.121.1.43";
 
   /**
    * The description for the printable string attribute syntax.
    */
   public static final String SYNTAX_PRINTABLE_STRING_DESCRIPTION =
-      "Printable String";
+    "Printable String";
 
   /**
    * The name for the printable string attribute syntax.
    */
-  public static final String SYNTAX_PRINTABLE_STRING_NAME =
-      "PrintableString";
+  public static final String SYNTAX_PRINTABLE_STRING_NAME = "PrintableString";
 
   /**
    * The OID for the printable string attribute syntax.
    */
   public static final String SYNTAX_PRINTABLE_STRING_OID =
-      "1.3.6.1.4.1.1466.115.121.1.44";
+    "1.3.6.1.4.1.1466.115.121.1.44";
 
   /**
    * The description for the protocol information attribute syntax.
    */
   public static final String SYNTAX_PROTOCOL_INFORMATION_DESCRIPTION =
-      "Protocol Information";
+    "Protocol Information";
 
   /**
    * The name for the protocol information attribute syntax.
    */
   public static final String SYNTAX_PROTOCOL_INFORMATION_NAME =
-      "ProtocolInformation";
+    "ProtocolInformation";
 
   /**
    * The OID for the protocol information attribute syntax.
    */
   public static final String SYNTAX_PROTOCOL_INFORMATION_OID =
-      "1.3.6.1.4.1.1466.115.121.1.42";
+    "1.3.6.1.4.1.1466.115.121.1.42";
 
   /**
    * The OID for the relative subtree specification attribute syntax.
    */
   public static final String SYNTAX_RELATIVE_SUBTREE_SPECIFICATION_OID =
-      OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".2";
+    OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".2";
 
   /**
-   * The description for the relative subtree specification attribute
-   * syntax.
+   * The description for the relative subtree specification attribute syntax.
    */
   public static final String SYNTAX_RELATIVE_SUBTREE_SPECIFICATION_DESCRIPTION =
-      "Relative Subtree Specification";
+    "Relative Subtree Specification";
 
   /**
    * The name for the relative subtree specification attribute syntax.
    */
   public static final String SYNTAX_RELATIVE_SUBTREE_SPECIFICATION_NAME =
-      "ds-relative-subtree-specification";
+    "ds-relative-subtree-specification";
 
   /**
    * The OID for the RFC3672 subtree specification attribute syntax.
    */
   public static final String SYNTAX_RFC3672_SUBTREE_SPECIFICATION_OID =
-      "1.3.6.1.4.1.1466.115.121.1.45";
+    "1.3.6.1.4.1.1466.115.121.1.45";
 
   /**
-   * The description for the RFC3672 subtree specification attribute
-   * syntax.
+   * The description for the RFC3672 subtree specification attribute syntax.
    */
   public static final String SYNTAX_RFC3672_SUBTREE_SPECIFICATION_DESCRIPTION =
-      "RFC3672 Subtree Specification";
+    "RFC3672 Subtree Specification";
 
   /**
    * The name for the RFC3672 subtree specification attribute syntax.
    */
   public static final String SYNTAX_RFC3672_SUBTREE_SPECIFICATION_NAME =
-      "SubtreeSpecification";
+    "SubtreeSpecification";
 
   /**
    * The description for the substring assertion attribute syntax.
    */
   public static final String SYNTAX_SUBSTRING_ASSERTION_DESCRIPTION =
-      "Substring Assertion";
+    "Substring Assertion";
 
   /**
    * The name for the substring assertion attribute syntax.
    */
   public static final String SYNTAX_SUBSTRING_ASSERTION_NAME =
-      "SubstringAssertion";
+    "SubstringAssertion";
 
   /**
-   * The OID for the Substring Assertion syntax used for assertion
-   * values in extensible match filters.
+   * The OID for the Substring Assertion syntax used for assertion values in
+   * extensible match filters.
    */
   public static final String SYNTAX_SUBSTRING_ASSERTION_OID =
-      "1.3.6.1.4.1.1466.115.121.1.58";
+    "1.3.6.1.4.1.1466.115.121.1.58";
 
   /**
    * The description for the supported algorithm attribute syntax.
    */
   public static final String SYNTAX_SUPPORTED_ALGORITHM_DESCRIPTION =
-      "Supported Algorithm";
+    "Supported Algorithm";
 
   /**
    * The name for the supported algorithm attribute syntax.
    */
   public static final String SYNTAX_SUPPORTED_ALGORITHM_NAME =
-      "SupportedAlgorithm";
+    "SupportedAlgorithm";
 
   /**
-   * The OID for the Substring Assertion syntax used for assertion
-   * values in extensible match filters.
+   * The OID for the Substring Assertion syntax used for assertion values in
+   * extensible match filters.
    */
   public static final String SYNTAX_SUPPORTED_ALGORITHM_OID =
-      "1.3.6.1.4.1.1466.115.121.1.49";
+    "1.3.6.1.4.1.1466.115.121.1.49";
 
   /**
    * The description for the telephone number attribute syntax.
    */
-  public static final String SYNTAX_TELEPHONE_DESCRIPTION =
-      "Telephone Number";
+  public static final String SYNTAX_TELEPHONE_DESCRIPTION = "Telephone Number";
 
   /**
    * The name for the telephone number attribute syntax.
@@ -1401,26 +1323,25 @@
    * The OID for the telephone number attribute syntax.
    */
   public static final String SYNTAX_TELEPHONE_OID =
-      "1.3.6.1.4.1.1466.115.121.1.50";
+    "1.3.6.1.4.1.1466.115.121.1.50";
 
   /**
-   * The description for the teletex terminal identifier attribute
-   * syntax.
+   * The description for the teletex terminal identifier attribute syntax.
    */
   public static final String SYNTAX_TELETEX_TERM_ID_DESCRIPTION =
-      "Teletex Terminal Identifier";
+    "Teletex Terminal Identifier";
 
   /**
    * The name for the teletex terminal identifier attribute syntax.
    */
   public static final String SYNTAX_TELETEX_TERM_ID_NAME =
-      "TeletexTerminalIdentifier";
+    "TeletexTerminalIdentifier";
 
   /**
    * The OID for the teletex terminal identifier attribute syntax.
    */
   public static final String SYNTAX_TELETEX_TERM_ID_OID =
-      "1.3.6.1.4.1.1466.115.121.1.51";
+    "1.3.6.1.4.1.1466.115.121.1.51";
 
   /**
    * The description for the telex number attribute syntax.
@@ -1435,26 +1356,24 @@
   /**
    * The OID for the telex number attribute syntax.
    */
-  public static final String SYNTAX_TELEX_OID =
-      "1.3.6.1.4.1.1466.115.121.1.52";
+  public static final String SYNTAX_TELEX_OID = "1.3.6.1.4.1.1466.115.121.1.52";
 
   /**
    * The description for the user password attribute syntax.
    */
-  public static final String SYNTAX_USER_PASSWORD_DESCRIPTION =
-      "User Password";
+  public static final String SYNTAX_USER_PASSWORD_DESCRIPTION = "User Password";
 
   /**
    * The name for the user password attribute syntax.
    */
   public static final String SYNTAX_USER_PASSWORD_NAME =
-      "ds-syntax-user-password";
+    "ds-syntax-user-password";
 
   /**
    * The OID for the user password attribute syntax.
    */
   public static final String SYNTAX_USER_PASSWORD_OID =
-      OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".1";
+    OID_OPENDS_SERVER_ATTRIBUTE_SYNTAX_BASE + ".1";
 
   /**
    * The description for the UTC time attribute syntax.
@@ -1470,7 +1389,7 @@
    * The OID for the UTC time attribute syntax.
    */
   public static final String SYNTAX_UTC_TIME_OID =
-      "1.3.6.1.4.1.1466.115.121.1.53";
+    "1.3.6.1.4.1.1466.115.121.1.53";
 
   /**
    * The description for the UUID attribute syntax.
@@ -1490,8 +1409,7 @@
   /**
    * The description for the "top" objectclass.
    */
-  public static final String TOP_OBJECTCLASS_DESCRIPTION =
-      "Topmost ObjectClass";
+  public static final String TOP_OBJECTCLASS_DESCRIPTION = "Topmost ObjectClass";
 
   /**
    * The name of the "top" objectclass.
@@ -1504,69 +1422,66 @@
   public static final String TOP_OBJECTCLASS_OID = "2.5.6.0";
 
   /**
-   * The name for the relative time greater-than extensible ordering
-   * matching rule.
+   * The name for the relative time greater-than extensible ordering matching
+   * rule.
    */
   public static final String EXT_OMR_RELATIVE_TIME_GT_NAME =
-      "relativeTimeGTOrderingMatch";
+    "relativeTimeGTOrderingMatch";
 
   /**
-   * The alternative name for the relative time greater-than extensible
-   * ordering matching rule.
+   * The alternative name for the relative time greater-than extensible ordering
+   * matching rule.
    */
   public static final String EXT_OMR_RELATIVE_TIME_GT_ALT_NAME =
-      "relativeTimeOrderingMatch.gt";
+    "relativeTimeOrderingMatch.gt";
 
   /**
-   * The OID for the relative time greater-than extensible ordering
-   * matching rule.
+   * The OID for the relative time greater-than extensible ordering matching
+   * rule.
    */
   public static final String EXT_OMR_RELATIVE_TIME_GT_OID =
-      "1.3.6.1.4.1.26027.1.4.5";
+    "1.3.6.1.4.1.26027.1.4.5";
 
   /**
-   * The name for the relative time less-than extensible ordering
-   * matching rule.
+   * The name for the relative time less-than extensible ordering matching rule.
    */
   public static final String EXT_OMR_RELATIVE_TIME_LT_NAME =
-      "relativeTimeLTOrderingMatch";
+    "relativeTimeLTOrderingMatch";
 
   /**
-   * The alternative name for the relative time less-than extensible
-   * ordering matching rule.
-   */
-  public static final String EXT_OMR_RELATIVE_TIME_LT_ALT_NAME =
-      "relativeTimeOrderingMatch.lt";
-
-  /**
-   * The OID for the relative time less-than extensible ordering
+   * The alternative name for the relative time less-than extensible ordering
    * matching rule.
    */
+  public static final String EXT_OMR_RELATIVE_TIME_LT_ALT_NAME =
+    "relativeTimeOrderingMatch.lt";
+
+  /**
+   * The OID for the relative time less-than extensible ordering matching rule.
+   */
   public static final String EXT_OMR_RELATIVE_TIME_LT_OID =
-      "1.3.6.1.4.1.26027.1.4.6";
+    "1.3.6.1.4.1.26027.1.4.6";
 
   /**
    * The OID for the partial date and time extensible matching rule.
    */
   public static final String EXT_PARTIAL_DATE_TIME_OID =
-      "1.3.6.1.4.1.26027.1.4.7";
+    "1.3.6.1.4.1.26027.1.4.7";
 
   /**
    * The name for the partial date and time extensible rule.
    */
   public static final String EXT_PARTIAL_DATE_TIME_NAME =
-      "partialDateAndTimeMatchingRule";
+    "partialDateAndTimeMatchingRule";
 
   /**
    * The name of the schema extension that will be used to specify the
-   * approximate matching rule that should be used for a given attribute
-   * type.
+   * approximate matching rule that should be used for a given attribute type.
    */
   public static final String SCHEMA_PROPERTY_APPROX_RULE = "X-APPROX";
 
   /**
-   * The name of the schema property that will be used to specify the
-   * origin of a schema element.
+   * The name of the schema property that will be used to specify the origin of
+   * a schema element.
    */
   public static final String SCHEMA_PROPERTY_ORIGIN = "X-ORIGIN";
 
@@ -1574,31 +1489,28 @@
    * The OID for the extensibleObject objectclass.
    */
   public static final String EXTENSIBLE_OBJECT_OBJECTCLASS_OID =
-      "1.3.6.1.4.1.1466.101.120.111";
+    "1.3.6.1.4.1.1466.101.120.111";
 
   /**
    * The name for the extensibleObject objectclass.
    */
   public static final String EXTENSIBLE_OBJECT_OBJECTCLASS_NAME =
-      "extensibleObject";
+    "extensibleObject";
 
   /**
    * The value representing just one space character.
    */
-  public static final ByteString SINGLE_SPACE_VALUE =
-      ByteString.valueOf(" ");
+  public static final ByteString SINGLE_SPACE_VALUE = ByteString.valueOf(" ");
 
   /**
    * The normalized true value.
    */
-  public static final ByteString TRUE_VALUE =
-      ByteString.valueOf("TRUE");
+  public static final ByteString TRUE_VALUE = ByteString.valueOf("TRUE");
 
   /**
    * The normalized false value.
    */
-  public static final ByteString FALSE_VALUE =
-      ByteString.valueOf("FALSE");
+  public static final ByteString FALSE_VALUE = ByteString.valueOf("FALSE");
 
   /**
    * The name of the time zone for universal coordinated time (UTC).
@@ -1606,9 +1518,9 @@
   public static final String TIME_ZONE_UTC = "UTC";
 
   /**
-   * The date format string that will be used to construct and parse
-   * dates represented using generalized time with a two-digit year. It
-   * is assumed that the provided date formatter will be set to UTC.
+   * The date format string that will be used to construct and parse dates
+   * represented using generalized time with a two-digit year. It is assumed
+   * that the provided date formatter will be set to UTC.
    */
   public static final String DATE_FORMAT_UTC_TIME = "yyMMddHHmmss'Z'";
 
diff --git a/sdk/src/org/opends/sdk/schema/SchemaElement.java b/sdk/src/org/opends/sdk/schema/SchemaElement.java
index a33727d..f428fae 100644
--- a/sdk/src/org/opends/sdk/schema/SchemaElement.java
+++ b/sdk/src/org/opends/sdk/schema/SchemaElement.java
@@ -29,8 +29,10 @@
 
 
 
+import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.opends.sdk.LocalizableMessage;
 
@@ -42,9 +44,9 @@
  * An abstract base class for LDAP schema definitions which contain an
  * description, and an optional set of extra properties.
  * <p>
- * This class defines common properties and behaviour of the various
- * types of schema definitions (e.g. object class definitions, and
- * attribute type definitions).
+ * This class defines common properties and behaviour of the various types of
+ * schema definitions (e.g. object class definitions, and attribute type
+ * definitions).
  */
 abstract class SchemaElement
 {
@@ -56,20 +58,22 @@
 
 
 
-  SchemaElement(String description,
-      Map<String, List<String>> extraProperties)
+  SchemaElement(final String description,
+      final Map<String, List<String>> extraProperties)
   {
     Validator.ensureNotNull(description, extraProperties);
     this.description = description;
+
+    // Assumes caller has made the map unmodifiable.
     this.extraProperties = extraProperties;
   }
 
 
 
   /**
-   * Retrieves the description for this schema definition.
+   * Returns the description of this schema definition.
    *
-   * @return The description for this schema definition.
+   * @return The description of this schema definition.
    */
   public final String getDescription()
   {
@@ -80,32 +84,32 @@
 
 
   /**
-   * Retrieves an iterable over the value(s) of the specified "extra"
+   * Returns an unmodifiable list containing the values of the named "extra"
    * property for this schema definition.
    *
    * @param name
-   *          The name of the "extra" property for which to retrieve the
-   *          value(s).
-   * @return Returns an iterable over the value(s) of the specified
-   *         "extra" property for this schema definition, or
-   *         <code>null</code> if no such property is defined.
+   *          The name of the "extra" property whose values are to be returned.
+   * @return Returns an unmodifiable list containing the values of the named
+   *         "extra" property for this schema definition, which may be empty if
+   *         no such property is defined.
    */
-  public final Iterable<String> getExtraProperty(String name)
+  public final List<String> getExtraProperty(final String name)
   {
 
-    return extraProperties.get(name);
+    final List<String> values = extraProperties.get(name);
+    return values != null ? values : Collections.<String> emptyList();
   }
 
 
 
   /**
-   * Retrieves an iterable over the names of "extra" properties
+   * Returns an unmodifiable set containing the names of the "extra" properties
    * associated with this schema definition.
    *
-   * @return Returns an iterable over the names of "extra" properties
-   *         associated with this schema definition.
+   * @return Returns an unmodifiable set containing the names of the "extra"
+   *         properties associated with this schema definition.
    */
-  public final Iterable<String> getExtraPropertyNames()
+  public final Set<String> getExtraPropertyNames()
   {
 
     return extraProperties.keySet();
@@ -114,11 +118,11 @@
 
 
   /**
-   * Builds a string representation of this schema definition in the
-   * form specified in RFC 2252.
+   * Builds a string representation of this schema definition in the form
+   * specified in RFC 2252.
    *
-   * @return The string representation of this schema definition in the
-   *         form specified in RFC 2252.
+   * @return The string representation of this schema definition in the form
+   *         specified in RFC 2252.
    */
   final String buildDefinition()
   {
@@ -130,8 +134,7 @@
 
     if (!extraProperties.isEmpty())
     {
-      for (final Map.Entry<String, List<String>> e : extraProperties
-          .entrySet())
+      for (final Map.Entry<String, List<String>> e : extraProperties.entrySet())
       {
 
         final String property = e.getKey();
@@ -171,8 +174,8 @@
 
 
   /**
-   * Appends a string representation of this schema definition's
-   * non-generic properties to the provided buffer.
+   * Appends a string representation of this schema definition's non-generic
+   * properties to the provided buffer.
    *
    * @param buffer
    *          The buffer to which the information should be appended.
diff --git a/sdk/src/org/opends/sdk/schema/SchemaException.java b/sdk/src/org/opends/sdk/schema/SchemaException.java
index 3accb1c..d3a7635 100644
--- a/sdk/src/org/opends/sdk/schema/SchemaException.java
+++ b/sdk/src/org/opends/sdk/schema/SchemaException.java
@@ -34,13 +34,11 @@
 
 
 
-
 /**
  * Thrown when a schema could not be decoded or validated.
  */
 @SuppressWarnings("serial")
-final class SchemaException extends Exception implements
-    LocalizableException
+final class SchemaException extends Exception implements LocalizableException
 {
   // The I18N message associated with this exception.
   private final LocalizableMessage message;
@@ -49,11 +47,11 @@
 
   /**
    * Creates a new schema exception with the provided message.
-   * 
+   *
    * @param message
    *          The message that explains the problem that occurred.
    */
-  public SchemaException(LocalizableMessage message)
+  public SchemaException(final LocalizableMessage message)
   {
     super(String.valueOf(message));
     this.message = message;
@@ -63,16 +61,15 @@
 
   /**
    * Creates a new schema exception with the provided message and cause.
-   * 
+   *
    * @param message
    *          The message that explains the problem that occurred.
    * @param cause
-   *          The cause which may be later retrieved by the
-   *          {@link #getCause} method. A {@code null} value is
-   *          permitted, and indicates that the cause is nonexistent or
-   *          unknown.
+   *          The cause which may be later retrieved by the {@link #getCause}
+   *          method. A {@code null} value is permitted, and indicates that the
+   *          cause is nonexistent or unknown.
    */
-  public SchemaException(LocalizableMessage message, Throwable cause)
+  public SchemaException(final LocalizableMessage message, final Throwable cause)
   {
     super(String.valueOf(message), cause);
     this.message = message;
diff --git a/sdk/src/org/opends/sdk/schema/SchemaUtils.java b/sdk/src/org/opends/sdk/schema/SchemaUtils.java
index 0f4b596..3730e62 100644
--- a/sdk/src/org/opends/sdk/schema/SchemaUtils.java
+++ b/sdk/src/org/opends/sdk/schema/SchemaUtils.java
@@ -29,7 +29,8 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
+import static com.sun.opends.sdk.util.StaticUtils.isAlpha;
+import static com.sun.opends.sdk.util.StaticUtils.isDigit;
 
 import java.util.*;
 
@@ -46,11 +47,10 @@
 final class SchemaUtils
 {
   /**
-   * Reads the value for an "extra" parameter. It will handle a single
-   * unquoted word (which is technically illegal, but we'll allow it), a
-   * single quoted string, or an open parenthesis followed by a
-   * space-delimited set of quoted strings or unquoted words followed by
-   * a close parenthesis.
+   * Reads the value for an "extra" parameter. It will handle a single unquoted
+   * word (which is technically illegal, but we'll allow it), a single quoted
+   * string, or an open parenthesis followed by a space-delimited set of quoted
+   * strings or unquoted words followed by a close parenthesis.
    *
    * @param reader
    *          The string representation of the definition.
@@ -58,7 +58,7 @@
    * @throws DecodeException
    *           If a problem occurs while attempting to read the value.
    */
-  static List<String> readExtensions(SubstringReader reader)
+  static List<String> readExtensions(final SubstringReader reader)
       throws DecodeException
   {
     int length = 0;
@@ -108,7 +108,9 @@
             values.add(readQuotedString(reader));
             reader.skipWhitespaces();
             reader.mark();
-          } while (reader.read() != ')');
+          }
+          while (reader.read() != ')');
+          values = Collections.unmodifiableList(values);
         }
       }
       else
@@ -117,7 +119,8 @@
         do
         {
           length++;
-        } while (reader.read() != ' ');
+        }
+        while (reader.read() != ' ');
 
         reader.reset();
         values = Collections.singletonList(reader.read(length));
@@ -127,15 +130,14 @@
     }
     catch (final StringIndexOutOfBoundsException e)
     {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE
-          .get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE.get();
       throw DecodeException.error(message);
     }
   }
 
 
 
-  static List<String> readNameDescriptors(SubstringReader reader)
+  static List<String> readNameDescriptors(final SubstringReader reader)
       throws DecodeException
   {
     int length = 0;
@@ -180,7 +182,9 @@
             values.add(readQuotedDescriptor(reader));
             reader.skipWhitespaces();
             reader.mark();
-          } while (reader.read() != ')');
+          }
+          while (reader.read() != ')');
+          values = Collections.unmodifiableList(values);
         }
       }
       else
@@ -194,8 +198,7 @@
     }
     catch (final StringIndexOutOfBoundsException e)
     {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE
-          .get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE.get();
       throw DecodeException.error(message);
     }
   }
@@ -203,18 +206,16 @@
 
 
   /**
-   * Reads the attribute description or numeric OID, skipping over any
-   * leading or trailing spaces.
+   * Reads the attribute description or numeric OID, skipping over any leading
+   * or trailing spaces.
    *
    * @param reader
    *          The string representation of the definition.
-   * @return The attribute description or numeric OID read from the
-   *         definition.
+   * @return The attribute description or numeric OID read from the definition.
    * @throws DecodeException
-   *           If a problem is encountered while reading the name or
-   *           OID.
+   *           If a problem is encountered while reading the name or OID.
    */
-  static String readOID(SubstringReader reader) throws DecodeException
+  static String readOID(final SubstringReader reader) throws DecodeException
   {
     int length = 0;
     boolean enclosingQuote = false;
@@ -249,8 +250,8 @@
         // only digits and periods, but not consecutive periods.
         boolean lastWasPeriod = false;
 
-        while (reader.remaining() > 0 && (c = reader.read()) != ' '
-            && c != ')' && !(c == '\'' && enclosingQuote))
+        while (reader.remaining() > 0 && (c = reader.read()) != ' ' && c != ')'
+            && !(c == '\'' && enclosingQuote))
         {
           if (c == '.')
           {
@@ -293,8 +294,8 @@
         // This must be an attribute description. In this case, we will
         // only accept alphabetic characters, numeric digits, and the
         // hyphen.
-        while (reader.remaining() > 0 && (c = reader.read()) != ' '
-            && c != ')' && !(c == '\'' && enclosingQuote))
+        while (reader.remaining() > 0 && (c = reader.read()) != ' ' && c != ')'
+            && !(c == '\'' && enclosingQuote))
         {
           if (length == 0 && !isAlpha(c))
           {
@@ -304,8 +305,7 @@
             throw DecodeException.error(message);
           }
 
-          if (!isAlpha(c) && !isDigit(c) && c != '-' && c != '.'
-              && c != '_')
+          if (!isAlpha(c) && !isDigit(c) && c != '-' && c != '.' && c != '_')
           {
             // This is an illegal character.
             final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_CHAR_IN_STRING_OID
@@ -333,13 +333,12 @@
 
     if (length == 0)
     {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_OID_NO_VALUE
-          .get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_OID_NO_VALUE.get();
       throw DecodeException.error(message);
     }
 
     reader.reset();
-    String oid = reader.read(length);
+    final String oid = reader.read(length);
     if (enclosingQuote)
     {
       reader.read();
@@ -351,8 +350,8 @@
 
 
   /**
-   * Reads the next OID from the definition, skipping over any leading
-   * spaces. The OID may be followed by a integer length in brackets.
+   * Reads the next OID from the definition, skipping over any leading spaces.
+   * The OID may be followed by a integer length in brackets.
    *
    * @param reader
    *          The string representation of the definition.
@@ -360,8 +359,7 @@
    * @throws DecodeException
    *           If a problem is encountered while reading the token name.
    */
-  static String readOIDLen(SubstringReader reader)
-      throws DecodeException
+  static String readOIDLen(final SubstringReader reader) throws DecodeException
   {
     int length = 1;
     boolean enclosingQuote = false;
@@ -426,8 +424,7 @@
 
         if (length == 0)
         {
-          final LocalizableMessage message = ERR_ATTR_SYNTAX_OID_NO_VALUE
-              .get();
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_OID_NO_VALUE.get();
           throw DecodeException.error(message);
         }
       }
@@ -448,8 +445,7 @@
             throw DecodeException.error(message);
           }
 
-          if (!isAlpha(c) && !isDigit(c) && c != '-' && c != '.'
-              && c != '_')
+          if (!isAlpha(c) && !isDigit(c) && c != '-' && c != '.' && c != '_')
           {
             // This is an illegal character.
             final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_CHAR_IN_STRING_OID
@@ -502,15 +498,14 @@
     }
     catch (final StringIndexOutOfBoundsException e)
     {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE
-          .get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE.get();
       throw DecodeException.error(message);
     }
   }
 
 
 
-  static Set<String> readOIDs(SubstringReader reader)
+  static Set<String> readOIDs(final SubstringReader reader)
       throws DecodeException
   {
     Set<String> values;
@@ -524,15 +519,16 @@
       final char c = reader.read();
       if (c == '(')
       {
-        values = new HashSet<String>();
-
+        values = new LinkedHashSet<String>();
         do
         {
           values.add(readOID(reader));
 
           // Skip over any trailing spaces;
           reader.skipWhitespaces();
-        } while (reader.read() != ')');
+        }
+        while (reader.read() != ')');
+        values = Collections.unmodifiableSet(values);
       }
       else
       {
@@ -544,8 +540,7 @@
     }
     catch (final StringIndexOutOfBoundsException e)
     {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE
-          .get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE.get();
       throw DecodeException.error(message);
     }
   }
@@ -553,87 +548,16 @@
 
 
   /**
-   * Reads the value of a string enclosed in single quotes, skipping
-   * over the quotes and any leading spaces.
+   * Reads the value of a string enclosed in single quotes, skipping over the
+   * quotes and any leading spaces.
    *
    * @param reader
    *          The string representation of the definition.
    * @return The string value read from the definition.
    * @throws DecodeException
-   *           If a problem is encountered while reading the quoted
-   *           string.
+   *           If a problem is encountered while reading the quoted string.
    */
-  private static String readQuotedDescriptor(SubstringReader reader)
-      throws DecodeException
-  {
-    int length = 0;
-
-    // Skip over any spaces at the beginning of the value.
-    reader.skipWhitespaces();
-
-    try
-    {
-      // The next character must be a single quote.
-      char c = reader.read();
-      if (c != '\'')
-      {
-        final LocalizableMessage message = ERR_ATTR_SYNTAX_EXPECTED_QUOTE_AT_POS
-            .get(reader.pos() - 1, String.valueOf(c));
-        throw DecodeException.error(message);
-      }
-
-      // Read until we find the closing quote.
-      reader.mark();
-      while ((c = reader.read()) != '\'')
-      {
-        if (length == 0 && !isAlpha(c))
-        {
-          // This is an illegal character.
-          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_CHAR_IN_STRING_OID
-              .get(String.valueOf(c), reader.pos() - 1);
-          throw DecodeException.error(message);
-        }
-
-        if (!isAlpha(c) && !isDigit(c) && c != '-' && c != '_'
-            && c != '.')
-        {
-          // This is an illegal character.
-          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_CHAR_IN_STRING_OID
-              .get(String.valueOf(c), reader.pos() - 1);
-          throw DecodeException.error(message);
-        }
-
-        length++;
-      }
-
-      reader.reset();
-
-      final String descr = reader.read(length);
-      reader.read();
-      return descr;
-    }
-    catch (final StringIndexOutOfBoundsException e)
-    {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE
-          .get();
-      throw DecodeException.error(message);
-    }
-  }
-
-
-
-  /**
-   * Reads the value of a string enclosed in single quotes, skipping
-   * over the quotes and any leading spaces.
-   *
-   * @param reader
-   *          The string representation of the definition.
-   * @return The string value read from the definition.
-   * @throws DecodeException
-   *           If a problem is encountered while reading the quoted
-   *           string.
-   */
-  static String readQuotedString(SubstringReader reader)
+  static String readQuotedString(final SubstringReader reader)
       throws DecodeException
   {
     int length = 0;
@@ -667,8 +591,7 @@
     }
     catch (final StringIndexOutOfBoundsException e)
     {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE
-          .get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE.get();
       throw DecodeException.error(message);
     }
   }
@@ -676,8 +599,8 @@
 
 
   /**
-   * Reads the next ruleid from the definition, skipping over any
-   * leading spaces.
+   * Reads the next ruleid from the definition, skipping over any leading
+   * spaces.
    *
    * @param reader
    *          The string representation of the definition.
@@ -685,7 +608,7 @@
    * @throws DecodeException
    *           If a problem is encountered while reading the token name.
    */
-  static Integer readRuleID(SubstringReader reader)
+  static Integer readRuleID(final SubstringReader reader)
       throws DecodeException
   {
     // This must be a ruleid. In that case, we will accept
@@ -726,15 +649,14 @@
     }
     catch (final StringIndexOutOfBoundsException e)
     {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE
-          .get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE.get();
       throw DecodeException.error(message);
     }
   }
 
 
 
-  static Set<Integer> readRuleIDs(SubstringReader reader)
+  static Set<Integer> readRuleIDs(final SubstringReader reader)
       throws DecodeException
   {
     Set<Integer> values;
@@ -748,15 +670,16 @@
       final char c = reader.read();
       if (c == '(')
       {
-        values = new HashSet<Integer>();
-
+        values = new LinkedHashSet<Integer>();
         do
         {
           values.add(readRuleID(reader));
 
           // Skip over any trailing spaces;
           reader.skipWhitespaces();
-        } while (reader.read() != ')');
+        }
+        while (reader.read() != ')');
+        values = Collections.unmodifiableSet(values);
       }
       else
       {
@@ -768,8 +691,7 @@
     }
     catch (final StringIndexOutOfBoundsException e)
     {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE
-          .get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE.get();
       throw DecodeException.error(message);
     }
   }
@@ -777,18 +699,16 @@
 
 
   /**
-   * Reads the next token name from the definition, skipping over any
-   * leading or trailing spaces or <code>null</code> if there are no
-   * more tokens to read.
+   * Reads the next token name from the definition, skipping over any leading or
+   * trailing spaces or <code>null</code> if there are no more tokens to read.
    *
    * @param reader
    *          The string representation of the definition.
-   * @return The token name read from the definition or
-   *         <code>null</code> .
+   * @return The token name read from the definition or <code>null</code> .
    * @throws DecodeException
    *           If a problem is encountered while reading the token name.
    */
-  static String readTokenName(SubstringReader reader)
+  static String readTokenName(final SubstringReader reader)
       throws DecodeException
   {
     String token = null;
@@ -827,8 +747,142 @@
     }
     catch (final StringIndexOutOfBoundsException e)
     {
-      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE
-          .get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE.get();
+      throw DecodeException.error(message);
+    }
+  }
+
+
+
+  /**
+   * Returns an unmodifiable copy of the provided schema element extra
+   * properties.
+   *
+   * @param extraProperties
+   *          The schema element extra properties.
+   * @return An unmodifiable copy of the provided schema element extra
+   *         properties.
+   */
+  static Map<String, List<String>> unmodifiableCopyOfExtraProperties(
+      final Map<String, List<String>> extraProperties)
+  {
+    if (extraProperties == null || extraProperties.isEmpty())
+    {
+      return Collections.emptyMap();
+    }
+    else
+    {
+      final Map<String, List<String>> tmp = new LinkedHashMap<String, List<String>>(
+          extraProperties.size());
+      for (final Map.Entry<String, List<String>> e : extraProperties.entrySet())
+      {
+        tmp.put(e.getKey(), unmodifiableCopyOfList(e.getValue()));
+      }
+      return Collections.unmodifiableMap(tmp);
+    }
+  }
+
+
+
+  static <E> List<E> unmodifiableCopyOfList(final List<E> l)
+  {
+    if (l == null || l.isEmpty())
+    {
+      return Collections.emptyList();
+    }
+    else if (l.size() == 1)
+    {
+      return Collections.singletonList(l.get(0));
+    }
+    else
+    {
+      final List<E> copy = new LinkedList<E>(l);
+      return Collections.unmodifiableList(copy);
+    }
+  }
+
+
+
+  static <E> Set<E> unmodifiableCopyOfSet(final Set<E> s)
+  {
+    if (s == null || s.isEmpty())
+    {
+      return Collections.emptySet();
+    }
+    else if (s.size() == 1)
+    {
+      return Collections.singleton(s.iterator().next());
+    }
+    else
+    {
+      final Set<E> copy = new LinkedHashSet<E>(s);
+      return Collections.unmodifiableSet(copy);
+    }
+  }
+
+
+
+  /**
+   * Reads the value of a string enclosed in single quotes, skipping over the
+   * quotes and any leading spaces.
+   *
+   * @param reader
+   *          The string representation of the definition.
+   * @return The string value read from the definition.
+   * @throws DecodeException
+   *           If a problem is encountered while reading the quoted string.
+   */
+  private static String readQuotedDescriptor(final SubstringReader reader)
+      throws DecodeException
+  {
+    int length = 0;
+
+    // Skip over any spaces at the beginning of the value.
+    reader.skipWhitespaces();
+
+    try
+    {
+      // The next character must be a single quote.
+      char c = reader.read();
+      if (c != '\'')
+      {
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_EXPECTED_QUOTE_AT_POS
+            .get(reader.pos() - 1, String.valueOf(c));
+        throw DecodeException.error(message);
+      }
+
+      // Read until we find the closing quote.
+      reader.mark();
+      while ((c = reader.read()) != '\'')
+      {
+        if (length == 0 && !isAlpha(c))
+        {
+          // This is an illegal character.
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_CHAR_IN_STRING_OID
+              .get(String.valueOf(c), reader.pos() - 1);
+          throw DecodeException.error(message);
+        }
+
+        if (!isAlpha(c) && !isDigit(c) && c != '-' && c != '_' && c != '.')
+        {
+          // This is an illegal character.
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_ILLEGAL_CHAR_IN_STRING_OID
+              .get(String.valueOf(c), reader.pos() - 1);
+          throw DecodeException.error(message);
+        }
+
+        length++;
+      }
+
+      reader.reset();
+
+      final String descr = reader.read(length);
+      reader.read();
+      return descr;
+    }
+    catch (final StringIndexOutOfBoundsException e)
+    {
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_TRUNCATED_VALUE.get();
       throw DecodeException.error(message);
     }
   }
@@ -840,4 +894,5 @@
   {
     // Nothing to do.
   }
+
 }
diff --git a/sdk/src/org/opends/sdk/schema/SubstringAssertionSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/SubstringAssertionSyntaxImpl.java
index 99c8e01..fb58f58 100644
--- a/sdk/src/org/opends/sdk/schema/SubstringAssertionSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/SubstringAssertionSyntaxImpl.java
@@ -29,7 +29,10 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_SUBSTRING_ASSERTION_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
@@ -39,11 +42,10 @@
 
 
 /**
- * This class defines the substring assertion attribute syntax, which
- * contains one or more substring components, as used in a substring
- * search filter. For the purposes of matching, it will be treated like
- * a Directory String syntax except that approximate matching will not
- * be allowed.
+ * This class defines the substring assertion attribute syntax, which contains
+ * one or more substring components, as used in a substring search filter. For
+ * the purposes of matching, it will be treated like a Directory String syntax
+ * except that approximate matching will not be allowed.
  */
 final class SubstringAssertionSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -87,21 +89,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // Get the string representation of the value and check its length.
     // A zero-length value is acceptable. A one-length value is
@@ -117,9 +119,8 @@
     {
       if (valueString.charAt(0) == '*')
       {
-        invalidReason
-            .append(Messages.WARN_ATTR_SYNTAX_SUBSTRING_ONLY_WILDCARD
-                .get());
+        invalidReason.append(Messages.WARN_ATTR_SYNTAX_SUBSTRING_ONLY_WILDCARD
+            .get());
 
         return false;
       }
@@ -132,8 +133,7 @@
     {
       for (int i = 1; i < valueLength; i++)
       {
-        if (valueString.charAt(i) == '*'
-            && valueString.charAt(i - 1) == '*')
+        if (valueString.charAt(i) == '*' && valueString.charAt(i - 1) == '*')
         {
           invalidReason
               .append(Messages.WARN_ATTR_SYNTAX_SUBSTRING_CONSECUTIVE_WILDCARDS
diff --git a/sdk/src/org/opends/sdk/schema/SupportedAlgorithmSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/SupportedAlgorithmSyntaxImpl.java
index 2519568..f7ab726 100644
--- a/sdk/src/org/opends/sdk/schema/SupportedAlgorithmSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/SupportedAlgorithmSyntaxImpl.java
@@ -29,19 +29,20 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_OCTET_STRING_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_SUPPORTED_ALGORITHM_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the supported algorithm attribute syntax. This
- * should be restricted to holding only X.509 supported algorithms, but
- * we will accept any set of bytes. It will be treated much like the
- * octet string attribute syntax.
+ * This class implements the supported algorithm attribute syntax. This should
+ * be restricted to holding only X.509 supported algorithms, but we will accept
+ * any set of bytes. It will be treated much like the octet string attribute
+ * syntax.
  */
 final class SupportedAlgorithmSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -85,21 +86,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // All values will be acceptable for the supported algorithm syntax.
     return true;
diff --git a/sdk/src/org/opends/sdk/schema/Syntax.java b/sdk/src/org/opends/sdk/schema/Syntax.java
index b96df7b..ae6ec48 100644
--- a/sdk/src/org/opends/sdk/schema/Syntax.java
+++ b/sdk/src/org/opends/sdk/schema/Syntax.java
@@ -46,18 +46,17 @@
 
 
 /**
- * This class defines a data structure for storing and interacting with
- * an LDAP syntaxes, which constrain the structure of attribute values
- * stored in an LDAP directory, and determine the representation of
- * attribute and assertion values transferred in the LDAP protocol.
+ * This class defines a data structure for storing and interacting with an LDAP
+ * syntaxes, which constrain the structure of attribute values stored in an LDAP
+ * directory, and determine the representation of attribute and assertion values
+ * transferred in the LDAP protocol.
  * <p>
- * Syntax implementations must extend the
- * <code>SyntaxImplementation</code> class so they can be used by OpenDS
- * to validate attribute values.
+ * Syntax implementations must extend the {@link SyntaxImpl} interface so they
+ * can be used by OpenDS to validate attribute values.
  * <p>
- * Where ordered sets of names, or extra properties are provided, the
- * ordering will be preserved when the associated fields are accessed
- * via their getters or via the {@link #toString()} methods.
+ * Where ordered sets of names, or extra properties are provided, the ordering
+ * will be preserved when the associated fields are accessed via their getters
+ * or via the {@link #toString()} methods.
  */
 public final class Syntax extends SchemaElement
 {
@@ -72,9 +71,22 @@
 
 
 
-  Syntax(String oid, String description,
-      Map<String, List<String>> extraProperties, String definition,
-      SyntaxImpl implementation)
+  Syntax(final String oid)
+  {
+    super("", Collections.singletonMap("X-SUBST", Collections
+        .singletonList(Schema.getDefaultSyntax().getOID())));
+
+    Validator.ensureNotNull(oid);
+    this.oid = oid;
+    this.definition = buildDefinition();
+    this.impl = Schema.getDefaultSyntax().impl;
+  }
+
+
+
+  Syntax(final String oid, final String description,
+      final Map<String, List<String>> extraProperties, final String definition,
+      final SyntaxImpl implementation)
   {
     super(description, extraProperties);
 
@@ -92,26 +104,15 @@
     this.impl = implementation;
   }
 
-  Syntax(String oid)
-  {
-    super("", Collections.singletonMap("X-SUBST",
-        Collections.singletonList(Schema.getDefaultSyntax().getOID())));
-
-    Validator.ensureNotNull(oid);
-    this.oid = oid;
-    this.definition = buildDefinition();
-    this.impl = Schema.getDefaultSyntax().impl;
-  }
-
 
 
   /**
-   * Retrieves the default approximate matching rule that will be used
-   * for attributes with this syntax.
+   * Retrieves the default approximate matching rule that will be used for
+   * attributes with this syntax.
    *
    * @return The default approximate matching rule that will be used for
-   *         attributes with this syntax, or {@code null} if approximate
-   *         matches will not be allowed for this type by default.
+   *         attributes with this syntax, or {@code null} if approximate matches
+   *         will not be allowed for this type by default.
    */
   public MatchingRule getApproximateMatchingRule()
   {
@@ -124,9 +125,9 @@
    * Retrieves the default equality matching rule that will be used for
    * attributes with this syntax.
    *
-   * @return The default equality matching rule that will be used for
-   *         attributes with this syntax, or {@code null} if equality
-   *         matches will not be allowed for this type by default.
+   * @return The default equality matching rule that will be used for attributes
+   *         with this syntax, or {@code null} if equality matches will not be
+   *         allowed for this type by default.
    */
   public MatchingRule getEqualityMatchingRule()
   {
@@ -151,9 +152,9 @@
    * Retrieves the default ordering matching rule that will be used for
    * attributes with this syntax.
    *
-   * @return The default ordering matching rule that will be used for
-   *         attributes with this syntax, or {@code null} if ordering
-   *         matches will not be allowed for this type by default.
+   * @return The default ordering matching rule that will be used for attributes
+   *         with this syntax, or {@code null} if ordering matches will not be
+   *         allowed for this type by default.
    */
   public MatchingRule getOrderingMatchingRule()
   {
@@ -167,8 +168,8 @@
    * attributes with this syntax.
    *
    * @return The default substring matching rule that will be used for
-   *         attributes with this syntax, or {@code null} if substring
-   *         matches will not be allowed for this type by default.
+   *         attributes with this syntax, or {@code null} if substring matches
+   *         will not be allowed for this type by default.
    */
   public MatchingRule getSubstringMatchingRule()
   {
@@ -178,8 +179,8 @@
 
 
   /**
-   * Retrieves the hash code for this schema element. It will be
-   * calculated as the sum of the characters in the OID.
+   * Retrieves the hash code for this schema element. It will be calculated as
+   * the sum of the characters in the OID.
    *
    * @return The hash code for this attribute syntax.
    */
@@ -192,17 +193,15 @@
 
 
   /**
-   * Indicates whether this attribute syntax requires that values must
-   * be encoded using the Basic Encoding Rules (BER) used by X.500
-   * directories and always include the {@code binary} attribute
-   * description option.
+   * Indicates whether this attribute syntax requires that values must be
+   * encoded using the Basic Encoding Rules (BER) used by X.500 directories and
+   * always include the {@code binary} attribute description option.
    *
-   * @return {@code true} this attribute syntax requires that values
-   *         must be BER encoded and always include the {@code binary}
-   *         attribute description option, or {@code false} if not.
-   * @see <a href="http://tools.ietf.org/html/rfc4522">RFC 4522 -
-   *      Lightweight Directory Access Protocol (LDAP): The Binary
-   *      Encoding Option </a>
+   * @return {@code true} this attribute syntax requires that values must be BER
+   *         encoded and always include the {@code binary} attribute description
+   *         option, or {@code false} if not.
+   * @see <a href="http://tools.ietf.org/html/rfc4522">RFC 4522 - Lightweight
+   *      Directory Access Protocol (LDAP): The Binary Encoding Option </a>
    */
   public boolean isBEREncodingRequired()
   {
@@ -212,11 +211,11 @@
 
 
   /**
-   * Indicates whether this attribute syntax would likely be a human
-   * readable string.
+   * Indicates whether this attribute syntax would likely be a human readable
+   * string.
    *
-   * @return {@code true} if this attribute syntax would likely be a
-   *         human readable string or {@code false} if not.
+   * @return {@code true} if this attribute syntax would likely be a human
+   *         readable string or {@code false} if not.
    */
   public boolean isHumanReadable()
   {
@@ -226,11 +225,11 @@
 
 
   /**
-   * Retrieves a string representation of this attribute syntax in the
-   * format defined in RFC 2252.
+   * Retrieves a string representation of this attribute syntax in the format
+   * defined in RFC 2252.
    *
-   * @return A string representation of this attribute syntax in the
-   *         format defined in RFC 2252.
+   * @return A string representation of this attribute syntax in the format
+   *         defined in RFC 2252.
    */
   @Override
   public String toString()
@@ -241,19 +240,19 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
    *
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return {@code true} if the provided value is acceptable for use
-   *         with this syntax, or {@code false} if not.
+   * @return {@code true} if the provided value is acceptable for use with this
+   *         syntax, or {@code false} if not.
    */
-  public boolean valueIsAcceptable(ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final ByteSequence value,
+      final LocalizableMessageBuilder invalidReason)
   {
     return impl.valueIsAcceptable(schema, value, invalidReason);
   }
@@ -262,14 +261,13 @@
 
   Syntax duplicate()
   {
-    return new Syntax(oid, description, extraProperties, definition,
-        impl);
+    return new Syntax(oid, description, extraProperties, definition, impl);
   }
 
 
 
   @Override
-  void toStringContent(StringBuilder buffer)
+  void toStringContent(final StringBuilder buffer)
   {
     buffer.append(oid);
 
@@ -284,7 +282,7 @@
 
 
   @Override
-  void validate(List<LocalizableMessage> warnings, Schema schema)
+  void validate(final List<LocalizableMessage> warnings, final Schema schema)
       throws SchemaException
   {
     this.schema = schema;
@@ -298,25 +296,24 @@
         if (property.getKey().equalsIgnoreCase("x-subst"))
         {
           /**
-           * One unimplemented syntax can be substituted by another
-           * defined syntax. A substitution syntax is an
-           * LDAPSyntaxDescriptionSyntax with X-SUBST extension.
+           * One unimplemented syntax can be substituted by another defined
+           * syntax. A substitution syntax is an LDAPSyntaxDescriptionSyntax
+           * with X-SUBST extension.
            */
-          final Iterator<String> values =
-              property.getValue().iterator();
+          final Iterator<String> values = property.getValue().iterator();
           if (values.hasNext())
           {
             final String value = values.next();
             if (value.equals(oid))
             {
-              final LocalizableMessage message =
-                  ERR_ATTR_SYNTAX_CYCLIC_SUB_SYNTAX.get(oid);
+              final LocalizableMessage message = ERR_ATTR_SYNTAX_CYCLIC_SUB_SYNTAX
+                  .get(oid);
               throw new SchemaException(message);
             }
             if (!schema.hasSyntax(value))
             {
-              final LocalizableMessage message =
-                  ERR_ATTR_SYNTAX_UNKNOWN_SUB_SYNTAX.get(oid, value);
+              final LocalizableMessage message = ERR_ATTR_SYNTAX_UNKNOWN_SUB_SYNTAX
+                  .get(oid, value);
               throw new SchemaException(message);
             }
             final Syntax subSyntax = schema.getSyntax(value);
@@ -330,8 +327,7 @@
         }
         else if (property.getKey().equalsIgnoreCase("x-pattern"))
         {
-          final Iterator<String> values =
-              property.getValue().iterator();
+          final Iterator<String> values = property.getValue().iterator();
           if (values.hasNext())
           {
             final String value = values.next();
@@ -342,9 +338,8 @@
             }
             catch (final Exception e)
             {
-              final LocalizableMessage message =
-                  WARN_ATTR_SYNTAX_LDAPSYNTAX_REGEX_INVALID_PATTERN
-                      .get(oid, value);
+              final LocalizableMessage message = WARN_ATTR_SYNTAX_LDAPSYNTAX_REGEX_INVALID_PATTERN
+                  .get(oid, value);
               throw new SchemaException(message);
             }
           }
@@ -364,9 +359,8 @@
       if (impl == null)
       {
         impl = Schema.getDefaultSyntax().impl;
-        final LocalizableMessage message =
-            WARN_ATTR_SYNTAX_NOT_IMPLEMENTED.get(oid, Schema
-                .getDefaultSyntax().getOID());
+        final LocalizableMessage message = WARN_ATTR_SYNTAX_NOT_IMPLEMENTED
+            .get(oid, Schema.getDefaultSyntax().getOID());
         warnings.add(message);
       }
     }
@@ -377,14 +371,13 @@
     {
       if (schema.hasMatchingRule(impl.getEqualityMatchingRule()))
       {
-        equalityMatchingRule =
-            schema.getMatchingRule(impl.getEqualityMatchingRule());
+        equalityMatchingRule = schema.getMatchingRule(impl
+            .getEqualityMatchingRule());
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE.get(impl
-                .getEqualityMatchingRule(), impl.getName());
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UNKNOWN_EQUALITY_MATCHING_RULE
+            .get(impl.getEqualityMatchingRule(), impl.getName());
         warnings.add(message);
       }
     }
@@ -393,14 +386,13 @@
     {
       if (schema.hasMatchingRule(impl.getOrderingMatchingRule()))
       {
-        orderingMatchingRule =
-            schema.getMatchingRule(impl.getOrderingMatchingRule());
+        orderingMatchingRule = schema.getMatchingRule(impl
+            .getOrderingMatchingRule());
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE.get(impl
-                .getOrderingMatchingRule(), impl.getName());
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UNKNOWN_ORDERING_MATCHING_RULE
+            .get(impl.getOrderingMatchingRule(), impl.getName());
         warnings.add(message);
       }
     }
@@ -409,14 +401,13 @@
     {
       if (schema.hasMatchingRule(impl.getSubstringMatchingRule()))
       {
-        substringMatchingRule =
-            schema.getMatchingRule(impl.getSubstringMatchingRule());
+        substringMatchingRule = schema.getMatchingRule(impl
+            .getSubstringMatchingRule());
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE.get(impl
-                .getSubstringMatchingRule(), impl.getName());
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UNKNOWN_SUBSTRING_MATCHING_RULE
+            .get(impl.getSubstringMatchingRule(), impl.getName());
         warnings.add(message);
       }
     }
@@ -425,14 +416,13 @@
     {
       if (schema.hasMatchingRule(impl.getApproximateMatchingRule()))
       {
-        approximateMatchingRule =
-            schema.getMatchingRule(impl.getApproximateMatchingRule());
+        approximateMatchingRule = schema.getMatchingRule(impl
+            .getApproximateMatchingRule());
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UNKNOWN_APPROXIMATE_MATCHING_RULE.get(impl
-                .getApproximateMatchingRule(), impl.getName());
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UNKNOWN_APPROXIMATE_MATCHING_RULE
+            .get(impl.getApproximateMatchingRule(), impl.getName());
         warnings.add(message);
       }
     }
diff --git a/sdk/src/org/opends/sdk/schema/SyntaxImpl.java b/sdk/src/org/opends/sdk/schema/SyntaxImpl.java
index 65667f6..4997c32 100644
--- a/sdk/src/org/opends/sdk/schema/SyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/SyntaxImpl.java
@@ -34,20 +34,19 @@
 
 
 
-
 /**
- * This class defines the set of methods and structures that must be
+ * This interface defines the set of methods and structures that must be
  * implemented to define a new attribute syntax.
  */
 public interface SyntaxImpl
 {
   /**
-   * Retrieves the default approximate matching rule that will be used
-   * for attributes with this syntax.
-   * 
+   * Retrieves the default approximate matching rule that will be used for
+   * attributes with this syntax.
+   *
    * @return The default approximate matching rule that will be used for
-   *         attributes with this syntax, or {@code null} if approximate
-   *         matches will not be allowed for this type by default.
+   *         attributes with this syntax, or {@code null} if approximate matches
+   *         will not be allowed for this type by default.
    */
   public String getApproximateMatchingRule();
 
@@ -56,10 +55,10 @@
   /**
    * Retrieves the default equality matching rule that will be used for
    * attributes with this syntax.
-   * 
-   * @return The default equality matching rule that will be used for
-   *         attributes with this syntax, or {@code null} if equality
-   *         matches will not be allowed for this type by default.
+   *
+   * @return The default equality matching rule that will be used for attributes
+   *         with this syntax, or {@code null} if equality matches will not be
+   *         allowed for this type by default.
    */
   public String getEqualityMatchingRule();
 
@@ -67,7 +66,7 @@
 
   /**
    * Retrieves the common name for this attribute syntax.
-   * 
+   *
    * @return The common name for this attribute syntax.
    */
   public String getName();
@@ -77,10 +76,10 @@
   /**
    * Retrieves the default ordering matching rule that will be used for
    * attributes with this syntax.
-   * 
-   * @return The default ordering matching rule that will be used for
-   *         attributes with this syntax, or {@code null} if ordering
-   *         matches will not be allowed for this type by default.
+   *
+   * @return The default ordering matching rule that will be used for attributes
+   *         with this syntax, or {@code null} if ordering matches will not be
+   *         allowed for this type by default.
    */
   public String getOrderingMatchingRule();
 
@@ -89,56 +88,54 @@
   /**
    * Retrieves the default substring matching rule that will be used for
    * attributes with this syntax.
-   * 
+   *
    * @return The default substring matching rule that will be used for
-   *         attributes with this syntax, or {@code null} if substring
-   *         matches will not be allowed for this type by default.
+   *         attributes with this syntax, or {@code null} if substring matches
+   *         will not be allowed for this type by default.
    */
   public String getSubstringMatchingRule();
 
 
 
   /**
-   * Indicates whether this attribute syntax requires that values must
-   * be encoded using the Basic Encoding Rules (BER) used by X.500
-   * directories and always include the {@code binary} attribute
-   * description option.
-   * 
-   * @return {@code true} this attribute syntax requires that values
-   *         must be BER encoded and always include the {@code binary}
-   *         attribute description option, or {@code false} if not.
-   * @see <a href="http://tools.ietf.org/html/rfc4522">RFC 4522 -
-   *      Lightweight Directory Access Protocol (LDAP): The Binary
-   *      Encoding Option </a>
+   * Indicates whether this attribute syntax requires that values must be
+   * encoded using the Basic Encoding Rules (BER) used by X.500 directories and
+   * always include the {@code binary} attribute description option.
+   *
+   * @return {@code true} this attribute syntax requires that values must be BER
+   *         encoded and always include the {@code binary} attribute description
+   *         option, or {@code false} if not.
+   * @see <a href="http://tools.ietf.org/html/rfc4522">RFC 4522 - Lightweight
+   *      Directory Access Protocol (LDAP): The Binary Encoding Option </a>
    */
   public boolean isBEREncodingRequired();
 
 
 
   /**
-   * Indicates whether this attribute syntax would likely be a human
-   * readable string.
-   * 
-   * @return {@code true} if this attribute syntax would likely be a
-   *         human readable string or {@code false} if not.
+   * Indicates whether this attribute syntax would likely be a human readable
+   * string.
+   *
+   * @return {@code true} if this attribute syntax would likely be a human
+   *         readable string or {@code false} if not.
    */
   boolean isHumanReadable();
 
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return {@code true} if the provided value is acceptable for use
-   *         with this syntax, or {@code false} if not.
+   * @return {@code true} if the provided value is acceptable for use with this
+   *         syntax, or {@code false} if not.
    */
   boolean valueIsAcceptable(Schema schema, ByteSequence value,
       LocalizableMessageBuilder invalidReason);
diff --git a/sdk/src/org/opends/sdk/schema/TelephoneNumberEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/TelephoneNumberEqualityMatchingRuleImpl.java
index 7f356b4..4365add 100644
--- a/sdk/src/org/opends/sdk/schema/TelephoneNumberEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/TelephoneNumberEqualityMatchingRuleImpl.java
@@ -36,17 +36,16 @@
 
 
 /**
- * This class implements the telephoneNumberMatch matching rule defined
- * in X.520 and referenced in RFC 2252. Note that although the
- * specification calls for a very rigorous format, this is widely
- * ignored so this matching will compare only numeric digits and strip
- * out everything else.
+ * This class implements the telephoneNumberMatch matching rule defined in X.520
+ * and referenced in RFC 2252. Note that although the specification calls for a
+ * very rigorous format, this is widely ignored so this matching will compare
+ * only numeric digits and strip out everything else.
  */
 final class TelephoneNumberEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final String valueString = value.toString();
     final int valueLength = valueString.length();
diff --git a/sdk/src/org/opends/sdk/schema/TelephoneNumberSubstringMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/TelephoneNumberSubstringMatchingRuleImpl.java
index 9fe1104..0894a95 100644
--- a/sdk/src/org/opends/sdk/schema/TelephoneNumberSubstringMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/TelephoneNumberSubstringMatchingRuleImpl.java
@@ -36,17 +36,16 @@
 
 
 /**
- * This class implements the telephoneNumberSubstringsMatch matching
- * rule defined in X.520 and referenced in RFC 2252. Note that although
- * the specification calls for a very rigorous format, this is widely
- * ignored so this matching will compare only numeric digits and strip
- * out everything else.
+ * This class implements the telephoneNumberSubstringsMatch matching rule
+ * defined in X.520 and referenced in RFC 2252. Note that although the
+ * specification calls for a very rigorous format, this is widely ignored so
+ * this matching will compare only numeric digits and strip out everything else.
  */
 final class TelephoneNumberSubstringMatchingRuleImpl extends
     AbstractSubstringMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     final String valueString = value.toString();
     final int valueLength = valueString.length();
diff --git a/sdk/src/org/opends/sdk/schema/TelephoneNumberSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/TelephoneNumberSyntaxImpl.java
index 57e13ac..9371051 100644
--- a/sdk/src/org/opends/sdk/schema/TelephoneNumberSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/TelephoneNumberSyntaxImpl.java
@@ -29,9 +29,14 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_TELEPHONE_EMPTY;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_TELEPHONE_ILLEGAL_CHAR;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_TELEPHONE_NO_DIGITS;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_TELEPHONE_NO_PLUS;
+import static com.sun.opends.sdk.util.StaticUtils.isDigit;
+import static org.opends.sdk.schema.SchemaConstants.EMR_TELEPHONE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_TELEPHONE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_TELEPHONE_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessage;
@@ -39,15 +44,13 @@
 
 
 
-
 /**
- * This class implements the telephone number attribute syntax, which is
- * defined in RFC 2252. Note that this can have two modes of operation,
- * depending on its configuration. Most of the time, it will be very
- * lenient when deciding what to accept, and will allow anything but
- * only pay attention to the digits. However, it can also be configured
- * in a "strict" mode, in which case it will only accept values in the
- * E.123 international telephone number format.
+ * This class implements the telephone number attribute syntax, which is defined
+ * in RFC 2252. Note that this can have two modes of operation, depending on its
+ * configuration. Most of the time, it will be very lenient when deciding what
+ * to accept, and will allow anything but only pay attention to the digits.
+ * However, it can also be configured in a "strict" mode, in which case it will
+ * only accept values in the E.123 international telephone number format.
  */
 final class TelephoneNumberSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -83,26 +86,25 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // No matter what, the value can't be empty or null.
     String valueStr;
-    if (value == null
-        || (valueStr = value.toString().trim()).length() == 0)
+    if (value == null || (valueStr = value.toString().trim()).length() == 0)
     {
       invalidReason.append(ERR_ATTR_SYNTAX_TELEPHONE_EMPTY.get());
       return false;
@@ -116,8 +118,8 @@
       // acceptable.
       if (valueStr.charAt(0) != '+')
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_TELEPHONE_NO_PLUS.get(valueStr);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_TELEPHONE_NO_PLUS
+            .get(valueStr);
         invalidReason.append(message);
         return false;
       }
@@ -135,9 +137,8 @@
         }
         else if (!isSeparator(c))
         {
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_TELEPHONE_ILLEGAL_CHAR.get(valueStr,
-                  String.valueOf(c), i);
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_TELEPHONE_ILLEGAL_CHAR
+              .get(valueStr, String.valueOf(c), i);
           invalidReason.append(message);
           return false;
         }
@@ -145,8 +146,8 @@
 
       if (!digitSeen)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_TELEPHONE_NO_DIGITS.get(valueStr);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_TELEPHONE_NO_DIGITS
+            .get(valueStr);
         invalidReason.append(message);
         return false;
       }
@@ -167,8 +168,8 @@
       }
 
       // If we made it here, then we didn't find any digits.
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_TELEPHONE_NO_DIGITS.get(valueStr);
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_TELEPHONE_NO_DIGITS
+          .get(valueStr);
       invalidReason.append(message);
       return false;
     }
@@ -177,15 +178,15 @@
 
 
   /**
-   * Indicates whether the provided character is a valid separator for
-   * telephone number components when operating in strict mode.
-   * 
+   * Indicates whether the provided character is a valid separator for telephone
+   * number components when operating in strict mode.
+   *
    * @param c
    *          The character for which to make the determination.
-   * @return <CODE>true</CODE> if the provided character is a valid
-   *         separator, or <CODE>false</CODE> if it is not.
+   * @return <CODE>true</CODE> if the provided character is a valid separator,
+   *         or <CODE>false</CODE> if it is not.
    */
-  private boolean isSeparator(char c)
+  private boolean isSeparator(final char c)
   {
     switch (c)
     {
diff --git a/sdk/src/org/opends/sdk/schema/TeletexTerminalIdentifierSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/TeletexTerminalIdentifierSyntaxImpl.java
index 77e32fd..9256bd2 100644
--- a/sdk/src/org/opends/sdk/schema/TeletexTerminalIdentifierSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/TeletexTerminalIdentifierSyntaxImpl.java
@@ -30,7 +30,10 @@
 
 
 import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.EMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_TELETEX_TERM_ID_NAME;
 
 import java.util.HashSet;
 
@@ -39,15 +42,14 @@
 
 
 
-
 /**
- * This class implements the teletex terminal identifier attribute
- * syntax, which contains a printable string (the terminal identifier)
- * followed by zero or more parameters, which start with a dollar sign
- * and are followed by a parameter name, a colon, and a value. The
- * parameter value should consist of any string of bytes (the dollar
- * sign and backslash must be escaped with a preceding backslash), and
- * the parameter name must be one of the following strings:
+ * This class implements the teletex terminal identifier attribute syntax, which
+ * contains a printable string (the terminal identifier) followed by zero or
+ * more parameters, which start with a dollar sign and are followed by a
+ * parameter name, a colon, and a value. The parameter value should consist of
+ * any string of bytes (the dollar sign and backslash must be escaped with a
+ * preceding backslash), and the parameter name must be one of the following
+ * strings:
  * <UL>
  * <LI>graphic</LI>
  * <LI>control</LI>
@@ -56,15 +58,14 @@
  * <LI>private</LI>
  * </UL>
  */
-final class TeletexTerminalIdentifierSyntaxImpl extends
-    AbstractSyntaxImpl
+final class TeletexTerminalIdentifierSyntaxImpl extends AbstractSyntaxImpl
 {
   /**
-   * The set of allowed fax parameter values, formatted entirely in
-   * lowercase characters.
+   * The set of allowed fax parameter values, formatted entirely in lowercase
+   * characters.
    */
-  private static final HashSet<String> ALLOWED_TTX_PARAMETERS =
-      new HashSet<String>(5);
+  private static final HashSet<String> ALLOWED_TTX_PARAMETERS = new HashSet<String>(
+      5);
 
   static
   {
@@ -116,21 +117,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // Get a lowercase string representation of the value and find its
     // length.
@@ -172,8 +173,8 @@
         if (!PrintableStringSyntaxImpl.isPrintableCharacter(c))
         {
 
-          invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_NOT_PRINTABLE
-              .get(valueString, String.valueOf(c), pos));
+          invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_NOT_PRINTABLE.get(
+              valueString, String.valueOf(c), pos));
         }
       }
     }
@@ -216,8 +217,7 @@
       }
       else if (c == '$')
       {
-        final String paramStr =
-            valueString.substring(paramStartPos, pos);
+        final String paramStr = valueString.substring(paramStartPos, pos);
 
         final int colonPos = paramStr.indexOf(':');
         if (colonPos < 0)
@@ -232,9 +232,8 @@
         if (!ALLOWED_TTX_PARAMETERS.contains(paramName))
         {
 
-          invalidReason
-              .append(ERR_ATTR_SYNTAX_TELETEXID_ILLEGAL_PARAMETER.get(
-                  valueString, paramName));
+          invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_ILLEGAL_PARAMETER.get(
+              valueString, paramName));
           return false;
         }
 
@@ -258,8 +257,8 @@
     if (!ALLOWED_TTX_PARAMETERS.contains(paramName))
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_ILLEGAL_PARAMETER
-          .get(valueString, paramName));
+      invalidReason.append(ERR_ATTR_SYNTAX_TELETEXID_ILLEGAL_PARAMETER.get(
+          valueString, paramName));
       return false;
     }
 
diff --git a/sdk/src/org/opends/sdk/schema/TelexNumberSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/TelexNumberSyntaxImpl.java
index 83c1971..0806f62 100644
--- a/sdk/src/org/opends/sdk/schema/TelexNumberSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/TelexNumberSyntaxImpl.java
@@ -29,20 +29,24 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_TELEX_ILLEGAL_CHAR;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_TELEX_NOT_PRINTABLE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_TELEX_TOO_SHORT;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_TELEX_TRUNCATED;
+import static org.opends.sdk.schema.SchemaConstants.EMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.OMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SMR_CASE_IGNORE_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_TELEX_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the telex number attribute syntax, which
- * contains three printable strings separated by dollar sign characters.
- * Equality, ordering, and substring matching will be allowed by
- * default.
+ * This class implements the telex number attribute syntax, which contains three
+ * printable strings separated by dollar sign characters. Equality, ordering,
+ * and substring matching will be allowed by default.
  */
 final class TelexNumberSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -86,21 +90,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // Get a string representation of the value and find its length.
     final String valueString = value.toString();
@@ -109,8 +113,7 @@
     if (valueLength < 5)
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_TOO_SHORT
-          .get(valueString));
+      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_TOO_SHORT.get(valueString));
       return false;
     }
 
@@ -119,8 +122,8 @@
     if (!PrintableStringSyntaxImpl.isPrintableCharacter(c))
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_NOT_PRINTABLE.get(
-          valueString, String.valueOf(c), 0));
+      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_NOT_PRINTABLE.get(valueString,
+          String.valueOf(c), 0));
       return false;
     }
 
@@ -149,8 +152,7 @@
     if (pos >= valueLength)
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_TRUNCATED
-          .get(valueString));
+      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_TRUNCATED.get(valueString));
       return false;
     }
 
@@ -159,8 +161,8 @@
     if (!PrintableStringSyntaxImpl.isPrintableCharacter(c))
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_NOT_PRINTABLE.get(
-          valueString, String.valueOf(c), (pos - 1)));
+      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_NOT_PRINTABLE.get(valueString,
+          String.valueOf(c), (pos - 1)));
       return false;
     }
 
@@ -189,8 +191,7 @@
     if (pos >= valueLength)
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_TRUNCATED
-          .get(valueString));
+      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_TRUNCATED.get(valueString));
       return false;
     }
 
@@ -199,8 +200,8 @@
     if (!PrintableStringSyntaxImpl.isPrintableCharacter(c))
     {
 
-      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_NOT_PRINTABLE.get(
-          valueString, String.valueOf(c), (pos - 1)));
+      invalidReason.append(ERR_ATTR_SYNTAX_TELEX_NOT_PRINTABLE.get(valueString,
+          String.valueOf(c), (pos - 1)));
       return false;
     }
 
diff --git a/sdk/src/org/opends/sdk/schema/UTCTimeSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/UTCTimeSyntaxImpl.java
index a95a3cc..3f1e3a6 100644
--- a/sdk/src/org/opends/sdk/schema/UTCTimeSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/UTCTimeSyntaxImpl.java
@@ -46,12 +46,12 @@
 
 
 /**
- * This class implements the UTC time attribute syntax. This is very
- * similar to the generalized time syntax (and actually has been
- * deprecated in favor of that), but requires that the minute be
- * provided and does not allow for sub-second times. All matching will
- * be performed using the generalized time matching rules, and equality,
- * ordering, and substring matching will be allowed.
+ * This class implements the UTC time attribute syntax. This is very similar to
+ * the generalized time syntax (and actually has been deprecated in favor of
+ * that), but requires that the minute be provided and does not allow for
+ * sub-second times. All matching will be performed using the generalized time
+ * matching rules, and equality, ordering, and substring matching will be
+ * allowed.
  */
 final class UTCTimeSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -60,13 +60,13 @@
    * The lock that will be used to provide threadsafe access to the date
    * formatter.
    */
-  private final static Object dateFormatLock;
+  private final static Object DATE_FORMAT_LOCK;
 
   /**
-   * The date formatter that will be used to convert dates into UTC time
-   * values. Note that all interaction with it must be synchronized.
+   * The date formatter that will be used to convert dates into UTC time values.
+   * Note that all interaction with it must be synchronized.
    */
-  private final static SimpleDateFormat dateFormat;
+  private final static SimpleDateFormat DATE_FORMAT;
 
   /*
    * Create the date formatter that will be used to construct and parse
@@ -74,65 +74,62 @@
    */
   static
   {
-    dateFormat = new SimpleDateFormat(DATE_FORMAT_UTC_TIME);
-    dateFormat.setLenient(false);
-    dateFormat.setTimeZone(TimeZone.getTimeZone(TIME_ZONE_UTC));
+    DATE_FORMAT = new SimpleDateFormat(DATE_FORMAT_UTC_TIME);
+    DATE_FORMAT.setLenient(false);
+    DATE_FORMAT.setTimeZone(TimeZone.getTimeZone(TIME_ZONE_UTC));
 
-    dateFormatLock = new Object();
+    DATE_FORMAT_LOCK = new Object();
   }
 
 
 
   /**
-   * Retrieves an string containing a UTC time representation of the
-   * provided date.
-   * 
+   * Retrieves an string containing a UTC time representation of the provided
+   * date.
+   *
    * @param d
    *          The date for which to retrieve the UTC time value.
    * @return The attribute value created from the date.
    */
-  static String createUTCTimeValue(Date d)
+  static String createUTCTimeValue(final Date d)
   {
-    synchronized (dateFormatLock)
+    synchronized (DATE_FORMAT_LOCK)
     {
-      return dateFormat.format(d);
+      return DATE_FORMAT.format(d);
     }
   }
 
 
 
   /**
-   * Decodes the provided normalized value as a UTC time value and
-   * retrieves a Java <CODE>Date</CODE> object containing its
-   * representation.
-   * 
+   * Decodes the provided normalized value as a UTC time value and retrieves a
+   * Java <CODE>Date</CODE> object containing its representation.
+   *
    * @param valueString
    *          The normalized UTC time value to decode to a Java
    *          <CODE>Date</CODE>.
-   * @return The Java <CODE>Date</CODE> created from the provided UTC
-   *         time value.
+   * @return The Java <CODE>Date</CODE> created from the provided UTC time
+   *         value.
    * @throws DecodeException
-   *           If the provided value cannot be parsed as a valid UTC
-   *           time string.
+   *           If the provided value cannot be parsed as a valid UTC time
+   *           string.
    */
-  static Date decodeUTCTimeValue(String valueString)
+  static Date decodeUTCTimeValue(final String valueString)
       throws DecodeException
   {
     try
     {
-      synchronized (dateFormatLock)
+      synchronized (DATE_FORMAT_LOCK)
       {
-        return dateFormat.parse(valueString);
+        return DATE_FORMAT.parse(valueString);
       }
     }
     catch (final Exception e)
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_UTC_TIME_CANNOT_PARSE.get(valueString, String
-              .valueOf(e));
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_CANNOT_PARSE
+          .get(valueString, String.valueOf(e));
       final DecodeException de = DecodeException.error(message, e);
-      StaticUtils.DEBUG_LOG.throwing("UTCTimeSyntax",
-          "decodeUTCTimeValue", de);
+      StaticUtils.DEBUG_LOG.throwing("UTCTimeSyntax", "decodeUTCTimeValue", de);
       throw de;
     }
   }
@@ -178,21 +175,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // Get the value as a string and verify that it is at least long
     // enough for "YYYYMMDDhhmmZ", which is the shortest allowed value.
@@ -200,8 +197,8 @@
     final int length = valueString.length();
     if (length < 11)
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_UTC_TIME_TOO_SHORT.get(valueString);
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_TOO_SHORT
+          .get(valueString);
       invalidReason.append(message);
       return false;
     }
@@ -225,9 +222,8 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_YEAR.get(valueString,
-                String.valueOf(valueString.charAt(i)));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_YEAR
+            .get(valueString, String.valueOf(valueString.charAt(i)));
         invalidReason.append(message);
         return false;
       }
@@ -255,9 +251,8 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_MONTH.get(valueString,
-                valueString.substring(2, 4));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_MONTH
+            .get(valueString, valueString.substring(2, 4));
         invalidReason.append(message);
         return false;
       }
@@ -272,17 +267,15 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_MONTH.get(valueString,
-                valueString.substring(2, 4));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_MONTH
+            .get(valueString, valueString.substring(2, 4));
         invalidReason.append(message);
         return false;
       }
       break;
     default:
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_UTC_TIME_INVALID_MONTH.get(valueString,
-              valueString.substring(2, 4));
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_MONTH
+          .get(valueString, valueString.substring(2, 4));
       invalidReason.append(message);
       return false;
     }
@@ -312,9 +305,8 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_DAY.get(valueString,
-                valueString.substring(4, 6));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_DAY
+            .get(valueString, valueString.substring(4, 6));
         invalidReason.append(message);
         return false;
       }
@@ -338,9 +330,8 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_DAY.get(valueString,
-                valueString.substring(4, 6));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_DAY
+            .get(valueString, valueString.substring(4, 6));
         invalidReason.append(message);
         return false;
       }
@@ -354,17 +345,15 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_DAY.get(valueString,
-                valueString.substring(4, 6));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_DAY
+            .get(valueString, valueString.substring(4, 6));
         invalidReason.append(message);
         return false;
       }
       break;
     default:
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_UTC_TIME_INVALID_DAY.get(valueString,
-              valueString.substring(4, 6));
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_DAY
+          .get(valueString, valueString.substring(4, 6));
       invalidReason.append(message);
       return false;
     }
@@ -393,9 +382,8 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_HOUR.get(valueString,
-                valueString.substring(6, 8));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_HOUR
+            .get(valueString, valueString.substring(6, 8));
         invalidReason.append(message);
         return false;
       }
@@ -411,17 +399,15 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_HOUR.get(valueString,
-                valueString.substring(6, 8));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_HOUR
+            .get(valueString, valueString.substring(6, 8));
         invalidReason.append(message);
         return false;
       }
       break;
     default:
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_UTC_TIME_INVALID_HOUR.get(valueString,
-              valueString.substring(6, 8));
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_HOUR
+          .get(valueString, valueString.substring(6, 8));
       invalidReason.append(message);
       return false;
     }
@@ -441,9 +427,8 @@
       // must be a digit between 0 and 9.
       if (length < 11)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString,
-                String.valueOf(m1), 8);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(m1), 8);
         invalidReason.append(message);
         return false;
       }
@@ -463,9 +448,8 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_MINUTE.get(valueString,
-                valueString.substring(8, 10));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_MINUTE
+            .get(valueString, valueString.substring(8, 10));
         invalidReason.append(message);
         return false;
       }
@@ -473,9 +457,8 @@
       break;
 
     default:
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString, String
-              .valueOf(m1), 8);
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR
+          .get(valueString, String.valueOf(m1), 8);
       invalidReason.append(message);
       return false;
     }
@@ -497,9 +480,8 @@
       // must be a digit between 0 and 9.
       if (length < 13)
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString,
-                String.valueOf(s1), 10);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(s1), 10);
         invalidReason.append(message);
         return false;
       }
@@ -519,9 +501,8 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_SECOND.get(valueString,
-                valueString.substring(10, 12));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_SECOND
+            .get(valueString, valueString.substring(10, 12));
         invalidReason.append(message);
         return false;
       }
@@ -533,18 +514,16 @@
       if (length < 13)
       {
 
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString,
-                String.valueOf(s1), 10);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(s1), 10);
         invalidReason.append(message);
         return false;
       }
 
       if (valueString.charAt(11) != '0')
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_SECOND.get(valueString,
-                valueString.substring(10, 12));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_SECOND
+            .get(valueString, valueString.substring(10, 12));
         invalidReason.append(message);
         return false;
       }
@@ -558,9 +537,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString,
-                String.valueOf(s1), 10);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(s1), 10);
         invalidReason.append(message);
         return false;
       }
@@ -575,17 +553,15 @@
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString,
-                String.valueOf(s1), 10);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(s1), 10);
         invalidReason.append(message);
         return false;
       }
 
     default:
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString, String
-              .valueOf(s1), 10);
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR
+          .get(valueString, String.valueOf(s1), 10);
       invalidReason.append(message);
       return false;
     }
@@ -603,9 +579,8 @@
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString,
-                String.valueOf(valueString.charAt(12)), 12);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(valueString.charAt(12)), 12);
         invalidReason.append(message);
         return false;
       }
@@ -620,17 +595,15 @@
       }
       else
       {
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString,
-                String.valueOf(valueString.charAt(12)), 12);
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR
+            .get(valueString, String.valueOf(valueString.charAt(12)), 12);
         invalidReason.append(message);
         return false;
       }
 
     default:
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR.get(valueString, String
-              .valueOf(valueString.charAt(12)), 12);
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_CHAR
+          .get(valueString, String.valueOf(valueString.charAt(12)), 12);
       invalidReason.append(message);
       return false;
     }
@@ -639,31 +612,29 @@
 
 
   /**
-   * Indicates whether the provided string contains a valid set of two
-   * or four UTC offset digits. The provided string must have either two
-   * or four characters from the provided start position to the end of
-   * the value.
-   * 
+   * Indicates whether the provided string contains a valid set of two or four
+   * UTC offset digits. The provided string must have either two or four
+   * characters from the provided start position to the end of the value.
+   *
    * @param value
    *          The whole value, including the offset.
    * @param startPos
-   *          The position of the first character that is contained in
-   *          the offset.
+   *          The position of the first character that is contained in the
+   *          offset.
    * @param invalidReason
-   *          The buffer to which the invalid reason may be appended if
-   *          the string does not contain a valid set of UTC offset
-   *          digits.
-   * @return <CODE>true</CODE> if the provided offset string is valid,
-   *         or <CODE>false</CODE> if it is not.
+   *          The buffer to which the invalid reason may be appended if the
+   *          string does not contain a valid set of UTC offset digits.
+   * @return <CODE>true</CODE> if the provided offset string is valid, or
+   *         <CODE>false</CODE> if it is not.
    */
-  private boolean hasValidOffset(String value, int startPos,
-      LocalizableMessageBuilder invalidReason)
+  private boolean hasValidOffset(final String value, final int startPos,
+      final LocalizableMessageBuilder invalidReason)
   {
     final int offsetLength = value.length() - startPos;
     if (offsetLength < 2)
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_UTC_TIME_TOO_SHORT.get(value);
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_TOO_SHORT
+          .get(value);
       invalidReason.append(message);
       return false;
     }
@@ -688,9 +659,8 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_OFFSET.get(value, value
-                .substring(startPos, startPos + offsetLength));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_OFFSET
+            .get(value, value.substring(startPos, startPos + offsetLength));
         invalidReason.append(message);
         return false;
       }
@@ -705,17 +675,15 @@
         // These are all fine.
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_OFFSET.get(value, value
-                .substring(startPos, startPos + offsetLength));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_OFFSET
+            .get(value, value.substring(startPos, startPos + offsetLength));
         invalidReason.append(message);
         return false;
       }
       break;
     default:
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_UTC_TIME_INVALID_OFFSET.get(value, value
-              .substring(startPos, startPos + offsetLength));
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_OFFSET
+          .get(value, value.substring(startPos, startPos + offsetLength));
       invalidReason.append(message);
       return false;
     }
@@ -747,17 +715,15 @@
           // These are all fine.
           break;
         default:
-          final LocalizableMessage message =
-              ERR_ATTR_SYNTAX_UTC_TIME_INVALID_OFFSET.get(value, value
-                  .substring(startPos, startPos + offsetLength));
+          final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_OFFSET
+              .get(value, value.substring(startPos, startPos + offsetLength));
           invalidReason.append(message);
           return false;
         }
         break;
       default:
-        final LocalizableMessage message =
-            ERR_ATTR_SYNTAX_UTC_TIME_INVALID_OFFSET.get(value, value
-                .substring(startPos, startPos + offsetLength));
+        final LocalizableMessage message = ERR_ATTR_SYNTAX_UTC_TIME_INVALID_OFFSET
+            .get(value, value.substring(startPos, startPos + offsetLength));
         invalidReason.append(message);
         return false;
       }
diff --git a/sdk/src/org/opends/sdk/schema/UUIDEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/UUIDEqualityMatchingRuleImpl.java
index 028c615..b3e306c 100644
--- a/sdk/src/org/opends/sdk/schema/UUIDEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/UUIDEqualityMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -37,23 +39,19 @@
 
 
 
-
 /**
- * This class defines the uuidMatch matching rule defined in RFC 4530.
- * It will be used as the default equality matching rule for the UUID
- * syntax.
+ * This class defines the uuidMatch matching rule defined in RFC 4530. It will
+ * be used as the default equality matching rule for the UUID syntax.
  */
-final class UUIDEqualityMatchingRuleImpl extends
-    AbstractMatchingRuleImpl
+final class UUIDEqualityMatchingRuleImpl extends AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     if (value.length() != 36)
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH.get(value.toString(),
-              value.length());
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH
+          .get(value.toString(), value.length());
       throw DecodeException.error(message);
     }
 
@@ -73,9 +71,8 @@
       case 23:
         if (c != '-')
         {
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH.get(value.toString(),
-                  i, String.valueOf(c));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH
+              .get(value.toString(), i, String.valueOf(c));
           throw DecodeException.error(message);
         }
         builder.append(c);
@@ -121,9 +118,8 @@
           builder.append('f');
           break;
         default:
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX.get(value.toString(),
-                  i, String.valueOf(value.byteAt(i)));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX
+              .get(value.toString(), i, String.valueOf(value.byteAt(i)));
           throw DecodeException.error(message);
         }
       }
diff --git a/sdk/src/org/opends/sdk/schema/UUIDOrderingMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/UUIDOrderingMatchingRuleImpl.java
index 8f88590..7452582 100644
--- a/sdk/src/org/opends/sdk/schema/UUIDOrderingMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/UUIDOrderingMatchingRuleImpl.java
@@ -28,7 +28,9 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.ByteString;
@@ -37,23 +39,20 @@
 
 
 
-
 /**
- * This class defines the uuidOrderingMatch matching rule defined in RFC
- * 4530. This will be the default ordering matching rule for the UUID
- * syntax.
+ * This class defines the uuidOrderingMatch matching rule defined in RFC 4530.
+ * This will be the default ordering matching rule for the UUID syntax.
  */
 final class UUIDOrderingMatchingRuleImpl extends
     AbstractOrderingMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     if (value.length() != 36)
     {
-      final LocalizableMessage message =
-          WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH.get(value.toString(),
-              value.length());
+      final LocalizableMessage message = WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH
+          .get(value.toString(), value.length());
       throw DecodeException.error(message);
     }
 
@@ -73,9 +72,8 @@
       case 23:
         if (c != '-')
         {
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH.get(value.toString(),
-                  i, String.valueOf(c));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH
+              .get(value.toString(), i, String.valueOf(c));
           throw DecodeException.error(message);
         }
         builder.append(c);
@@ -121,9 +119,8 @@
           builder.append('f');
           break;
         default:
-          final LocalizableMessage message =
-              WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX.get(value.toString(),
-                  i, String.valueOf(value.byteAt(i)));
+          final LocalizableMessage message = WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX
+              .get(value.toString(), i, String.valueOf(value.byteAt(i)));
           throw DecodeException.error(message);
         }
       }
diff --git a/sdk/src/org/opends/sdk/schema/UUIDSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/UUIDSyntaxImpl.java
index bd131e0..0dc82a8 100644
--- a/sdk/src/org/opends/sdk/schema/UUIDSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/UUIDSyntaxImpl.java
@@ -29,18 +29,19 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_UUID_EXPECTED_DASH;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_UUID_EXPECTED_HEX;
+import static com.sun.opends.sdk.messages.Messages.WARN_ATTR_SYNTAX_UUID_INVALID_LENGTH;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_UUID_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.LocalizableMessageBuilder;
 
 
 
-
 /**
- * This class implements the UUID syntax, which is defined in RFC 4530.
- * Equality and ordering matching will be allowed by default.
+ * This class implements the UUID syntax, which is defined in RFC 4530. Equality
+ * and ordering matching will be allowed by default.
  */
 final class UUIDSyntaxImpl extends AbstractSyntaxImpl
 {
@@ -59,21 +60,21 @@
 
 
   /**
-   * Indicates whether the provided value is acceptable for use in an
-   * attribute with this syntax. If it is not, then the reason may be
-   * appended to the provided buffer.
-   * 
+   * Indicates whether the provided value is acceptable for use in an attribute
+   * with this syntax. If it is not, then the reason may be appended to the
+   * provided buffer.
+   *
    * @param schema
    *          The schema in which this syntax is defined.
    * @param value
    *          The value for which to make the determination.
    * @param invalidReason
    *          The buffer to which the invalid reason should be appended.
-   * @return <CODE>true</CODE> if the provided value is acceptable for
-   *         use with this syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the provided value is acceptable for use with
+   *         this syntax, or <CODE>false</CODE> if not.
    */
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We will only accept values that look like valid UUIDs. This means
     // that all values must be in the form
diff --git a/sdk/src/org/opends/sdk/schema/UniqueMemberEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/UniqueMemberEqualityMatchingRuleImpl.java
index 5dbf775..884f0f0 100644
--- a/sdk/src/org/opends/sdk/schema/UniqueMemberEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/UniqueMemberEqualityMatchingRuleImpl.java
@@ -34,16 +34,16 @@
 
 
 /**
- * This class implements the uniqueMemberMatch matching rule defined in
- * X.520 and referenced in RFC 2252. It is based on the name and
- * optional UID syntax, and will compare values with a distinguished
- * name and optional bit string suffix.
+ * This class implements the uniqueMemberMatch matching rule defined in X.520
+ * and referenced in RFC 2252. It is based on the name and optional UID syntax,
+ * and will compare values with a distinguished name and optional bit string
+ * suffix.
  */
 final class UniqueMemberEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     return value.toByteString();
   }
diff --git a/sdk/src/org/opends/sdk/schema/UnknownSchemaElementException.java b/sdk/src/org/opends/sdk/schema/UnknownSchemaElementException.java
index 3e2db2a..63c90f7 100644
--- a/sdk/src/org/opends/sdk/schema/UnknownSchemaElementException.java
+++ b/sdk/src/org/opends/sdk/schema/UnknownSchemaElementException.java
@@ -29,28 +29,26 @@
 
 
 
-import org.opends.sdk.LocalizedIllegalArgumentException;
 import org.opends.sdk.LocalizableMessage;
-
+import org.opends.sdk.LocalizedIllegalArgumentException;
 
 
 
 /**
- * Thrown when a schema query fails because the requested schema element
- * could not be found or is ambiguous.
+ * Thrown when a schema query fails because the requested schema element could
+ * not be found or is ambiguous.
  */
 @SuppressWarnings("serial")
 public class UnknownSchemaElementException extends
     LocalizedIllegalArgumentException
 {
   /**
-   * Creates a new unknown schema element exception with the provided
-   * message.
-   * 
+   * Creates a new unknown schema element exception with the provided message.
+   *
    * @param message
    *          The message that explains the problem that occurred.
    */
-  public UnknownSchemaElementException(LocalizableMessage message)
+  public UnknownSchemaElementException(final LocalizableMessage message)
   {
     super(message);
   }
diff --git a/sdk/src/org/opends/sdk/schema/UserPasswordExactEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/UserPasswordExactEqualityMatchingRuleImpl.java
index f92decf..fb00329 100644
--- a/sdk/src/org/opends/sdk/schema/UserPasswordExactEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/UserPasswordExactEqualityMatchingRuleImpl.java
@@ -37,15 +37,15 @@
 
 
 /**
- * This class implements the userPasswordExactMatch matching rule, which
- * will simply compare encoded hashed password values to see if they are
- * exactly equal to each other.
+ * This class implements the userPasswordExactMatch matching rule, which will
+ * simply compare encoded hashed password values to see if they are exactly
+ * equal to each other.
  */
 final class UserPasswordExactEqualityMatchingRuleImpl extends
     AbstractMatchingRuleImpl
 {
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value) throws DecodeException
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value) throws DecodeException
   {
     // The normalized form of this matching rule is exactly equal to the
     // non-normalized form, except that the scheme needs to be converted
@@ -63,10 +63,9 @@
           break;
         }
       }
-      final ByteSequence seq1 =
-          value.subSequence(0, closingBracePos + 1);
-      final ByteSequence seq2 =
-          value.subSequence(closingBracePos + 1, value.length());
+      final ByteSequence seq1 = value.subSequence(0, closingBracePos + 1);
+      final ByteSequence seq2 = value.subSequence(closingBracePos + 1, value
+          .length());
       StaticUtils.toLowerCase(seq1, builder);
       builder.append(seq2);
       return ByteString.valueOf(builder.toString());
diff --git a/sdk/src/org/opends/sdk/schema/UserPasswordSyntaxImpl.java b/sdk/src/org/opends/sdk/schema/UserPasswordSyntaxImpl.java
index fe470a2..06ac246 100644
--- a/sdk/src/org/opends/sdk/schema/UserPasswordSyntaxImpl.java
+++ b/sdk/src/org/opends/sdk/schema/UserPasswordSyntaxImpl.java
@@ -29,9 +29,13 @@
 
 
 
-import static com.sun.opends.sdk.messages.Messages.*;
-import static com.sun.opends.sdk.util.StaticUtils.*;
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_USERPW_NO_CLOSING_BRACE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_USERPW_NO_OPENING_BRACE;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_USERPW_NO_SCHEME;
+import static com.sun.opends.sdk.messages.Messages.ERR_ATTR_SYNTAX_USERPW_NO_VALUE;
+import static com.sun.opends.sdk.util.StaticUtils.toLowerCase;
+import static org.opends.sdk.schema.SchemaConstants.EMR_USER_PASSWORD_EXACT_OID;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_USER_PASSWORD_NAME;
 
 import org.opends.sdk.ByteSequence;
 import org.opends.sdk.DecodeException;
@@ -40,12 +44,11 @@
 
 
 
-
 /**
- * This class defines an attribute syntax used for storing values that
- * have been encoded using a password storage scheme. The format for
- * attribute values with this syntax is the concatenation of the
- * following elements in the given order: <BR>
+ * This class defines an attribute syntax used for storing values that have been
+ * encoded using a password storage scheme. The format for attribute values with
+ * this syntax is the concatenation of the following elements in the given
+ * order: <BR>
  * <UL>
  * <LI>An opening curly brace ("{") character.</LI>
  * <LI>The name of the storage scheme used to encode the value.</LI>
@@ -57,17 +60,16 @@
 {
   /**
    * Decodes the provided user password value into its component parts.
-   * 
+   *
    * @param userPasswordValue
    *          The user password value to be decoded.
-   * @return A two-element string array whose elements are the storage
-   *         scheme name (in all lowercase characters) and the encoded
-   *         value, in that order.
+   * @return A two-element string array whose elements are the storage scheme
+   *         name (in all lowercase characters) and the encoded value, in that
+   *         order.
    * @throws DecodeException
-   *           If a problem is encountered while attempting to decode
-   *           the value.
+   *           If a problem is encountered while attempting to decode the value.
    */
-  static String[] decodeUserPassword(String userPasswordValue)
+  static String[] decodeUserPassword(final String userPasswordValue)
       throws DecodeException
   {
     // Make sure that there actually is a value to decode.
@@ -81,8 +83,8 @@
     // brace.
     if (userPasswordValue.charAt(0) != '{')
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_USERPW_NO_OPENING_BRACE.get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_USERPW_NO_OPENING_BRACE
+          .get();
       throw DecodeException.error(message);
     }
 
@@ -90,15 +92,14 @@
     final int closePos = userPasswordValue.indexOf('}');
     if (closePos < 0)
     {
-      final LocalizableMessage message =
-          ERR_ATTR_SYNTAX_USERPW_NO_CLOSING_BRACE.get();
+      final LocalizableMessage message = ERR_ATTR_SYNTAX_USERPW_NO_CLOSING_BRACE
+          .get();
       throw DecodeException.error(message);
     }
 
     // Get the storage scheme name and encoded value.
     final String schemeName = userPasswordValue.substring(1, closePos);
-    final String encodedValue =
-        userPasswordValue.substring(closePos + 1);
+    final String encodedValue = userPasswordValue.substring(closePos + 1);
 
     if (schemeName.length() == 0)
     {
@@ -112,15 +113,15 @@
 
 
   /**
-   * Indicates whether the provided value is encoded using the user
-   * password syntax.
-   * 
+   * Indicates whether the provided value is encoded using the user password
+   * syntax.
+   *
    * @param value
    *          The value for which to make the determination.
-   * @return <CODE>true</CODE> if the value appears to be encoded using
-   *         the user password syntax, or <CODE>false</CODE> if not.
+   * @return <CODE>true</CODE> if the value appears to be encoded using the user
+   *         password syntax, or <CODE>false</CODE> if not.
    */
-  static boolean isEncoded(ByteSequence value)
+  static boolean isEncoded(final ByteSequence value)
   {
     // If the value is null or empty, then it's not.
     if (value == null || value.length() == 0)
@@ -187,8 +188,8 @@
 
 
 
-  public boolean valueIsAcceptable(Schema schema, ByteSequence value,
-      LocalizableMessageBuilder invalidReason)
+  public boolean valueIsAcceptable(final Schema schema,
+      final ByteSequence value, final LocalizableMessageBuilder invalidReason)
   {
     // We have to accept any value here because in many cases the value
     // will not have been encoded by the time this method is called.
diff --git a/sdk/src/org/opends/sdk/schema/WordEqualityMatchingRuleImpl.java b/sdk/src/org/opends/sdk/schema/WordEqualityMatchingRuleImpl.java
index 1879d35..c1f15e4 100644
--- a/sdk/src/org/opends/sdk/schema/WordEqualityMatchingRuleImpl.java
+++ b/sdk/src/org/opends/sdk/schema/WordEqualityMatchingRuleImpl.java
@@ -28,18 +28,20 @@
 
 
 
-import static com.sun.opends.sdk.util.StringPrepProfile.*;
+import static com.sun.opends.sdk.util.StringPrepProfile.CASE_FOLD;
+import static com.sun.opends.sdk.util.StringPrepProfile.TRIM;
+import static com.sun.opends.sdk.util.StringPrepProfile.prepareUnicode;
 
 import org.opends.sdk.*;
 
 
 
 /**
- * This class implements the wordMatch matching rule defined in X.520.
- * That document defines "word" as implementation-specific, but in this
- * case we will consider it a match if the assertion value is contained
- * within the attribute value and is bounded by the edge of the value or
- * any of the following characters: <BR>
+ * This class implements the wordMatch matching rule defined in X.520. That
+ * document defines "word" as implementation-specific, but in this case we will
+ * consider it a match if the assertion value is contained within the attribute
+ * value and is bounded by the edge of the value or any of the following
+ * characters: <BR>
  * <UL>
  * <LI>A space</LI>
  * <LI>A period</LI>
@@ -53,18 +55,17 @@
  * <LI>An equal sign</LI>
  * </UL>
  */
-final class WordEqualityMatchingRuleImpl extends
-    AbstractMatchingRuleImpl
+final class WordEqualityMatchingRuleImpl extends AbstractMatchingRuleImpl
 {
   @Override
-  public Assertion getAssertion(Schema schema, ByteSequence value)
+  public Assertion getAssertion(final Schema schema, final ByteSequence value)
       throws DecodeException
   {
     final String normalStr = normalize(value);
 
     return new Assertion()
     {
-      public ConditionResult matches(ByteSequence attributeValue)
+      public ConditionResult matches(final ByteSequence attributeValue)
       {
         // See if the assertion value is contained in the attribute
         // value. If not, then it isn't a match.
@@ -132,15 +133,15 @@
 
 
 
-  public ByteString normalizeAttributeValue(Schema schema,
-      ByteSequence value)
+  public ByteString normalizeAttributeValue(final Schema schema,
+      final ByteSequence value)
   {
     return ByteString.valueOf(normalize(value));
   }
 
 
 
-  private String normalize(ByteSequence value)
+  private String normalize(final ByteSequence value)
   {
     final StringBuilder buffer = new StringBuilder();
     prepareUnicode(buffer, value, TRIM, CASE_FOLD);
diff --git a/sdk/src/org/opends/sdk/schema/package-info.java b/sdk/src/org/opends/sdk/schema/package-info.java
index ab62783..388c61e 100755
--- a/sdk/src/org/opends/sdk/schema/package-info.java
+++ b/sdk/src/org/opends/sdk/schema/package-info.java
@@ -29,3 +29,6 @@
  * Classes and interfaces for constructing and querying LDAP schemas.
  */
 package org.opends.sdk.schema;
+
+
+
diff --git a/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControlTestCase.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControlTestCase.java
new file mode 100644
index 0000000..739a446
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControlTestCase.java
@@ -0,0 +1,74 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.controls;
+
+
+
+import static org.testng.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opends.sdk.*;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlsTestCase;
+import org.opends.sdk.requests.Requests;
+import org.opends.sdk.requests.SearchRequest;
+import org.opends.sdk.responses.SearchResultEntry;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * Tests the account usability request control.
+ */
+public class AccountUsabilityRequestControlTestCase extends ControlsTestCase
+{
+  @Test()
+  public void testControl() throws Exception
+  {
+    // Send this control with a search request and see that you get
+    // a valid response.
+    final SearchRequest req = Requests.newSearchRequest(DN
+        .valueOf("uid=user.1,ou=people,o=test"), SearchScope.BASE_OBJECT,
+        Filter.getObjectClassPresentFilter());
+    final AccountUsabilityRequestControl control = AccountUsabilityRequestControl
+        .newControl(false);
+    req.addControl(control);
+    final Connection con = TestCaseUtils.getInternalConnection();
+    final List<SearchResultEntry> entries = new ArrayList<SearchResultEntry>();
+    con.search(req, entries);
+    assertTrue(entries.size() > 0);
+    final SearchResultEntry entry = entries.get(0);
+    final Control ctrl = entry.getControls().get(0);
+    if (!ctrl.getOID().equals("1.3.6.1.4.1.42.2.27.9.5.8"))
+    {
+      throw new Exception("expected control response 1.3.6.1.4.1.42.2.27.9.5.8");
+    }
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControlTestCase.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControlTestCase.java
new file mode 100644
index 0000000..5b3d651
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControlTestCase.java
@@ -0,0 +1,95 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.controls;
+
+
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.opends.sdk.*;
+import org.opends.sdk.controls.ControlsTestCase;
+import org.opends.sdk.requests.Requests;
+import org.opends.sdk.requests.SearchRequest;
+import org.opends.sdk.responses.SearchResultEntry;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * Tests the account usability response control.
+ */
+public class AccountUsabilityResponseControlTestCase extends ControlsTestCase
+{
+  @Test()
+  public void testInvalidResponseControl() throws Exception
+  {
+    // Don't send the request control and hence there
+    // shouldn't be response.
+    final SearchRequest req = Requests.newSearchRequest(DN
+        .valueOf("uid=user.1,ou=people,o=test"), SearchScope.BASE_OBJECT,
+        Filter.getObjectClassPresentFilter());
+    final Connection con = TestCaseUtils.getInternalConnection();
+    final List<SearchResultEntry> entries = new ArrayList<SearchResultEntry>();
+    con.search(req, entries);
+    assertTrue(entries.size() > 0);
+    final SearchResultEntry entry = entries.get(0);
+    final AccountUsabilityResponseControl aurctrl = entry.getControl(
+        AccountUsabilityResponseControl.DECODER, new DecodeOptions());
+    assertNull(aurctrl);
+  }
+
+
+
+  @Test()
+  public void testValidResponseControl() throws Exception
+  {
+    // Send this control with a search request and see that you get
+    // a valid response.
+    final SearchRequest req = Requests.newSearchRequest(DN
+        .valueOf("uid=user.1,ou=people,o=test"), SearchScope.BASE_OBJECT,
+        Filter.getObjectClassPresentFilter());
+    final AccountUsabilityRequestControl control = AccountUsabilityRequestControl
+        .newControl(false);
+    req.addControl(control);
+    final Connection con = TestCaseUtils.getInternalConnection();
+    final List<SearchResultEntry> entries = new ArrayList<SearchResultEntry>();
+    con.search(req, entries);
+    assertTrue(entries.size() > 0);
+    final SearchResultEntry entry = entries.get(0);
+    final AccountUsabilityResponseControl aurctrl = entry.getControl(
+        AccountUsabilityResponseControl.DECODER, new DecodeOptions());
+    assertFalse(aurctrl.isExpired());
+    assertFalse(aurctrl.isLocked());
+    assertFalse(aurctrl.isInactive());
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferReaderTestCase.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferReaderTestCase.java
new file mode 100644
index 0000000..95ba625
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferReaderTestCase.java
@@ -0,0 +1,62 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1ReaderTestCase;
+
+import com.sun.grizzly.memory.ByteBufferWrapper;
+import com.sun.grizzly.memory.DefaultMemoryManager;
+
+
+
+/**
+ * This class provides testcases for ASN1BufferReader.
+ */
+public class ASN1BufferReaderTestCase extends ASN1ReaderTestCase
+{
+  public final static DefaultMemoryManager memoryManager = new DefaultMemoryManager();
+
+
+
+  @Override
+  protected ASN1Reader getReader(final byte[] b, final int maxElementSize)
+      throws IOException
+  {
+    final ByteBufferWrapper buffer = new ByteBufferWrapper(memoryManager,
+        ByteBuffer.wrap(b));
+    final ASN1BufferReader reader = new ASN1BufferReader(maxElementSize);
+    reader.appendBytesRead(buffer);
+    return reader;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferWriterTestCase.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferWriterTestCase.java
new file mode 100644
index 0000000..ac123cb
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferWriterTestCase.java
@@ -0,0 +1,86 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.asn1.ASN1Reader;
+import org.opends.sdk.asn1.ASN1Writer;
+import org.opends.sdk.asn1.ASN1WriterTestCase;
+
+import com.sun.grizzly.Buffer;
+import com.sun.grizzly.memory.ByteBufferWrapper;
+
+
+
+/**
+ * This class provides testcases for ASN1BufferWriter.
+ */
+public class ASN1BufferWriterTestCase extends ASN1WriterTestCase
+{
+
+  private final ASN1BufferWriter writer = ASN1BufferWriter.getWriter();
+
+
+
+  @Override
+  protected byte[] getEncodedBytes() throws IOException, DecodeException
+  {
+    final Buffer buffer = writer.getBuffer();
+    final byte[] byteArray = new byte[buffer.remaining()];
+    buffer.get(byteArray);
+    return byteArray;
+  }
+
+
+
+  @Override
+  protected ASN1Reader getReader(final byte[] encodedBytes)
+      throws DecodeException, IOException
+  {
+    final ByteBufferWrapper buffer = new ByteBufferWrapper(
+        ASN1BufferReaderTestCase.memoryManager, ByteBuffer.wrap(encodedBytes));
+    final ASN1BufferReader reader = new ASN1BufferReader(0);
+    reader.appendBytesRead(buffer);
+    return reader;
+  }
+
+
+
+  @Override
+  protected ASN1Writer getWriter() throws IOException
+  {
+    writer.flush();
+    writer.recycle();
+    return writer;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/GlobalTransportFactoryTestCase.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/GlobalTransportFactoryTestCase.java
new file mode 100644
index 0000000..1608679
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/GlobalTransportFactoryTestCase.java
@@ -0,0 +1,68 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.ldap;
+
+
+
+import static org.testng.Assert.assertTrue;
+
+import java.net.Socket;
+import java.util.Random;
+
+import org.testng.annotations.Test;
+
+import com.sun.grizzly.TransportFactory;
+import com.sun.grizzly.nio.transport.TCPNIOTransport;
+
+
+
+/**
+ * Tests Global Transport Factory class.
+ */
+public class GlobalTransportFactoryTestCase extends LDAPTestCase
+{
+  @Test()
+  public void testGlobalTransport() throws Exception
+  {
+    // Create a transport.
+    final TransportFactory instance = GlobalTransportFactory.getInstance();
+    final TCPNIOTransport transport = instance.createTCPTransport();
+    final Random r = new Random();
+    int port = r.nextInt(10000);
+    if (port < 1000)
+    {
+      port += 1000;
+    }
+    transport.bind(port);
+    // Establish a socket connection to see if the transport factory works.
+    final Socket socket = new Socket("localhost", port);
+    // Successfully connected if there is no exception.
+    assertTrue(socket.isConnected());
+    // Don't stop the transport because it is shared with the ldap server.
+  }
+}
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/LDAPTestCase.java
similarity index 67%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/LDAPTestCase.java
index 62b3ae3..7d2e509 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/LDAPTestCase.java
@@ -22,21 +22,24 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package com.sun.opends.sdk.ldap;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.opends.sdk.OpenDSTestCase;
+import org.testng.annotations.Test;
 
 
 
 /**
- * Password call-back.
+ * An abstract class that all ldap unit tests should extend. Ldap represents the
+ * classes found directly under the package com.sun.opends.sdk.ldap.
  */
-public interface PasswordCallbackHandler
+
+@Test(groups = { "precommit", "ldap", "sdk" }, sequential = true)
+public abstract class LDAPTestCase extends OpenDSTestCase
 {
-  public boolean handle(PasswordCallback callback);
 }
diff --git a/sdk/src/org/opends/sdk/ldap/package-info.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/messages/MessagesTestCase.java
old mode 100755
new mode 100644
similarity index 82%
rename from sdk/src/org/opends/sdk/ldap/package-info.java
rename to sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/messages/MessagesTestCase.java
index f39e868..c6d4c57
--- a/sdk/src/org/opends/sdk/ldap/package-info.java
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/messages/MessagesTestCase.java
@@ -22,11 +22,18 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-/**
- * Classes and interfaces for interacting with a Directory Server
- * using the LDAP protocol.
- */
-package org.opends.sdk.ldap;
+package com.sun.opends.sdk.messages;
+
+
+
+import org.opends.sdk.OpenDSTestCase;
+
+
+
+public class MessagesTestCase extends OpenDSTestCase
+{
+
+}
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/tools/ToolsTestCase.java
similarity index 67%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/tools/ToolsTestCase.java
index 62b3ae3..eb8134c 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/tools/ToolsTestCase.java
@@ -22,21 +22,24 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package com.sun.opends.sdk.tools;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.opends.sdk.OpenDSTestCase;
+import org.testng.annotations.Test;
 
 
 
 /**
- * Password call-back.
+ * An abstract class that all tools unit tests should extend. A tool represents
+ * the classes found directly under the package com.sun.opends.sdk.tools.
  */
-public interface PasswordCallbackHandler
+
+@Test(groups = { "precommit", "tools", "sdk" }, sequential = true)
+public abstract class ToolsTestCase extends OpenDSTestCase
 {
-  public boolean handle(PasswordCallback callback);
 }
diff --git a/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/ASCIICharPropTestCase.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/ASCIICharPropTestCase.java
new file mode 100644
index 0000000..d2f2a69
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/ASCIICharPropTestCase.java
@@ -0,0 +1,183 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.util;
+
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * Tests various methods of ASCIICharProp class.
+ */
+public class ASCIICharPropTestCase extends UtilTestCase
+{
+  /**
+   * Invalid Ascii char data provider.
+   *
+   * @return Returns an array of data.
+   */
+  @DataProvider(name = "invalidasciidata")
+  public Object[][] createInValidASCIIData()
+  {
+    return new Object[][] {
+    // {null,/* uppercase*/ false,/*hex value*/0,/*decimal value*/0,/* is
+    // letter*/false,/*is digit*/false,/*is keychar*/false},
+    { '\u200A' } };
+  }
+
+
+
+  /**
+   * Valid Ascii char data provider.
+   *
+   * @return Returns an array of data.
+   */
+  @DataProvider(name = "validasciidata")
+  public Object[][] createValidASCIIData()
+  {
+    return new Object[][] {
+        { (char) 1,/* uppercase */false,/* hex value */0,/* decimal value */0,/*
+                                                                               * is
+                                                                               * letter
+                                                                               */
+        false,/* is digit */false,/* is keychar */false },
+        { '-',/* uppercase */false,/* hex value */-1,/* decimal value */-1,/*
+                                                                            * is
+                                                                            * letter
+                                                                            */
+        false,/* is digit */false,/* is keychar */true },
+        { 'a',/* uppercase */false,/* hex value */10,/* decimal value */-1,/*
+                                                                            * is
+                                                                            * letter
+                                                                            */
+        true,/* is digit */false,/* is keychar */true },
+        { 'A',/* uppercase */true,/* hex value */10,/* decimal value */-1,/*
+                                                                           * is
+                                                                           * letter
+                                                                           */
+        true,/* is digit */false,/* is keychar */true },
+        { '1',/* uppercase */false,/* hex value */1,/* decimal value */1,/*
+                                                                          * is
+                                                                          * letter
+                                                                          */
+        false,/* is digit */true,/* is keychar */true }, };
+  }
+
+
+
+  /**
+   * Tests whether a character is an invalid ascii character or not.
+   *
+   * @param myChar
+   *          The character that needs to be verified.
+   * @throws Exception
+   *           In case of any errors.
+   */
+  @Test(dataProvider = "invalidasciidata")
+  public void testEncode(final char myChar) throws Exception
+  {
+    assertEquals(ASCIICharProp.valueOf(myChar), null);
+  }
+
+
+
+  /**
+   * Tests whether a character is a valid ascii character or not.
+   *
+   * @param myChar
+   *          The character that needs to be verified.
+   * @param isUpper
+   *          Whether it is uppercase
+   * @param hexValue
+   *          The hexadecimal value
+   * @param decimalValue
+   *          The decimal value
+   * @param isLetter
+   *          Whether the character is a letter
+   * @param isDigit
+   *          Whether the character is a digit
+   * @param isKeyChar
+   *          Whether the character is a key char.
+   * @throws Exception
+   *           In case of any errors.
+   */
+  @Test(dataProvider = "validasciidata")
+  public void testEncode(final char myChar, final Boolean isUpper,
+      final Integer hexValue, final Integer decimalValue,
+      final Boolean isLetter, final Boolean isDigit, final Boolean isKeyChar)
+      throws Exception
+  {
+    final ASCIICharProp myProp = ASCIICharProp.valueOf(myChar);
+
+    // check letter.
+    if (isLetter)
+    {
+      assertTrue(myProp.isLetter());
+      // Check case.
+      if (isUpper)
+      {
+        assertTrue(myProp.isUpperCase());
+      }
+      else
+      {
+        assertTrue(myProp.isLowerCase());
+      }
+    }
+
+    // check digit.
+    if (isDigit)
+    {
+      assertTrue(myProp.isDigit());
+    }
+
+    if (isLetter || isDigit)
+    {
+      // Check hex.
+      final int hex = myProp.hexValue();
+      final int hex1 = hexValue.intValue();
+      assertEquals(myProp.hexValue(), hexValue.intValue());
+      // Decimal value.
+      assertEquals(myProp.decimalValue(), decimalValue.intValue());
+      // Check if it is equal to itself.
+      assertEquals(myProp.charValue(), myChar);
+      assertEquals(myProp.compareTo(ASCIICharProp.valueOf(myChar)), 0);
+    }
+
+    // keychar.
+    if (isKeyChar)
+    {
+      assertTrue(myProp.isKeyChar());
+    }
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/Base64TestCase.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/Base64TestCase.java
new file mode 100644
index 0000000..4218ec1
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/Base64TestCase.java
@@ -0,0 +1,238 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.util;
+
+
+
+import java.util.Arrays;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.LocalizedIllegalArgumentException;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * This class defines a set of tests for the {@link org.opends.sdk.util.Base64}
+ * class.
+ */
+public final class Base64TestCase extends UtilTestCase
+{
+  // Look up table for converting hex chars to byte values.
+  private static final byte[] hexToByte = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1, 10,
+      11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14,
+      15, -1, -1, -1, -1, -1, -1, -1, -1, -1 - 1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1 };
+
+
+
+  /**
+   * Base 64 invalid test data provider.
+   *
+   * @return Returns an array of invalid encoded base64 data.
+   */
+  @DataProvider(name = "invalidData")
+  public Object[][] createInvalidData()
+  {
+    // FIXME: fix cases ==== and ==x=
+
+    return new Object[][] { { "=" }, { "==" }, { "===" }, { "A" }, { "AA" },
+        { "AAA" }, { "AA`=" }, { "AA~=" }, { "AA!=" }, { "AA@=" }, { "AA#=" },
+        { "AA$=" }, { "AA%=" }, { "AA^=" }, { "AA*=" }, { "AA(=" }, { "AA)=" },
+        { "AA_=" }, { "AA-=" }, { "AA{=" }, { "AA}=" }, { "AA|=" }, { "AA[=" },
+        { "AA]=" }, { "AA\\=" }, { "AA;=" }, { "AA'=" }, { "AA\"=" },
+        { "AA:=" }, { "AA,=" }, { "AA.=" }, { "AA<=" }, { "AA>=" }, { "AA?=" },
+        { "AA;=" } };
+  }
+
+
+
+  /**
+   * Base 64 valid test data provider.
+   *
+   * @return Returns an array of decoded and valid encoded base64 data.
+   */
+  @DataProvider(name = "validData")
+  public Object[][] createValidData()
+  {
+    return new Object[][] {
+        { "", "" },
+        { "00", "AA==" },
+        { "01", "AQ==" },
+        { "02", "Ag==" },
+        { "03", "Aw==" },
+        { "04", "BA==" },
+        { "05", "BQ==" },
+        { "06", "Bg==" },
+        { "07", "Bw==" },
+        { "0000", "AAA=" },
+        { "000000", "AAAA" },
+        { "00000000", "AAAAAA==" },
+        {
+            "000102030405060708090a0b0c0d0e0f"
+                + "101112131415161718191a1b1c1d1e1f"
+                + "202122232425262728292a2b2c2d2e2f"
+                + "303132333435363738393a3b3c3d3e3f"
+                + "404142434445464748494a4b4c4d4e4f"
+                + "505152535455565758595a5b5c5d5e5f"
+                + "606162636465666768696a6b6c6d6e6f"
+                + "707172737475767778797a7b7c7d7e7f"
+                + "808182838485868788898a8b8c8d8e8f"
+                + "909192939495969798999a9b9c9d9e9f"
+                + "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
+                + "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
+                + "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
+                + "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
+                + "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
+                + "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff",
+            "AAECAwQFBgcICQoLDA0ODxAREhMUFRYXGBkaGxwdHh8gISIjJCUmJygpKissLS4v"
+                + "MDEyMzQ1Njc4OTo7PD0+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5f"
+                + "YGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fn+AgYKDhIWGh4iJiouMjY6P"
+                + "kJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8vb6/"
+                + "wMHCw8TFxsfIycrLzM3Oz9DR0tPU1dbX2Nna29zd3t/g4eLj5OXm5+jp6uvs7e7v"
+                + "8PHy8/T19vf4+fr7/P3+/w==" }, };
+  }
+
+
+
+  /**
+   * Tests the decode method against invalid data.
+   *
+   * @param encodedData
+   *          The invalid encoded data.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "invalidData", expectedExceptions = { LocalizedIllegalArgumentException.class })
+  public void testDecodeInvalidData(final String encodedData) throws Exception
+  {
+    Assert.fail("Expected exception but got result: "
+        + Arrays.toString(new ByteString[] { Base64.decode(encodedData) }));
+  }
+
+
+
+  /**
+   * Tests the decode method against valid data.
+   *
+   * @param hexData
+   *          The decoded hex data.
+   * @param encodedData
+   *          The encoded data.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "validData")
+  public void testDecodeValidData(final String hexData, final String encodedData)
+      throws Exception
+  {
+    final byte[] data = getBytes(hexData);
+    final byte[] decodedData = Base64.decode(encodedData).toByteArray();
+    Assert.assertEquals(decodedData, data);
+  }
+
+
+
+  /**
+   * Tests the encode method.
+   *
+   * @param hexData
+   *          The decoded hex data.
+   * @param encodedData
+   *          The encoded data.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "validData")
+  public void testEncode(final String hexData, final String encodedData)
+      throws Exception
+  {
+    final byte[] data = getBytes(hexData);
+    final String base64 = Base64.encode(ByteString.wrap(data));
+    Assert.assertEquals(base64, encodedData);
+  }
+
+
+
+  /**
+   * Decode a hex string to a byte-array.
+   *
+   * @param hexData
+   *          The string of hex.
+   * @return Returns the decoded byte array.
+   */
+  private byte[] getBytes(final String hexData)
+  {
+    final int sz = hexData.length();
+
+    if ((sz % 2) != 0)
+    {
+      throw new IllegalArgumentException(
+          "Hex string does not contain an even number of hex digits");
+    }
+
+    final byte[] bytes = new byte[sz / 2];
+
+    for (int i = 0, j = 0; i < sz; i += 2, j++)
+    {
+      int c = hexData.codePointAt(i);
+      if ((c & 0x7f) != c)
+      {
+        throw new IllegalArgumentException("Hex string contains non-hex digits");
+      }
+
+      final byte b1 = hexToByte[c];
+      if (b1 < 0)
+      {
+        throw new IllegalArgumentException("Hex string contains non-hex digits");
+      }
+
+      c = hexData.codePointAt(i + 1);
+      if ((c & 0x7f) != c)
+      {
+        throw new IllegalArgumentException("Hex string contains non-hex digits");
+      }
+
+      final byte b2 = hexToByte[c];
+      if (b2 < 0)
+      {
+        throw new IllegalArgumentException("Hex string contains non-hex digits");
+      }
+
+      bytes[j] = (byte) ((b1 << 4) | b2);
+    }
+
+    return bytes;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTest.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTestCase.java
similarity index 83%
rename from sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTest.java
rename to sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTestCase.java
index b249090..6a8b34a 100644
--- a/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTest.java
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTestCase.java
@@ -34,7 +34,6 @@
 import java.util.GregorianCalendar;
 import java.util.TimeZone;
 
-import org.opends.sdk.OpenDSTestCase;
 import org.testng.Assert;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
@@ -44,67 +43,8 @@
 /**
  * Test {@code StaticUtils}.
  */
-@Test(groups = { "precommit", "types", "sdk" }, sequential = true)
-public final class StaticUtilsTest extends OpenDSTestCase
+public final class StaticUtilsTestCase extends UtilTestCase
 {
-  @DataProvider(name = "dataForToLowerCase")
-  public Object[][] dataForToLowerCase()
-  {
-    // Value, toLowerCase or null if identity
-    return new Object[][] {
-        { "", null },
-        { " ", null },
-        { "   ", null },
-        { "12345", null },
-        {
-            "abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./",
-            null },
-        {
-            "Aabcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./",
-            "aabcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./" },
-        {
-            "abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./A",
-            "abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./a" },
-        { "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz" },
-        { "\u00c7edilla", "\u00e7edilla" },
-        { "ced\u00cdlla", "ced\u00edlla" }, };
-  }
-
-
-
-  @Test(dataProvider = "dataForToLowerCase")
-  public void testToLowerCaseString(String s, String expected)
-  {
-    String actual = StaticUtils.toLowerCase(s);
-    if (expected == null)
-    {
-      Assert.assertSame(actual, s);
-    }
-    else
-    {
-      Assert.assertEquals(actual, expected);
-    }
-  }
-
-
-
-  @Test(dataProvider = "dataForToLowerCase")
-  public void testToLowerCaseStringBuilder(String s, String expected)
-  {
-    StringBuilder builder = new StringBuilder();
-    String actual = StaticUtils.toLowerCase(s, builder).toString();
-    if (expected == null)
-    {
-      Assert.assertEquals(actual, s);
-    }
-    else
-    {
-      Assert.assertEquals(actual, expected);
-    }
-  }
-
-
-
   /**
    * Create data for format(...) tests.
    *
@@ -156,39 +96,26 @@
 
 
 
-  /**
-   * Tests {@link StaticUtils#formatAsGeneralizedTime(long)} .
-   *
-   * @param yyyy
-   *          The year.
-   * @param MM
-   *          The month.
-   * @param dd
-   *          The day.
-   * @param HH
-   *          The hour.
-   * @param mm
-   *          The minute.
-   * @param ss
-   *          The second.
-   * @param SSS
-   *          The milli-seconds.
-   * @param expected
-   *          The expected generalized time formatted string.
-   * @throws Exception
-   *           If an unexpected error occurred.
-   */
-  @Test(dataProvider = "createFormatData")
-  public void testFormatLong(int yyyy, int MM, int dd, int HH, int mm,
-      int ss, int SSS, String expected) throws Exception
+  @DataProvider(name = "dataForToLowerCase")
+  public Object[][] dataForToLowerCase()
   {
-    Calendar calendar = new GregorianCalendar(TimeZone
-        .getTimeZone("UTC"));
-    calendar.set(yyyy, MM, dd, HH, mm, ss);
-    calendar.set(Calendar.MILLISECOND, SSS);
-    long time = calendar.getTimeInMillis();
-    String actual = StaticUtils.formatAsGeneralizedTime(time);
-    Assert.assertEquals(actual, expected);
+    // Value, toLowerCase or null if identity
+    return new Object[][] {
+        { "", null },
+        { " ", null },
+        { "   ", null },
+        { "12345", null },
+        {
+            "abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./",
+            null },
+        {
+            "Aabcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./",
+            "aabcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./" },
+        {
+            "abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./A",
+            "abcdefghijklmnopqrstuvwxyz1234567890`~!@#$%^&*()_-+={}|[]\\:\";'<>?,./a" },
+        { "ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz" },
+        { "\u00c7edilla", "\u00e7edilla" }, { "ced\u00cdlla", "ced\u00edlla" }, };
   }
 
 
@@ -216,15 +143,85 @@
    *           If an unexpected error occurred.
    */
   @Test(dataProvider = "createFormatData")
-  public void testFormatDate(int yyyy, int MM, int dd, int HH, int mm,
-      int ss, int SSS, String expected) throws Exception
+  public void testFormatDate(final int yyyy, final int MM, final int dd,
+      final int HH, final int mm, final int ss, final int SSS,
+      final String expected) throws Exception
   {
-    Calendar calendar = new GregorianCalendar(TimeZone
-        .getTimeZone("UTC"));
+    final Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
     calendar.set(yyyy, MM, dd, HH, mm, ss);
     calendar.set(Calendar.MILLISECOND, SSS);
-    Date time = new Date(calendar.getTimeInMillis());
-    String actual = StaticUtils.formatAsGeneralizedTime(time);
+    final Date time = new Date(calendar.getTimeInMillis());
+    final String actual = StaticUtils.formatAsGeneralizedTime(time);
     Assert.assertEquals(actual, expected);
   }
+
+
+
+  /**
+   * Tests {@link StaticUtils#formatAsGeneralizedTime(long)} .
+   *
+   * @param yyyy
+   *          The year.
+   * @param MM
+   *          The month.
+   * @param dd
+   *          The day.
+   * @param HH
+   *          The hour.
+   * @param mm
+   *          The minute.
+   * @param ss
+   *          The second.
+   * @param SSS
+   *          The milli-seconds.
+   * @param expected
+   *          The expected generalized time formatted string.
+   * @throws Exception
+   *           If an unexpected error occurred.
+   */
+  @Test(dataProvider = "createFormatData")
+  public void testFormatLong(final int yyyy, final int MM, final int dd,
+      final int HH, final int mm, final int ss, final int SSS,
+      final String expected) throws Exception
+  {
+    final Calendar calendar = new GregorianCalendar(TimeZone.getTimeZone("UTC"));
+    calendar.set(yyyy, MM, dd, HH, mm, ss);
+    calendar.set(Calendar.MILLISECOND, SSS);
+    final long time = calendar.getTimeInMillis();
+    final String actual = StaticUtils.formatAsGeneralizedTime(time);
+    Assert.assertEquals(actual, expected);
+  }
+
+
+
+  @Test(dataProvider = "dataForToLowerCase")
+  public void testToLowerCaseString(final String s, final String expected)
+  {
+    final String actual = StaticUtils.toLowerCase(s);
+    if (expected == null)
+    {
+      Assert.assertSame(actual, s);
+    }
+    else
+    {
+      Assert.assertEquals(actual, expected);
+    }
+  }
+
+
+
+  @Test(dataProvider = "dataForToLowerCase")
+  public void testToLowerCaseStringBuilder(final String s, final String expected)
+  {
+    final StringBuilder builder = new StringBuilder();
+    final String actual = StaticUtils.toLowerCase(s, builder).toString();
+    if (expected == null)
+    {
+      Assert.assertEquals(actual, s);
+    }
+    else
+    {
+      Assert.assertEquals(actual, expected);
+    }
+  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StringPrepProfileTestCase.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StringPrepProfileTestCase.java
new file mode 100644
index 0000000..702fedb
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StringPrepProfileTestCase.java
@@ -0,0 +1,119 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package com.sun.opends.sdk.util;
+
+
+
+import static org.testng.Assert.assertEquals;
+
+import org.opends.sdk.Assertion;
+import org.opends.sdk.ByteString;
+import org.opends.sdk.ConditionResult;
+import org.opends.sdk.schema.MatchingRule;
+import org.opends.sdk.schema.Schema;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * This Test Class tests various matching rules for their compability against
+ * RFC 4517,4518 and 3454.
+ */
+public class StringPrepProfileTestCase extends UtilTestCase
+{
+  /**
+   * Tests the stringprep preparation sans any case folding. This is applicable
+   * to case exact matching rules only.
+   */
+  @Test(dataProvider = "exactRuleData")
+  public void testStringPrepNoCaseFold(final String value1,
+      final String value2, final ConditionResult result) throws Exception
+  {
+    // Take any caseExact matching rule.
+    final MatchingRule rule = Schema.getCoreSchema()
+        .getMatchingRule("2.5.13.5");
+    final Assertion assertion = rule.getAssertion(ByteString.valueOf(value1));
+    final ByteString normalizedValue2 = rule.normalizeAttributeValue(ByteString
+        .valueOf(value2));
+    final ConditionResult liveResult = assertion.matches(normalizedValue2);
+    assertEquals(result, liveResult);
+  }
+
+
+
+  /**
+   * Tests the stringprep preparation with case folding. This is applicable to
+   * case ignore matching rules only.
+   */
+  @Test(dataProvider = "caseFoldRuleData")
+  public void testStringPrepWithCaseFold(final String value1,
+      final String value2, final ConditionResult result) throws Exception
+  {
+    // Take any caseExact matching rule.
+    final MatchingRule rule = Schema.getCoreSchema()
+        .getMatchingRule("2.5.13.2");
+    final Assertion assertion = rule.getAssertion(ByteString.valueOf(value1));
+    final ByteString normalizedValue2 = rule.normalizeAttributeValue(ByteString
+        .valueOf(value2));
+    final ConditionResult liveResult = assertion.matches(normalizedValue2);
+    assertEquals(result, liveResult);
+  }
+
+
+
+  // Generates data for case exact matching rules.
+  @DataProvider(name = "exactRuleData")
+  private Object[][] createExactRuleData()
+  {
+    return new Object[][] { { "12345678", "12345678", ConditionResult.TRUE },
+        { "ABC45678", "ABC45678", ConditionResult.TRUE },
+        { "ABC45678", "abc45678", ConditionResult.FALSE },
+        { "\u0020foo\u0020bar\u0020\u0020", "foo bar", ConditionResult.TRUE },
+        { "test\u00AD\u200D", "test", ConditionResult.TRUE },
+        { "foo\u000Bbar", "foo\u0020bar", ConditionResult.TRUE },
+        { "foo\u070Fbar", "foobar", ConditionResult.TRUE }, };
+  }
+
+
+
+  // Generates data for case ignore matching rules.
+  @DataProvider(name = "caseFoldRuleData")
+  private Object[][] createIgnoreRuleData()
+  {
+    return new Object[][] { { "12345678", "12345678", ConditionResult.TRUE },
+        { "ABC45678", "abc45678", ConditionResult.TRUE },
+        { "\u0020foo\u0020bar\u0020\u0020", "foo bar", ConditionResult.TRUE },
+        { "test\u00AD\u200D", "test", ConditionResult.TRUE },
+        { "foo\u000Bbar", "foo\u0020bar", ConditionResult.TRUE },
+        { "foo\u070Fbar", "foobar", ConditionResult.TRUE },
+        { "foo\u0149bar", "foo\u02BC\u006Ebar", ConditionResult.TRUE },
+        { "foo\u017Bbar", "foo\u017Cbar", ConditionResult.TRUE },
+        { "foo\u017BBAR", "foo\u017Cbar", ConditionResult.TRUE }, };
+  }
+}
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/UtilTestCase.java
similarity index 68%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/UtilTestCase.java
index 62b3ae3..af703f4 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/UtilTestCase.java
@@ -22,21 +22,23 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package com.sun.opends.sdk.util;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.opends.sdk.OpenDSTestCase;
+import org.testng.annotations.Test;
 
 
 
 /**
- * Password call-back.
+ * An abstract class that all util unit tests should extend. Util represents the
+ * classes found directly under the package org.opends.sdk.util.
  */
-public interface PasswordCallbackHandler
+@Test(groups = { "precommit", "util", "sdk" }, sequential = true)
+public abstract class UtilTestCase extends OpenDSTestCase
 {
-  public boolean handle(PasswordCallback callback);
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTestCase.java
similarity index 68%
rename from sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTest.java
rename to sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTestCase.java
index 5819963..76da7f8 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTestCase.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 200-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
@@ -36,102 +36,29 @@
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import org.opends.sdk.LocalizedIllegalArgumentException;
-
 
 
 /**
  * Test {@code AttributeDescription}.
  */
-@Test(groups = { "precommit", "types", "sdk" }, sequential = true)
-public final class AttributeDescriptionTest extends OpenDSTestCase
+public final class AttributeDescriptionTestCase extends OpenDSTestCase
 {
-  @DataProvider(name = "dataForValueOfNoSchema")
-  public Object[][] dataForValueOfNoSchema()
+  @DataProvider(name = "dataForCompareCoreSchema")
+  public Object[][] dataForCompareCoreSchema()
   {
-    // Value, type, options, containsOptions("foo")
-    return new Object[][] {
-        { "cn", "cn", new String[0], false },
-        { " cn ", "cn", new String[0], false },
-        { "  cn  ", "cn", new String[0], false },
-        { "CN", "CN", new String[0], false },
-        { "1", "1", new String[0], false },
-        { "1.2", "1.2", new String[0], false },
-        { "1.2.3", "1.2.3", new String[0], false },
-        { "111.222.333", "111.222.333", new String[0], false },
-        { "objectClass", "objectClass", new String[0], false },
-        { "cn;foo", "cn", new String[] { "foo" }, true },
-        { "cn;FOO", "cn", new String[] { "FOO" }, true },
-        { "cn;bar", "cn", new String[] { "bar" }, false },
-        { "cn;BAR", "cn", new String[] { "BAR" }, false },
-        { "cn;foo;bar", "cn", new String[] { "foo", "bar" }, true },
-        { "cn;FOO;bar", "cn", new String[] { "FOO", "bar" }, true },
-        { "cn;foo;BAR", "cn", new String[] { "foo", "BAR" }, true },
-        { "cn;FOO;BAR", "cn", new String[] { "FOO", "BAR" }, true },
-        { "cn;bar;FOO", "cn", new String[] { "bar", "FOO" }, true },
-        { "cn;BAR;foo", "cn", new String[] { "BAR", "foo" }, true },
-        { "cn;bar;FOO", "cn", new String[] { "bar", "FOO" }, true },
-        { "cn;BAR;FOO", "cn", new String[] { "BAR", "FOO" }, true },
-        { " cn;BAR;FOO ", "cn", new String[] { "BAR", "FOO" }, true },
-        { "  cn;BAR;FOO  ", "cn", new String[] { "BAR", "FOO" }, true },
-        { "cn;xxx;yyy;zzz", "cn", new String[] { "xxx", "yyy", "zzz" },
-            false },
-        { "cn;zzz;YYY;xxx", "cn", new String[] { "zzz", "YYY", "xxx" },
-            false }, };
-  }
-
-
-
-  @Test(dataProvider = "dataForValueOfNoSchema")
-  public void testValueOfNoSchema(String ad, String at,
-      String[] options, boolean containsFoo)
-  {
-    AttributeDescription attributeDescription =
-        AttributeDescription.valueOf(ad, Schema.getEmptySchema());
-
-    Assert.assertEquals(attributeDescription.toString(), ad);
-
-    Assert.assertEquals(attributeDescription.getAttributeType()
-        .getNameOrOID(), at);
-
-    Assert.assertFalse(attributeDescription.isObjectClass());
-
-    if (options.length == 0)
-    {
-      Assert.assertFalse(attributeDescription.hasOptions());
-    }
-    else
-    {
-      Assert.assertTrue(attributeDescription.hasOptions());
-    }
-
-    Assert.assertFalse(attributeDescription.containsOption("dummy"));
-    if (containsFoo)
-    {
-      Assert.assertTrue(attributeDescription.containsOption("foo"));
-      Assert.assertTrue(attributeDescription.containsOption("FOO"));
-      Assert.assertTrue(attributeDescription.containsOption("FoO"));
-    }
-    else
-    {
-      Assert.assertFalse(attributeDescription.containsOption("foo"));
-      Assert.assertFalse(attributeDescription.containsOption("FOO"));
-      Assert.assertFalse(attributeDescription.containsOption("FoO"));
-    }
-
-    for (String option : options)
-    {
-      Assert.assertTrue(attributeDescription.containsOption(option));
-    }
-
-    Iterator<String> iterator =
-        attributeDescription.getOptions().iterator();
-    for (int i = 0; i < options.length; i++)
-    {
-      Assert.assertTrue(iterator.hasNext());
-      Assert.assertEquals(iterator.next(), options[i]);
-    }
-    Assert.assertFalse(iterator.hasNext());
+    // AD1, AD2, compare result, isSubtype, isSuperType
+    return new Object[][] { { "cn", "cn", 0, true, true },
+        { "cn", "commonName", 0, true, true },
+        { " cn", "commonName ", 0, true, true },
+        { "commonName", "cn", 0, true, true },
+        { "commonName", "commonName", 0, true, true },
+        { "cn", "objectClass", 1, false, false },
+        { "objectClass", "cn", -1, false, false },
+        { "name", "cn", 1, false, true }, { "cn", "name", -1, true, false },
+        { "name;foo", "cn", 1, false, false },
+        { "cn;foo", "name", -1, true, false },
+        { "name", "cn;foo", 1, false, true },
+        { "cn", "name;foo", -1, false, false }, };
   }
 
 
@@ -170,74 +97,12 @@
 
 
 
-  @Test(dataProvider = "dataForCompareNoSchema")
-  public void testCompareNoSchema(String ad1, String ad2, int compare,
-      boolean isSubType, boolean isSuperType)
+  @DataProvider(name = "dataForValueOfCoreSchema")
+  public Object[][] dataForValueOfCoreSchema()
   {
-    AttributeDescription attributeDescription1 =
-        AttributeDescription.valueOf(ad1, Schema.getEmptySchema());
-
-    AttributeDescription attributeDescription2 =
-        AttributeDescription.valueOf(ad2, Schema.getEmptySchema());
-
-    // Identity.
-    Assert.assertTrue(attributeDescription1
-        .equals(attributeDescription1));
-    Assert.assertTrue(attributeDescription1
-        .compareTo(attributeDescription1) == 0);
-    Assert.assertTrue(attributeDescription1
-        .isSubTypeOf(attributeDescription1));
-    Assert.assertTrue(attributeDescription1
-        .isSuperTypeOf(attributeDescription1));
-
-    if (compare == 0)
-    {
-      Assert.assertTrue(attributeDescription1
-          .equals(attributeDescription2));
-      Assert.assertTrue(attributeDescription2
-          .equals(attributeDescription1));
-      Assert.assertTrue(attributeDescription1
-          .compareTo(attributeDescription2) == 0);
-      Assert.assertTrue(attributeDescription2
-          .compareTo(attributeDescription1) == 0);
-
-      Assert.assertTrue(attributeDescription1
-          .isSubTypeOf(attributeDescription2));
-      Assert.assertTrue(attributeDescription1
-          .isSuperTypeOf(attributeDescription2));
-      Assert.assertTrue(attributeDescription2
-          .isSubTypeOf(attributeDescription1));
-      Assert.assertTrue(attributeDescription2
-          .isSuperTypeOf(attributeDescription1));
-    }
-    else
-    {
-      Assert.assertFalse(attributeDescription1
-          .equals(attributeDescription2));
-      Assert.assertFalse(attributeDescription2
-          .equals(attributeDescription1));
-
-      if (compare < 0)
-      {
-        Assert.assertTrue(attributeDescription1
-            .compareTo(attributeDescription2) < 0);
-        Assert.assertTrue(attributeDescription2
-            .compareTo(attributeDescription1) > 0);
-      }
-      else
-      {
-        Assert.assertTrue(attributeDescription1
-            .compareTo(attributeDescription2) > 0);
-        Assert.assertTrue(attributeDescription2
-            .compareTo(attributeDescription1) < 0);
-      }
-
-      Assert.assertEquals(attributeDescription1
-          .isSubTypeOf(attributeDescription2), isSubType);
-
-      Assert.assertEquals(attributeDescription1
-          .isSuperTypeOf(attributeDescription2), isSuperType);
-    }
+    // Value, type, isObjectClass
+    return new Object[][] { { "cn", "cn", false }, { "CN", "cn", false },
+        { "commonName", "cn", false }, { "objectclass", "objectClass", true }, };
   }
 
 
@@ -245,113 +110,76 @@
   @DataProvider(name = "dataForValueOfInvalidAttributeDescriptions")
   public Object[][] dataForValueOfInvalidAttributeDescriptions()
   {
-    return new Object[][] { { "" }, { " " }, { ";" }, { " ; " },
-        { "0cn" }, { "cn." }, { "cn;foo+bar" }, { "cn;foo;foo+bar" },
-        { ";foo" }, { "cn;" }, { "cn;;foo" }, { "cn; ;foo" },
-        { "cn;foo;" }, { "cn;foo; " }, { "cn;foo;;bar" },
-        { "cn;foo; ;bar" }, { "cn;foo;bar;;" }, { "1a" }, { "1.a" },
-        { "1-" }, { "1.1a" }, { "1.1.a" }, };
+    return new Object[][] { { "" }, { " " }, { ";" }, { " ; " }, { "0cn" },
+        { "cn." }, { "cn;foo+bar" }, { "cn;foo;foo+bar" }, { ";foo" },
+        { "cn;" }, { "cn;;foo" }, { "cn; ;foo" }, { "cn;foo;" },
+        { "cn;foo; " }, { "cn;foo;;bar" }, { "cn;foo; ;bar" },
+        { "cn;foo;bar;;" }, { "1a" }, { "1.a" }, { "1-" }, { "1.1a" },
+        { "1.1.a" }, };
   }
 
 
 
-  // FIXME: none of these pass! The valueOf method is far to lenient.
-  @Test(dataProvider = "dataForValueOfInvalidAttributeDescriptions",
-      expectedExceptions = LocalizedIllegalArgumentException.class)
-  public void testValueOfInvalidAttributeDescriptions(String ad)
+  @DataProvider(name = "dataForValueOfNoSchema")
+  public Object[][] dataForValueOfNoSchema()
   {
-    AttributeDescription.valueOf(ad, Schema.getEmptySchema());
-  }
-
-
-
-  @DataProvider(name = "dataForValueOfCoreSchema")
-  public Object[][] dataForValueOfCoreSchema()
-  {
-    // Value, type, isObjectClass
-    return new Object[][] { { "cn", "cn", false },
-        { "CN", "cn", false }, { "commonName", "cn", false },
-        { "objectclass", "objectClass", true }, };
-  }
-
-
-
-  @Test(dataProvider = "dataForValueOfCoreSchema")
-  public void testValueOfCoreSchema(String ad, String at,
-      boolean isObjectClass)
-  {
-    AttributeDescription attributeDescription =
-        AttributeDescription.valueOf(ad, Schema.getCoreSchema());
-
-    Assert.assertEquals(attributeDescription.toString(), ad);
-
-    Assert.assertEquals(attributeDescription.getAttributeType()
-        .getNameOrOID(), at);
-
-    Assert.assertEquals(attributeDescription.isObjectClass(),
-        isObjectClass);
-
-    Assert.assertFalse(attributeDescription.hasOptions());
-    Assert.assertFalse(attributeDescription.containsOption("dummy"));
-
-    Iterator<String> iterator =
-        attributeDescription.getOptions().iterator();
-    Assert.assertFalse(iterator.hasNext());
-  }
-
-
-
-  @DataProvider(name = "dataForCompareCoreSchema")
-  public Object[][] dataForCompareCoreSchema()
-  {
-    // AD1, AD2, compare result, isSubtype, isSuperType
-    return new Object[][] { { "cn", "cn", 0, true, true },
-        { "cn", "commonName", 0, true, true },
-        { " cn", "commonName ", 0, true, true },
-        { "commonName", "cn", 0, true, true },
-        { "commonName", "commonName", 0, true, true },
-        { "cn", "objectClass", 1, false, false },
-        { "objectClass", "cn", -1, false, false },
-        { "name", "cn", 1, false, true },
-        { "cn", "name", -1, true, false },
-        { "name;foo", "cn", 1, false, false },
-        { "cn;foo", "name", -1, true, false },
-        { "name", "cn;foo", 1, false, true },
-        { "cn", "name;foo", -1, false, false }, };
+    // Value, type, options, containsOptions("foo")
+    return new Object[][] {
+        { "cn", "cn", new String[0], false },
+        { " cn ", "cn", new String[0], false },
+        { "  cn  ", "cn", new String[0], false },
+        { "CN", "CN", new String[0], false },
+        { "1", "1", new String[0], false },
+        { "1.2", "1.2", new String[0], false },
+        { "1.2.3", "1.2.3", new String[0], false },
+        { "111.222.333", "111.222.333", new String[0], false },
+        { "objectClass", "objectClass", new String[0], false },
+        { "cn;foo", "cn", new String[] { "foo" }, true },
+        { "cn;FOO", "cn", new String[] { "FOO" }, true },
+        { "cn;bar", "cn", new String[] { "bar" }, false },
+        { "cn;BAR", "cn", new String[] { "BAR" }, false },
+        { "cn;foo;bar", "cn", new String[] { "foo", "bar" }, true },
+        { "cn;FOO;bar", "cn", new String[] { "FOO", "bar" }, true },
+        { "cn;foo;BAR", "cn", new String[] { "foo", "BAR" }, true },
+        { "cn;FOO;BAR", "cn", new String[] { "FOO", "BAR" }, true },
+        { "cn;bar;FOO", "cn", new String[] { "bar", "FOO" }, true },
+        { "cn;BAR;foo", "cn", new String[] { "BAR", "foo" }, true },
+        { "cn;bar;FOO", "cn", new String[] { "bar", "FOO" }, true },
+        { "cn;BAR;FOO", "cn", new String[] { "BAR", "FOO" }, true },
+        { " cn;BAR;FOO ", "cn", new String[] { "BAR", "FOO" }, true },
+        { "  cn;BAR;FOO  ", "cn", new String[] { "BAR", "FOO" }, true },
+        { "cn;xxx;yyy;zzz", "cn", new String[] { "xxx", "yyy", "zzz" }, false },
+        { "cn;zzz;YYY;xxx", "cn", new String[] { "zzz", "YYY", "xxx" }, false }, };
   }
 
 
 
   @Test(dataProvider = "dataForCompareCoreSchema")
-  public void testCompareCoreSchema(String ad1, String ad2,
-      int compare, boolean isSubType, boolean isSuperType)
+  public void testCompareCoreSchema(final String ad1, final String ad2,
+      final int compare, final boolean isSubType, final boolean isSuperType)
   {
-    AttributeDescription attributeDescription1 =
-        AttributeDescription.valueOf(ad1, Schema.getCoreSchema());
+    final AttributeDescription attributeDescription1 = AttributeDescription
+        .valueOf(ad1, Schema.getCoreSchema());
 
-    AttributeDescription attributeDescription2 =
-        AttributeDescription.valueOf(ad2, Schema.getCoreSchema());
+    final AttributeDescription attributeDescription2 = AttributeDescription
+        .valueOf(ad2, Schema.getCoreSchema());
 
     // Identity.
-    Assert.assertTrue(attributeDescription1
-        .equals(attributeDescription1));
-    Assert.assertTrue(attributeDescription1
-        .compareTo(attributeDescription1) == 0);
-    Assert.assertTrue(attributeDescription1
-        .isSubTypeOf(attributeDescription1));
+    Assert.assertTrue(attributeDescription1.equals(attributeDescription1));
+    Assert
+        .assertTrue(attributeDescription1.compareTo(attributeDescription1) == 0);
+    Assert.assertTrue(attributeDescription1.isSubTypeOf(attributeDescription1));
     Assert.assertTrue(attributeDescription1
         .isSuperTypeOf(attributeDescription1));
 
     if (compare == 0)
     {
-      Assert.assertTrue(attributeDescription1
-          .equals(attributeDescription2));
-      Assert.assertTrue(attributeDescription2
-          .equals(attributeDescription1));
-      Assert.assertTrue(attributeDescription1
-          .compareTo(attributeDescription2) == 0);
-      Assert.assertTrue(attributeDescription2
-          .compareTo(attributeDescription1) == 0);
+      Assert.assertTrue(attributeDescription1.equals(attributeDescription2));
+      Assert.assertTrue(attributeDescription2.equals(attributeDescription1));
+      Assert
+          .assertTrue(attributeDescription1.compareTo(attributeDescription2) == 0);
+      Assert
+          .assertTrue(attributeDescription2.compareTo(attributeDescription1) == 0);
 
       Assert.assertTrue(attributeDescription1
           .isSubTypeOf(attributeDescription2));
@@ -364,10 +192,8 @@
     }
     else
     {
-      Assert.assertFalse(attributeDescription1
-          .equals(attributeDescription2));
-      Assert.assertFalse(attributeDescription2
-          .equals(attributeDescription1));
+      Assert.assertFalse(attributeDescription1.equals(attributeDescription2));
+      Assert.assertFalse(attributeDescription2.equals(attributeDescription1));
 
       if (compare < 0)
       {
@@ -391,4 +217,157 @@
           .isSuperTypeOf(attributeDescription2), isSuperType);
     }
   }
+
+
+
+  @Test(dataProvider = "dataForCompareNoSchema")
+  public void testCompareNoSchema(final String ad1, final String ad2,
+      final int compare, final boolean isSubType, final boolean isSuperType)
+  {
+    final AttributeDescription attributeDescription1 = AttributeDescription
+        .valueOf(ad1, Schema.getEmptySchema());
+
+    final AttributeDescription attributeDescription2 = AttributeDescription
+        .valueOf(ad2, Schema.getEmptySchema());
+
+    // Identity.
+    Assert.assertTrue(attributeDescription1.equals(attributeDescription1));
+    Assert
+        .assertTrue(attributeDescription1.compareTo(attributeDescription1) == 0);
+    Assert.assertTrue(attributeDescription1.isSubTypeOf(attributeDescription1));
+    Assert.assertTrue(attributeDescription1
+        .isSuperTypeOf(attributeDescription1));
+
+    if (compare == 0)
+    {
+      Assert.assertTrue(attributeDescription1.equals(attributeDescription2));
+      Assert.assertTrue(attributeDescription2.equals(attributeDescription1));
+      Assert
+          .assertTrue(attributeDescription1.compareTo(attributeDescription2) == 0);
+      Assert
+          .assertTrue(attributeDescription2.compareTo(attributeDescription1) == 0);
+
+      Assert.assertTrue(attributeDescription1
+          .isSubTypeOf(attributeDescription2));
+      Assert.assertTrue(attributeDescription1
+          .isSuperTypeOf(attributeDescription2));
+      Assert.assertTrue(attributeDescription2
+          .isSubTypeOf(attributeDescription1));
+      Assert.assertTrue(attributeDescription2
+          .isSuperTypeOf(attributeDescription1));
+    }
+    else
+    {
+      Assert.assertFalse(attributeDescription1.equals(attributeDescription2));
+      Assert.assertFalse(attributeDescription2.equals(attributeDescription1));
+
+      if (compare < 0)
+      {
+        Assert.assertTrue(attributeDescription1
+            .compareTo(attributeDescription2) < 0);
+        Assert.assertTrue(attributeDescription2
+            .compareTo(attributeDescription1) > 0);
+      }
+      else
+      {
+        Assert.assertTrue(attributeDescription1
+            .compareTo(attributeDescription2) > 0);
+        Assert.assertTrue(attributeDescription2
+            .compareTo(attributeDescription1) < 0);
+      }
+
+      Assert.assertEquals(attributeDescription1
+          .isSubTypeOf(attributeDescription2), isSubType);
+
+      Assert.assertEquals(attributeDescription1
+          .isSuperTypeOf(attributeDescription2), isSuperType);
+    }
+  }
+
+
+
+  @Test(dataProvider = "dataForValueOfCoreSchema")
+  public void testValueOfCoreSchema(final String ad, final String at,
+      final boolean isObjectClass)
+  {
+    final AttributeDescription attributeDescription = AttributeDescription
+        .valueOf(ad, Schema.getCoreSchema());
+
+    Assert.assertEquals(attributeDescription.toString(), ad);
+
+    Assert.assertEquals(attributeDescription.getAttributeType().getNameOrOID(),
+        at);
+
+    Assert.assertEquals(attributeDescription.isObjectClass(), isObjectClass);
+
+    Assert.assertFalse(attributeDescription.hasOptions());
+    Assert.assertFalse(attributeDescription.containsOption("dummy"));
+
+    final Iterator<String> iterator = attributeDescription.getOptions()
+        .iterator();
+    Assert.assertFalse(iterator.hasNext());
+  }
+
+
+
+  // FIXME: none of these pass! The valueOf method is far to lenient.
+  @Test(dataProvider = "dataForValueOfInvalidAttributeDescriptions", expectedExceptions = LocalizedIllegalArgumentException.class)
+  public void testValueOfInvalidAttributeDescriptions(final String ad)
+  {
+    AttributeDescription.valueOf(ad, Schema.getEmptySchema());
+  }
+
+
+
+  @Test(dataProvider = "dataForValueOfNoSchema")
+  public void testValueOfNoSchema(final String ad, final String at,
+      final String[] options, final boolean containsFoo)
+  {
+    final AttributeDescription attributeDescription = AttributeDescription
+        .valueOf(ad, Schema.getEmptySchema());
+
+    Assert.assertEquals(attributeDescription.toString(), ad);
+
+    Assert.assertEquals(attributeDescription.getAttributeType().getNameOrOID(),
+        at);
+
+    Assert.assertFalse(attributeDescription.isObjectClass());
+
+    if (options.length == 0)
+    {
+      Assert.assertFalse(attributeDescription.hasOptions());
+    }
+    else
+    {
+      Assert.assertTrue(attributeDescription.hasOptions());
+    }
+
+    Assert.assertFalse(attributeDescription.containsOption("dummy"));
+    if (containsFoo)
+    {
+      Assert.assertTrue(attributeDescription.containsOption("foo"));
+      Assert.assertTrue(attributeDescription.containsOption("FOO"));
+      Assert.assertTrue(attributeDescription.containsOption("FoO"));
+    }
+    else
+    {
+      Assert.assertFalse(attributeDescription.containsOption("foo"));
+      Assert.assertFalse(attributeDescription.containsOption("FOO"));
+      Assert.assertFalse(attributeDescription.containsOption("FoO"));
+    }
+
+    for (final String option : options)
+    {
+      Assert.assertTrue(attributeDescription.containsOption(option));
+    }
+
+    final Iterator<String> iterator = attributeDescription.getOptions()
+        .iterator();
+    for (final String option : options)
+    {
+      Assert.assertTrue(iterator.hasNext());
+      Assert.assertEquals(iterator.next(), option);
+    }
+    Assert.assertFalse(iterator.hasNext());
+  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/AuthenticatedConnectionFactoryTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/AuthenticatedConnectionFactoryTestCase.java
new file mode 100644
index 0000000..9ff1cd1
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/AuthenticatedConnectionFactoryTestCase.java
@@ -0,0 +1,62 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import org.opends.sdk.requests.Requests;
+
+
+
+/**
+ * Tests the authenticated connection factory.
+ */
+public class AuthenticatedConnectionFactoryTestCase extends
+    ConnectionFactoryTestCase
+{
+  private final AuthenticatedConnectionFactory authFactory = new AuthenticatedConnectionFactory(
+      new LDAPConnectionFactory("localhost", TestCaseUtils.getLdapPort()),
+      Requests.newSimpleBindRequest("", ""));
+
+
+
+  @Override
+  protected FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      final ResultHandler<AsynchronousConnection> handler)
+  {
+    return authFactory.getAsynchronousConnection(handler);
+  }
+
+
+
+  @Override
+  protected Connection getConnection() throws Exception
+  {
+    return authFactory.getConnection();
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteSequenceTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteSequenceTestCase.java
new file mode 100644
index 0000000..0d29541
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteSequenceTestCase.java
@@ -0,0 +1,247 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * Abstract test case for the ByteSequence interface.
+ */
+public abstract class ByteSequenceTestCase extends SdkTestCase
+{
+  /**
+   * ByteSequence data provider that gets the ByteSequence implementation from
+   * the abstract method.
+   *
+   * @return The array of ByteStrings and the bytes it should contain.
+   */
+  @DataProvider(name = "byteSequenceProvider")
+  public Object[][] concreteByteSequenceProvider() throws Exception
+  {
+    return byteSequenceProvider();
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testByteAt(final ByteSequence bs, final byte[] ba)
+  {
+    for (int i = 0; i < ba.length; i++)
+    {
+      Assert.assertEquals(bs.byteAt(i), ba[i]);
+    }
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider", expectedExceptions = IndexOutOfBoundsException.class)
+  public void testByteAtBadIndex1(final ByteSequence bs, final byte[] ba)
+  {
+    bs.byteAt(ba.length);
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider", expectedExceptions = IndexOutOfBoundsException.class)
+  public void testByteAtBadIndex2(final ByteSequence bs, final byte[] ba)
+  {
+    bs.byteAt(-1);
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testCopyTo(final ByteSequence bs, final byte[] ba)
+  {
+    final byte[] newBa = new byte[ba.length];
+    bs.copyTo(newBa);
+    Assert.assertTrue(Arrays.equals(newBa, ba));
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testCopyToByteSequenceBuilder(final ByteSequence bs,
+      final byte[] ba)
+  {
+    final ByteStringBuilder builder = new ByteStringBuilder();
+    bs.copyTo(builder);
+    Assert.assertTrue(Arrays.equals(builder.toByteArray(), ba));
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testCopyToOutputStream(final ByteSequence bs, final byte[] ba)
+      throws Exception
+  {
+    final ByteArrayOutputStream stream = new ByteArrayOutputStream();
+    bs.copyTo(stream);
+    Assert.assertTrue(Arrays.equals(stream.toByteArray(), ba));
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider", expectedExceptions = IndexOutOfBoundsException.class)
+  public void testCopyToWithBadOffset(final ByteSequence bs, final byte[] ba)
+  {
+    bs.copyTo(new byte[0], -1);
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testCopyToWithOffset(final ByteSequence bs, final byte[] ba)
+  {
+    for (int i = 0; i < ba.length * 2; i++)
+    {
+      final byte[] newBa = new byte[ba.length * 2];
+      bs.copyTo(newBa, i);
+
+      final byte[] resultBa = new byte[ba.length * 2];
+      System.arraycopy(ba, 0, resultBa, i, Math.min(ba.length, ba.length * 2
+          - i));
+      Assert.assertTrue(Arrays.equals(newBa, resultBa));
+    }
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testEquals(final ByteSequence bs, final byte[] ba)
+      throws Exception
+  {
+    Assert.assertTrue(bs.equals(ByteString.wrap(ba)));
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testLength(final ByteSequence bs, final byte[] ba)
+      throws Exception
+  {
+    Assert.assertEquals(bs.length(), ba.length);
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testSubSequence(final ByteSequence bs, final byte[] ba)
+  {
+    ByteSequence bsSub = bs.subSequence(0, bs.length() / 2);
+    byte[] baSub = new byte[ba.length / 2];
+    System.arraycopy(ba, 0, baSub, 0, baSub.length);
+    Assert.assertTrue(Arrays.equals(bsSub.toByteArray(), baSub));
+
+    bsSub = bs.subSequence(ba.length / 4, (bs.length() / 4) * 3);
+    baSub = new byte[(bs.length() / 4) * 3 - ba.length / 4];
+    System.arraycopy(ba, ba.length / 4, baSub, 0, baSub.length);
+    Assert.assertTrue(Arrays.equals(bsSub.toByteArray(), baSub));
+
+    bsSub = bs.subSequence(ba.length / 2, bs.length());
+    baSub = new byte[bs.length() - ba.length / 2];
+    System.arraycopy(ba, ba.length / 2, baSub, 0, baSub.length);
+    Assert.assertTrue(Arrays.equals(bsSub.toByteArray(), baSub));
+
+    bsSub = bs.subSequence(0, bs.length());
+    Assert.assertTrue(Arrays.equals(bsSub.toByteArray(), ba));
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider", expectedExceptions = IndexOutOfBoundsException.class)
+  public void testSubSequenceBadStartEnd1(final ByteSequence bs, final byte[] ba)
+  {
+    bs.subSequence(-1, bs.length());
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider", expectedExceptions = IndexOutOfBoundsException.class)
+  public void testSubSequenceBadStartEnd2(final ByteSequence bs, final byte[] ba)
+  {
+    bs.subSequence(0, bs.length() + 1);
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider", expectedExceptions = IndexOutOfBoundsException.class)
+  public void testSubSequenceBadStartEnd3(final ByteSequence bs, final byte[] ba)
+  {
+    bs.subSequence(-1, bs.length() + 1);
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testToByteArray(final ByteSequence bs, final byte[] ba)
+  {
+    Assert.assertTrue(Arrays.equals(bs.toByteArray(), ba));
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testToByteSequence(final ByteSequence bs, final byte[] ba)
+  {
+    Assert.assertTrue(Arrays.equals(bs.toByteString().toByteArray(), ba));
+  }
+
+
+
+  @Test(dataProvider = "byteSequenceProvider")
+  public void testToString(final ByteSequence bs, final byte[] ba)
+  {
+    String str;
+    try
+    {
+      str = new String(ba, "UTF-8");
+    }
+    catch (final UnsupportedEncodingException uee)
+    {
+      str = new String(ba);
+    }
+
+    Assert.assertTrue(bs.toString().equals(str));
+  }
+
+
+
+  protected abstract Object[][] byteSequenceProvider() throws Exception;
+
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringBuilderTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringBuilderTestCase.java
new file mode 100644
index 0000000..462ce1c
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringBuilderTestCase.java
@@ -0,0 +1,296 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * Test case for ByteStringBuilder.
+ */
+public class ByteStringBuilderTestCase extends ByteSequenceTestCase
+{
+  private static final byte[] eightBytes = new byte[] { (byte) 0x01,
+      (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06,
+      (byte) 0x07, (byte) 0x08 };
+
+
+
+  /**
+   * ByteSequence data provider.
+   *
+   * @return The array of ByteStrings and the bytes it should contain.
+   */
+  @Override
+  @DataProvider(name = "byteSequenceProvider")
+  public Object[][] byteSequenceProvider() throws Exception
+  {
+    final Object[][] builders = byteStringBuilderProvider();
+    final Object[][] addlSequences = new Object[builders.length + 1][];
+    System.arraycopy(builders, 0, addlSequences, 0, builders.length);
+    addlSequences[builders.length] = new Object[] {
+        new ByteStringBuilder().append(eightBytes).subSequence(2, 6),
+        new byte[] { (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06 } };
+
+    return addlSequences;
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testAppendBadByteBufferLength1()
+  {
+    new ByteStringBuilder().append(ByteBuffer.wrap(new byte[5]), -1);
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testAppendBadByteBufferLength2()
+  {
+    new ByteStringBuilder().append(ByteBuffer.wrap(new byte[5]), 6);
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testAppendBadByteSequenceReaderLength1()
+  {
+    new ByteStringBuilder().append(ByteString.wrap(new byte[5]).asReader(), -1);
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testAppendBadByteSequenceReaderLength2()
+  {
+    new ByteStringBuilder().append(ByteString.wrap(new byte[5]).asReader(), 6);
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testAppendBadInputStreamLength() throws Exception
+  {
+    final ByteArrayInputStream stream = new ByteArrayInputStream(new byte[5]);
+    new ByteStringBuilder().append(stream, -1);
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testAppendBadLength1()
+  {
+    new ByteStringBuilder().append(new byte[5], 0, 6);
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testAppendBadLength2()
+  {
+    new ByteStringBuilder().append(new byte[5], 0, -1);
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testAppendBadOffset1()
+  {
+    new ByteStringBuilder().append(new byte[5], -1, 3);
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testAppendBadOffset2()
+  {
+    new ByteStringBuilder().append(new byte[5], 6, 0);
+  }
+
+
+
+  @Test
+  public void testAppendInputStream() throws Exception
+  {
+    final ByteStringBuilder bsb = new ByteStringBuilder();
+    final ByteArrayInputStream stream = new ByteArrayInputStream(new byte[5]);
+    Assert.assertEquals(bsb.append(stream, 10), 5);
+  }
+
+
+
+  @Test(dataProvider = "builderProvider", expectedExceptions = IndexOutOfBoundsException.class)
+  public void testClear(final ByteStringBuilder bs, final byte[] ba)
+  {
+    bs.clear();
+    Assert.assertEquals(bs.length(), 0);
+    bs.byteAt(0);
+  }
+
+
+
+  @Test
+  public void testEnsureAdditionalCapacity()
+  {
+    final ByteStringBuilder bsb = new ByteStringBuilder(8);
+    Assert.assertEquals(bsb.getBackingArray().length, 8);
+    bsb.ensureAdditionalCapacity(43);
+    bsb.ensureAdditionalCapacity(2);
+    Assert.assertTrue(bsb.getBackingArray().length >= 43);
+  }
+
+
+
+  @Test(dataProvider = "builderProvider")
+  public void testGetBackingArray(final ByteStringBuilder bs, final byte[] ba)
+  {
+    final byte[] trimmedArray = new byte[bs.length()];
+    System.arraycopy(bs.getBackingArray(), 0, trimmedArray, 0, bs.length());
+    Assert.assertTrue(Arrays.equals(trimmedArray, ba));
+  }
+
+
+
+  @Test(expectedExceptions = IllegalArgumentException.class)
+  public void testInvalidCapacity()
+  {
+    new ByteStringBuilder(-1);
+  }
+
+
+
+  @Test
+  public void testTrimToSize()
+  {
+    final ByteStringBuilder bsb = new ByteStringBuilder();
+    bsb.append(eightBytes);
+    Assert.assertTrue(bsb.getBackingArray().length > 8);
+    bsb.trimToSize();
+    Assert.assertEquals(bsb.getBackingArray().length, 8);
+  }
+
+
+
+  @DataProvider(name = "builderProvider")
+  private Object[][] byteStringBuilderProvider() throws Exception
+  {
+    final ByteBuffer testBuffer = ByteBuffer.wrap(eightBytes);
+    final ByteString testByteString = ByteString.wrap(eightBytes);
+    final ByteSequenceReader testByteReader = testByteString.asReader();
+    final InputStream testStream = new ByteArrayInputStream(eightBytes);
+    final ByteStringBuilder testBuilderFromStream = new ByteStringBuilder(8);
+    testBuilderFromStream.append(testStream, 8);
+
+    return new Object[][] {
+        { new ByteStringBuilder().append((byte) 0x00).append((byte) 0x01),
+            new byte[] { (byte) 0x00, (byte) 0x01 } },
+        {
+            new ByteStringBuilder(5)
+                .append(
+                    new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
+                        (byte) 0x04 }).append(
+                    new byte[] { (byte) 0x05, (byte) 0x06, (byte) 0x07,
+                        (byte) 0x08 }), eightBytes },
+        {
+            new ByteStringBuilder(3).append(eightBytes, 0, 3).append(
+                eightBytes, 3, 5), eightBytes },
+        { new ByteStringBuilder().append(testBuffer, 3).append(testBuffer, 5),
+            eightBytes },
+        { new ByteStringBuilder(2).append(testByteString), eightBytes },
+        {
+            new ByteStringBuilder().append(testByteReader, 5).append(
+                testByteReader, 3), eightBytes },
+        { testBuilderFromStream, eightBytes },
+        {
+            new ByteStringBuilder().append(Short.MIN_VALUE).append(
+                Short.MAX_VALUE),
+            new byte[] { (byte) 0x80, (byte) 0x00, (byte) 0x7F, (byte) 0xFF } },
+        {
+            new ByteStringBuilder(5).append(Integer.MIN_VALUE).append(
+                Integer.MAX_VALUE),
+            new byte[] { (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+                (byte) 0x7F, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF } },
+        {
+            new ByteStringBuilder().append(Long.MIN_VALUE).append(
+                Long.MAX_VALUE),
+            new byte[] { (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+                (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+                (byte) 0x7F, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+                (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF } },
+        { new ByteStringBuilder(11).append("this is a").append(" test"),
+            "this is a test".getBytes("UTF-8") },
+        {
+            new ByteStringBuilder().appendBERLength(0x00000000)
+                .appendBERLength(0x00000001).appendBERLength(0x0000000F)
+                .appendBERLength(0x00000010).appendBERLength(0x0000007F).
+
+                appendBERLength(0x000000FF).
+
+                appendBERLength(0x00000100).appendBERLength(0x00000FFF)
+                .appendBERLength(0x00001000).appendBERLength(0x0000FFFF).
+
+                appendBERLength(0x00010000).appendBERLength(0x000FFFFF)
+                .appendBERLength(0x00100000).appendBERLength(0x00FFFFFF).
+
+                appendBERLength(0x01000000).appendBERLength(0x0FFFFFFF)
+                .appendBERLength(0x10000000).appendBERLength(0xFFFFFFFF),
+
+            new byte[] { (byte) 0x00, (byte) 0x01, (byte) 0x0F, (byte) 0x10,
+                (byte) 0x7F,
+
+                (byte) 0x81, (byte) 0xFF,
+
+                (byte) 0x82, (byte) 0x01, (byte) 0x00, (byte) 0x82,
+                (byte) 0x0F, (byte) 0xFF, (byte) 0x82, (byte) 0x10,
+                (byte) 0x00, (byte) 0x82, (byte) 0xFF, (byte) 0xFF,
+
+                (byte) 0x83, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+                (byte) 0x83, (byte) 0x0F, (byte) 0xFF, (byte) 0xFF,
+                (byte) 0x83, (byte) 0x10, (byte) 0x00, (byte) 0x00,
+                (byte) 0x83, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+
+                (byte) 0x84, (byte) 0x01, (byte) 0x00, (byte) 0x00,
+                (byte) 0x00, (byte) 0x84, (byte) 0x0F, (byte) 0xFF,
+                (byte) 0xFF, (byte) 0xFF, (byte) 0x84, (byte) 0x10,
+                (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x84,
+                (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF } },
+
+    };
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringTestCase.java
new file mode 100644
index 0000000..6efde50
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringTestCase.java
@@ -0,0 +1,167 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * This class defines a set of tests for the org.opends.server.types.ByteString
+ * class.
+ */
+public class ByteStringTestCase extends ByteSequenceTestCase
+{
+  /**
+   * ByteString data provider.
+   *
+   * @return The array of ByteStrings and the bytes it should contain.
+   */
+  @Override
+  @DataProvider(name = "byteSequenceProvider")
+  public Object[][] byteSequenceProvider() throws Exception
+  {
+    return new Object[][] {
+        { ByteString.empty(), new byte[0] },
+        { ByteString.valueOf(1),
+            new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x01 } },
+        { ByteString.valueOf(Integer.MAX_VALUE),
+            new byte[] { (byte) 0x7F, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF } },
+        { ByteString.valueOf(Integer.MIN_VALUE),
+            new byte[] { (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00 } },
+        {
+            ByteString.valueOf(Long.MAX_VALUE),
+            new byte[] { (byte) 0x7F, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF,
+                (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF } },
+        {
+            ByteString.valueOf(Long.MIN_VALUE),
+            new byte[] { (byte) 0x80, (byte) 0x00, (byte) 0x00, (byte) 0x00,
+                (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 } },
+        { ByteString.valueOf("cn=testvalue"), "cn=testvalue".getBytes("UTF-8") },
+        { ByteString.wrap(new byte[0]), new byte[0] },
+        {
+            ByteString
+                .wrap(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
+                    (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,
+                    (byte) 0x08 }),
+            new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+                (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08 } },
+        {
+            ByteString.wrap(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
+                (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,
+                (byte) 0x08, (byte) 0x09, (byte) 0x10 }, 0, 8),
+            new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03, (byte) 0x04,
+                (byte) 0x05, (byte) 0x06, (byte) 0x07, (byte) 0x08 } },
+        {
+            ByteString.wrap(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
+                (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,
+                (byte) 0x08, (byte) 0x09, (byte) 0x10 }, 1, 8),
+            new byte[] { (byte) 0x02, (byte) 0x03, (byte) 0x04, (byte) 0x05,
+                (byte) 0x06, (byte) 0x07, (byte) 0x08, (byte) 0x09 } },
+        {
+            ByteString.wrap(new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
+                (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,
+                (byte) 0x08, (byte) 0x09, (byte) 0x10 }, 2, 8),
+            new byte[] { (byte) 0x03, (byte) 0x04, (byte) 0x05, (byte) 0x06,
+                (byte) 0x07, (byte) 0x08, (byte) 0x09, (byte) 0x10 } },
+        {
+            ByteString.wrap(
+                new byte[] { (byte) 0x01, (byte) 0x02, (byte) 0x03,
+                    (byte) 0x04, (byte) 0x05, (byte) 0x06, (byte) 0x07,
+                    (byte) 0x08 }, 3, 0), new byte[0] }, };
+  }
+
+
+
+  @DataProvider(name = "byteStringIntegerProvier")
+  public Object[][] byteStringIntegerProvider()
+  {
+    return new Object[][] { { ByteString.valueOf(0), 0 },
+        { ByteString.valueOf(1), 1 },
+        { ByteString.valueOf(Integer.MAX_VALUE), Integer.MAX_VALUE },
+        { ByteString.valueOf(Integer.MIN_VALUE), Integer.MIN_VALUE }, };
+  }
+
+
+
+  @DataProvider(name = "byteStringLongProvier")
+  public Object[][] byteStringLongProvider()
+  {
+    return new Object[][] { { ByteString.valueOf(0L), 0L },
+        { ByteString.valueOf(1L), 1L },
+        { ByteString.valueOf(Long.MAX_VALUE), Long.MAX_VALUE },
+        { ByteString.valueOf(Long.MIN_VALUE), Long.MIN_VALUE } };
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testInvalidWrapLength()
+  {
+    ByteString.wrap(new byte[] { (byte) 0x00, (byte) 0x01, (byte) 0x02,
+        (byte) 0x03 }, 2, 8);
+  }
+
+
+
+  @Test(dataProvider = "byteStringIntegerProvider")
+  public void testToInteger(final ByteString bs, final int i)
+  {
+    Assert.assertEquals(bs.toInt(), i);
+  }
+
+
+
+  @Test(dataProvider = "byteStringLongProvider")
+  public void testToLong(final ByteString bs, final long l)
+  {
+    Assert.assertEquals(bs.toLong(), l);
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testUndersizedToInteger()
+  {
+    ByteString.wrap(new byte[] { (byte) 0x00, (byte) 0x01 }).toInt();
+  }
+
+
+
+  @Test(expectedExceptions = IndexOutOfBoundsException.class)
+  public void testUndersizedToLong()
+  {
+    ByteString.wrap(
+        new byte[] { (byte) 0x00, (byte) 0x01, (byte) 0x02, (byte) 0x03 })
+        .toLong();
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/ConnectionFactoryTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ConnectionFactoryTestCase.java
new file mode 100644
index 0000000..4d85d2e
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ConnectionFactoryTestCase.java
@@ -0,0 +1,171 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.concurrent.CountDownLatch;
+
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * Tests the connectionfactory classes.
+ */
+public abstract class ConnectionFactoryTestCase extends SdkTestCase
+{
+  class MyResultHandler implements ResultHandler<AsynchronousConnection>
+  {
+    // latch.
+    private final CountDownLatch latch;
+    // invalid flag.
+    private volatile boolean invalid;
+
+
+
+    MyResultHandler(final CountDownLatch latch)
+    {
+      this.latch = latch;
+    }
+
+
+
+    public void handleErrorResult(final ErrorResultException error)
+    {
+      // came here.
+      invalid = true;
+      latch.countDown();
+    }
+
+
+
+    public void handleResult(final AsynchronousConnection con)
+    {
+      //
+      latch.countDown();
+    }
+  }
+
+
+
+  /**
+   * Ensures that the LDAP Server is running.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @BeforeClass()
+  public void startServer() throws Exception
+  {
+    TestCaseUtils.startServer();
+  }
+
+
+
+  /**
+   * Tests the async connection in the blocking mode. This is not fully async as
+   * it blocks on the future.
+   *
+   * @throws Exception
+   */
+  @Test()
+  public void testBlockingFutureNoHandler() throws Exception
+  {
+    final FutureResult<AsynchronousConnection> future = getAsynchronousConnection(null);
+    final AsynchronousConnection con = future.get();
+    // quickly check if iit is a valid connection.
+    // Don't use a result handler.
+    assertNotNull(con.readRootDSE(null).get());
+    con.close();
+  }
+
+
+
+  /**
+   * Tests the non-blocking fully async connection using a handler.
+   *
+   * @throws Exception
+   */
+  @Test()
+  public void testNonBlockingFutureWithHandler() throws Exception
+  {
+    // Use the handler to get the result asynchronously.
+    final CountDownLatch latch = new CountDownLatch(1);
+    final MyResultHandler handler = new MyResultHandler(latch);
+    final FutureResult<AsynchronousConnection> future = getAsynchronousConnection(handler);
+    // Since we don't have anything to do, we would rather
+    // be notified by the latch when the other thread calls our handler.
+    latch.await(); // should do a timed wait rather?
+    if (handler.invalid)
+    {
+      // There was an error.
+      throw new Exception();
+    }
+  }
+
+
+
+  /**
+   * Tests the synchronous connection.
+   *
+   * @throws Exception
+   */
+  @Test()
+  public void testSynchronousConnection() throws Exception
+  {
+    final Connection con = getConnection();
+    assertNotNull(con);
+    // quickly check if iit is a valid connection.
+    assertTrue(con.readRootDSE().getEntry().getName().isRootDN());
+    con.close();
+  }
+
+
+
+  /**
+   * Gets the future result from the implementations.
+   *
+   * @return FutureResult.
+   */
+  protected abstract FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      ResultHandler<AsynchronousConnection> handler) throws Exception;
+
+
+
+  /**
+   * Gets the connection from the implementations.
+   *
+   * @return Connection
+   */
+  protected abstract Connection getConnection() throws Exception;
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/DNTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/DNTestCase.java
new file mode 100644
index 0000000..81437a2
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/DNTestCase.java
@@ -0,0 +1,997 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.sun.opends.sdk.util.Platform;
+
+
+
+/**
+ * This class defines a set of tests for the org.opends.sdk.DN class.
+ */
+public class DNTestCase extends SdkTestCase
+{
+  /**
+   * child DN test data provider.
+   *
+   * @return The array of test data.
+   */
+  @DataProvider(name = "createChildDNTestData")
+  public Object[][] createChildDNTestData()
+  {
+    return new Object[][] {
+        { "", "", "" },
+        { "", "dc=org", "dc=org" },
+        { "", "dc=opends,dc=org", "dc=opends,dc=org" },
+        { "dc=org", "", "dc=org" },
+        { "dc=org", "dc=opends", "dc=opends,dc=org" },
+        { "dc=org", "dc=foo,dc=opends", "dc=foo,dc=opends,dc=org" },
+        { "dc=opends,dc=org", "", "dc=opends,dc=org" },
+        { "dc=opends,dc=org", "dc=foo", "dc=foo,dc=opends,dc=org" },
+        { "dc=opends,dc=org", "dc=bar,dc=foo", "dc=bar,dc=foo,dc=opends,dc=org" }, };
+  }
+
+
+
+  /**
+   * Child RDN test data provider.
+   *
+   * @return The array of test data.
+   */
+  @DataProvider(name = "createChildRDNTestData")
+  public Object[][] createChildRDNTestData()
+  {
+    return new Object[][] { { "", "dc=org", "dc=org" },
+        { "dc=org", "dc=opends", "dc=opends,dc=org" },
+        { "dc=opends,dc=org", "dc=foo", "dc=foo,dc=opends,dc=org" }, };
+  }
+
+
+
+  /**
+   * DN test data provider.
+   *
+   * @return The array of test DN strings.
+   */
+  @DataProvider(name = "testDNs")
+  public Object[][] createData()
+  {
+    return new Object[][] {
+        { "", "", "" },
+        { "   ", "", "" },
+        { "cn=", "cn=", "cn=" },
+        { "cn= ", "cn=", "cn=" },
+        { "cn =", "cn=", "cn=" },
+        { "cn = ", "cn=", "cn=" },
+        { "dc=com", "dc=com", "dc=com" },
+        { "dc=com+o=com", "dc=com+o=com", "dc=com+o=com" },
+        { "DC=COM", "dc=com", "DC=COM" },
+        { "dc = com", "dc=com", "dc=com" },
+        { " dc = com ", "dc=com", "dc=com" },
+        { "dc=example,dc=com", "dc=example,dc=com", "dc=example,dc=com" },
+        { "dc=example, dc=com", "dc=example,dc=com", "dc=example,dc=com" },
+        { "dc=example ,dc=com", "dc=example,dc=com", "dc=example,dc=com" },
+        { "dc =example , dc  =   com", "dc=example,dc=com", "dc=example,dc=com" },
+        { "givenName=John+cn=Doe,ou=People,dc=example,dc=com",
+            "cn=doe+givenname=john,ou=people,dc=example,dc=com",
+            "givenName=John+cn=Doe,ou=People,dc=example,dc=com" },
+        { "givenName=John\\+cn=Doe,ou=People,dc=example,dc=com",
+            "givenname=john\\+cn\\=doe,ou=people,dc=example,dc=com",
+            "givenName=John\\+cn=Doe,ou=People,dc=example,dc=com" },
+        { "cn=Doe\\, John,ou=People,dc=example,dc=com",
+            "cn=doe\\, john,ou=people,dc=example,dc=com",
+            "cn=Doe\\, John,ou=People,dc=example,dc=com" },
+        { "UID=jsmith,DC=example,DC=net", "uid=jsmith,dc=example,dc=net",
+            "UID=jsmith,DC=example,DC=net" },
+        { "OU=Sales+CN=J. Smith,DC=example,DC=net",
+            "cn=j. smith+ou=sales,dc=example,dc=net",
+            "OU=Sales+CN=J. Smith,DC=example,DC=net" },
+        { "CN=James \\\"Jim\\\" Smith\\, III,DC=example,DC=net",
+            "cn=james \\\"jim\\\" smith\\, iii,dc=example,dc=net",
+            "CN=James \\\"Jim\\\" Smith\\, III,DC=example,DC=net" },
+        { "CN=John Smith\\2C III,DC=example,DC=net",
+            "cn=john smith\\, iii,dc=example,dc=net",
+            "CN=John Smith\\, III,DC=example,DC=net" },
+        { "CN=\\23John Smith\\20,DC=example,DC=net",
+            "cn=\\#john smith,dc=example,dc=net",
+            "CN=\\#John Smith\\ ,DC=example,DC=net" },
+        {
+            "CN=Before\\0dAfter,DC=example,DC=net",
+            // \0d is a hex representation of Carriage return. It is mapped
+            // to a SPACE as defined in the MAP ( RFC 4518)
+            "cn=before after,dc=example,dc=net",
+            "CN=Before\\0dAfter,DC=example,DC=net" },
+        { "2.5.4.3=#04024869",
+        // Unicode codepoints from 0000-0008 are mapped to nothing.
+            "cn=hi", "2.5.4.3=\\04\\02Hi" },
+        { "1.1.1=", "1.1.1=", "1.1.1=" },
+        { "CN=Lu\\C4\\8Di\\C4\\87", "cn=lu\u010di\u0107", "CN=Lu\u010di\u0107" },
+        { "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8,o=Airius",
+            "ou=\u55b6\u696d\u90e8,o=airius", "ou=\u55b6\u696d\u90e8,o=Airius" },
+        { "photo=\\ john \\ ,dc=com", "photo=\\ john \\ ,dc=com",
+            "photo=\\ john \\ ,dc=com" },
+        { "AB-global=", "ab-global=", "AB-global=" },
+        { "OU= Sales + CN = J. Smith ,DC=example,DC=net",
+            "cn=j. smith+ou=sales,dc=example,dc=net",
+            "OU=Sales+CN=J. Smith,DC=example,DC=net" },
+        { "cn=John+a=", "a=+cn=john", "cn=John+a=" },
+        { "O=\"Sue, Grabbit and Runn\",C=US", "o=sue\\, grabbit and runn,c=us",
+            "O=Sue\\, Grabbit and Runn,C=US" }, };
+  }
+
+
+
+  /**
+   * DN comparison test data provider.
+   *
+   * @return The array of test DN strings.
+   */
+  @DataProvider(name = "createDNComparisonData")
+  public Object[][] createDNComparisonData()
+  {
+    return new Object[][] {
+        { "cn=hello world,dc=com", "cn=hello world,dc=com", 0 },
+        { "cn=hello world,dc=com", "CN=hello world,dc=com", 0 },
+        { "cn=hello   world,dc=com", "cn=hello world,dc=com", 0 },
+        { "  cn =  hello world  ,dc=com", "cn=hello world,dc=com", 0 },
+        { "cn=hello world\\ ,dc=com", "cn=hello world,dc=com", 0 },
+        { "cn=HELLO WORLD,dc=com", "cn=hello world,dc=com", 0 },
+        { "cn=HELLO+sn=WORLD,dc=com", "sn=world+cn=hello,dc=com", 0 },
+        /**
+         * { "x-test-integer-type=10,dc=com", "x-test-integer-type=9,dc=com", 1
+         * }, { "x-test-integer-type=999,dc=com",
+         * "x-test-integer-type=1000,dc=com", -1 }, {
+         * "x-test-integer-type=-1,dc=com", "x-test-integer-type=0,dc=com", -1
+         * }, { "x-test-integer-type=0,dc=com", "x-test-integer-type=-1,dc=com",
+         * 1 },
+         **/
+        { "cn=aaa,dc=com", "cn=aaaa,dc=com", -1 },
+        { "cn=AAA,dc=com", "cn=aaaa,dc=com", -1 },
+        { "cn=aaa,dc=com", "cn=AAAA,dc=com", -1 },
+        { "cn=aaaa,dc=com", "cn=aaa,dc=com", 1 },
+        { "cn=AAAA,dc=com", "cn=aaa,dc=com", 1 },
+        { "cn=aaaa,dc=com", "cn=AAA,dc=com", 1 },
+        { "cn=aaab,dc=com", "cn=aaaa,dc=com", 1 },
+        { "cn=aaaa,dc=com", "cn=aaab,dc=com", -1 },
+        { "dc=aaa,dc=aaa", "dc=bbb", -1 }, { "dc=bbb,dc=aaa", "dc=bbb", -1 },
+        { "dc=ccc,dc=aaa", "dc=bbb", -1 }, { "dc=aaa,dc=bbb", "dc=bbb", 1 },
+        { "dc=bbb,dc=bbb", "dc=bbb", 1 }, { "dc=ccc,dc=bbb", "dc=bbb", 1 },
+        { "dc=aaa,dc=ccc", "dc=bbb", 1 }, { "dc=bbb,dc=ccc", "dc=bbb", 1 },
+        { "dc=ccc,dc=ccc", "dc=bbb", 1 }, { "", "dc=bbb", -1 },
+        { "dc=bbb", "", 1 } };
+  }
+
+
+
+  /**
+   * DN equality test data provider.
+   *
+   * @return The array of test DN strings.
+   */
+  @DataProvider(name = "createDNEqualityData")
+  public Object[][] createDNEqualityData()
+  {
+    return new Object[][] {
+        { "cn=hello world,dc=com", "cn=hello world,dc=com", 0 },
+        { "cn=hello world,dc=com", "CN=hello world,dc=com", 0 },
+        { "cn=hello   world,dc=com", "cn=hello world,dc=com", 0 },
+        { "  cn =  hello world  ,dc=com", "cn=hello world,dc=com", 0 },
+        { "cn=hello world\\ ,dc=com", "cn=hello world,dc=com", 0 },
+        { "cn=HELLO WORLD,dc=com", "cn=hello world,dc=com", 0 },
+        { "cn=HELLO+sn=WORLD,dc=com", "sn=world+cn=hello,dc=com", 0 },
+        { "x-test-integer-type=10,dc=com", "x-test-integer-type=9,dc=com", 1 },
+        { "x-test-integer-type=999,dc=com", "x-test-integer-type=1000,dc=com",
+            -1 },
+        { "x-test-integer-type=-1,dc=com", "x-test-integer-type=0,dc=com", -1 },
+        { "x-test-integer-type=0,dc=com", "x-test-integer-type=-1,dc=com", 1 },
+        { "cn=aaa,dc=com", "cn=aaaa,dc=com", -1 },
+        { "cn=AAA,dc=com", "cn=aaaa,dc=com", -1 },
+        { "cn=aaa,dc=com", "cn=AAAA,dc=com", -1 },
+        { "cn=aaaa,dc=com", "cn=aaa,dc=com", 1 },
+        { "cn=AAAA,dc=com", "cn=aaa,dc=com", 1 },
+        { "cn=aaaa,dc=com", "cn=AAA,dc=com", 1 },
+        { "cn=aaab,dc=com", "cn=aaaa,dc=com", 1 },
+        { "cn=aaaa,dc=com", "cn=aaab,dc=com", -1 },
+        { "dc=aaa,dc=aaa", "dc=bbb", -1 }, { "dc=bbb,dc=aaa", "dc=bbb", -1 },
+        { "dc=ccc,dc=aaa", "dc=bbb", -1 }, { "dc=aaa,dc=bbb", "dc=bbb", 1 },
+        { "dc=bbb,dc=bbb", "dc=bbb", 1 }, { "dc=ccc,dc=bbb", "dc=bbb", 1 },
+        { "dc=aaa,dc=ccc", "dc=bbb", 1 }, { "dc=bbb,dc=ccc", "dc=bbb", 1 },
+        { "dc=ccc,dc=ccc", "dc=bbb", 1 }, { "", "dc=bbb", -1 },
+        { "dc=bbb", "", 1 } };
+  }
+
+
+
+  /**
+   * Illegal DN test data provider.
+   *
+   * @return The array of illegal test DN strings.
+   */
+  @DataProvider(name = "illegalDNs")
+  public Object[][] createIllegalData()
+  {
+    return new Object[][] { { "manager" }, { "manager " }, { "=Jim" },
+        { " =Jim" }, { "= Jim" },
+        { " = Jim" },
+        { "cn+Jim" },
+        { "cn + Jim" },
+        { "cn=Jim+" },
+        { "cn=Jim+manager" },
+        { "cn=Jim+manager " },
+        { "cn=Jim+manager," },// { "cn=Jim," }, { "cn=Jim,  " }, { "c[n]=Jim" },
+        { "_cn=Jim" }, { "c_n=Jim" }, { "cn\"=Jim" }, { "c\"n=Jim" },
+        { "1cn=Jim" }, { "cn+uid=Jim" }, { "-cn=Jim" }, { "/tmp=a" },
+        { "\\tmp=a" }, { "cn;lang-en=Jim" }, { "@cn=Jim" },
+        { "_name_=Jim" },
+        { "\u03c0=pi" },
+        { "v1.0=buggy" },// { "1.=buggy" }, { ".1=buggy" },
+        { "oid.1." }, { "1.3.6.1.4.1.1466..0=#04024869" }, { "cn=#a" },
+        { "cn=#ag" }, { "cn=#ga" }, { "cn=#abcdefgh" },
+        { "cn=a\\b" }, // { "cn=a\\bg" }, { "cn=\"hello" },
+        { "cn=+mail=,dc=example,dc=com" }, { "cn=xyz+sn=,dc=example,dc=com" },
+        { "cn=,dc=example,dc=com" } };
+  }
+
+
+
+  /**
+   * Is Child of test data provider.
+   *
+   * @return The array of test data.
+   */
+  @DataProvider(name = "createIsChildOfTestData")
+  public Object[][] createIsChildOfTestData()
+  {
+    return new Object[][] { { "", "", false }, { "", "dc=org", false },
+        { "", "dc=opends,dc=org", false },
+        { "", "dc=foo,dc=opends,dc=org", false }, { "dc=org", "", true },
+        { "dc=org", "dc=org", false }, { "dc=org", "dc=opends,dc=org", false },
+        { "dc=org", "dc=foo,dc=opends,dc=org", false },
+        { "dc=opends,dc=org", "", false },
+        { "dc=opends,dc=org", "dc=org", true },
+        { "dc=opends,dc=org", "dc=opends,dc=org", false },
+        { "dc=opends,dc=org", "dc=foo,dc=opends,dc=org", false },
+        { "dc=foo,dc=opends,dc=org", "", false },
+        { "dc=foo,dc=opends,dc=org", "dc=org", false },
+        { "dc=foo,dc=opends,dc=org", "dc=opends,dc=org", true },
+        { "dc=foo,dc=opends,dc=org", "dc=foo,dc=opends,dc=org", false },
+        { "dc=org", "dc=com", false },
+        { "dc=opends,dc=org", "dc=foo,dc=org", false },
+        { "dc=opends,dc=org", "dc=opends,dc=com", false }, };
+  }
+
+
+
+  /**
+   * DN test data provider.
+   *
+   * @return The array of test DN strings.
+   */
+  @DataProvider(name = "createNumComponentsTestData")
+  public Object[][] createNumComponentsTestData()
+  {
+    return new Object[][] { { "", 0 }, { "dc=com", 1 },
+        { "dc=opends,dc=com", 2 }, { "dc=world,dc=opends,dc=com", 3 },
+        { "dc=hello,dc=world,dc=opends,dc=com", 4 }, };
+  }
+
+
+
+  /**
+   * DN test data provider.
+   *
+   * @return The array of test DN strings.
+   */
+  @DataProvider(name = "createParentAndRDNTestData")
+  public Object[][] createParentAndRDNTestData()
+  {
+    return new Object[][] {
+        { "", null, null },
+        { "dc=com", "", "dc=com" },
+        { "dc=opends,dc=com", "dc=com", "dc=opends" },
+        { "dc=world,dc=opends,dc=com", "dc=opends,dc=com", "dc=world" },
+        { "dc=hello,dc=world,dc=opends,dc=com", "dc=world,dc=opends,dc=com",
+            "dc=hello" }, };
+  }
+
+
+
+  /**
+   * DN test data provider.
+   *
+   * @return The array of test DN strings.
+   */
+  @DataProvider(name = "createRDNTestData")
+  public Object[][] createRDNTestData()
+  {
+    return new Object[][] { { "dc=com", 0, "dc=com" },
+        { "dc=opends,dc=com", 0, "dc=opends" },
+        { "dc=opends,dc=com", 1, "dc=com" },
+        { "dc=hello,dc=world,dc=opends,dc=com", 0, "dc=hello" },
+        { "dc=hello,dc=world,dc=opends,dc=com", 1, "dc=world" },
+        { "dc=hello,dc=world,dc=opends,dc=com", 2, "dc=opends" },
+        { "dc=hello,dc=world,dc=opends,dc=com", 3, "dc=com" }, };
+  }
+
+
+
+  /**
+   * Subordinate test data provider.
+   *
+   * @return The array of subordinate and superior DN Strings.
+   */
+  @DataProvider(name = "createSubordinateTestData")
+  public Object[][] createSubordinateTestData()
+  {
+    return new Object[][] { { "", "", true }, { "", "dc=org", false },
+        { "", "dc=opends,dc=org", false },
+        { "", "dc=foo,dc=opends,dc=org", false }, { "dc=org", "", true },
+        { "dc=org", "dc=org", true }, { "dc=org", "dc=opends,dc=org", false },
+        { "dc=org", "dc=foo,dc=opends,dc=org", false },
+        { "dc=opends,dc=org", "", true },
+        { "dc=opends,dc=org", "dc=org", true },
+        { "dc=opends,dc=org", "dc=opends,dc=org", true },
+        { "dc=opends,dc=org", "dc=foo,dc=opends,dc=org", false },
+        { "dc=foo,dc=opends,dc=org", "", true },
+        { "dc=foo,dc=opends,dc=org", "dc=org", true },
+        { "dc=foo,dc=opends,dc=org", "dc=opends,dc=org", true },
+        { "dc=foo,dc=opends,dc=org", "dc=foo,dc=opends,dc=org", true },
+        { "dc=org", "dc=com", false },
+        { "dc=opends,dc=org", "dc=foo,dc=org", false },
+        { "dc=opends,dc=org", "dc=opends,dc=com", false }, };
+  }
+
+
+
+  /**
+   * Superior test data provider.
+   *
+   * @return The array of superior and subordindate DN Strings.
+   */
+  @DataProvider(name = "createSuperiorTestData")
+  public Object[][] createSuperiorTestData()
+  {
+    return new Object[][] { { "", "", true }, { "", "dc=org", true },
+        { "", "dc=opends,dc=org", true },
+        { "", "dc=foo,dc=opends,dc=org", true }, { "dc=org", "", false },
+        { "dc=org", "dc=org", true }, { "dc=org", "dc=opends,dc=org", true },
+        { "dc=org", "dc=foo,dc=opends,dc=org", true },
+        { "dc=opends,dc=org", "", false },
+        { "dc=opends,dc=org", "dc=org", false },
+        { "dc=opends,dc=org", "dc=opends,dc=org", true },
+        { "dc=opends,dc=org", "dc=foo,dc=opends,dc=org", true },
+        { "dc=foo,dc=opends,dc=org", "", false },
+        { "dc=foo,dc=opends,dc=org", "dc=org", false },
+        { "dc=foo,dc=opends,dc=org", "dc=opends,dc=org", false },
+        { "dc=foo,dc=opends,dc=org", "dc=foo,dc=opends,dc=org", true },
+        { "dc=org", "dc=com", false },
+        { "dc=opends,dc=org", "dc=foo,dc=org", false },
+        { "dc=opends,dc=org", "dc=opends,dc=com", false }, };
+  }
+
+
+
+  @Test()
+  public void testAdminData()
+  {
+    DN.valueOf("cn=cn\\=admin data");
+    final DN theDN = DN.valueOf("cn=my dn");
+    final RDN theRDN = new RDN("cn", "my rdn");
+    final DN theChildDN = theDN.child(theRDN);
+    DN.valueOf(theChildDN.toString());
+  }
+
+
+
+  /**
+   * Test the child(DN) method.
+   *
+   * @param s
+   *          The test DN string.
+   * @param l
+   *          The local name to be appended.
+   * @param e
+   *          The expected DN.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createChildDNTestData")
+  public void testChildDN(final String s, final String l, final String e)
+      throws Exception
+  {
+    final DN dn = DN.valueOf(s);
+    final DN localName = DN.valueOf(l);
+    final DN expected = DN.valueOf(e);
+
+    assertEquals(dn.child(localName), expected);
+  }
+
+
+
+  /**
+   * Test the child(DN) method.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(expectedExceptions = { NullPointerException.class, AssertionError.class })
+  public void testChildDNException() throws Exception
+  {
+    final DN dn = DN.valueOf("dc=org");
+    dn.child((DN) null);
+  }
+
+
+
+  /**
+   * Test the child(DN) method's interaction with other methods.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testChildDNInteraction() throws Exception
+  {
+    final DN p = DN.valueOf("dc=opends,dc=org");
+    final DN l = DN.valueOf("dc=foo");
+    final DN e = DN.valueOf("dc=foo,dc=opends,dc=org");
+    final DN c = p.child(l);
+
+    assertEquals(c.size(), 3);
+
+    assertEquals(c.compareTo(p), 1);
+    assertEquals(p.compareTo(c), -1);
+
+    assertTrue(p.isParentOf(c));
+    assertFalse(c.isParentOf(p));
+
+    assertTrue(c.isChildOf(p));
+    assertFalse(p.isChildOf(c));
+
+    assertEquals(c, e);
+    assertEquals(c.hashCode(), e.hashCode());
+
+    assertEquals(c.toNormalizedString(), e.toNormalizedString());
+    assertEquals(c.toString(), e.toString());
+
+    assertEquals(c.rdn(), RDN.valueOf("dc=foo"));
+
+    assertEquals(c.parent(), DN.valueOf("dc=opends,dc=org"));
+    assertEquals(c.parent(), e.parent());
+
+    assertEquals(c.child(RDN.valueOf("dc=xxx")), DN
+        .valueOf("dc=xxx,dc=foo,dc=opends,dc=org"));
+    assertEquals(c.child(DN.valueOf("dc=xxx,dc=yyy")), DN
+        .valueOf("dc=xxx,dc=yyy,dc=foo,dc=opends,dc=org"));
+  }
+
+
+
+  /**
+   * Test the child(RDN...) method.
+   *
+   * @param s
+   *          The test DN string.
+   * @param r
+   *          The RDN to be appended.
+   * @param e
+   *          The expected DN.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createChildRDNTestData")
+  public void testChildSingleRDN(final String s, final String r, final String e)
+      throws Exception
+  {
+    final DN dn = DN.valueOf(s);
+    final RDN rdn = RDN.valueOf(r);
+    final DN expected = DN.valueOf(e);
+
+    assertEquals(dn.child(rdn), expected);
+  }
+
+
+
+  /**
+   * Test DN compareTo
+   *
+   * @param first
+   *          First DN to compare.
+   * @param second
+   *          Second DN to compare.
+   * @param result
+   *          Expected comparison result.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createDNComparisonData")
+  public void testCompareTo(final String first, final String second,
+      final int result) throws Exception
+  {
+    final DN dn1 = DN.valueOf(first);
+    final DN dn2 = DN.valueOf(second);
+
+    int rc = dn1.compareTo(dn2);
+
+    // Normalize the result.
+    if (rc < 0)
+    {
+      rc = -1;
+    }
+    else if (rc > 0)
+    {
+      rc = 1;
+    }
+
+    assertEquals(rc, result, "Comparison for <" + first + "> and <" + second
+        + ">.");
+  }
+
+
+
+  /**
+   * Test DN equality
+   *
+   * @param first
+   *          First DN to compare.
+   * @param second
+   *          Second DN to compare.
+   * @param result
+   *          Expected comparison result.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createDNEqualityData")
+  public void testEquality(final String first, final String second,
+      final int result) throws Exception
+  {
+    final DN dn1 = DN.valueOf(first);
+    final DN dn2 = DN.valueOf(second);
+
+    if (result == 0)
+    {
+      assertTrue(dn1.equals(dn2), "DN equality for <" + first + "> and <"
+          + second + ">");
+    }
+    else
+    {
+      assertFalse(dn1.equals(dn2), "DN equality for <" + first + "> and <"
+          + second + ">");
+    }
+  }
+
+
+
+  /**
+   * Tests the equals method with a value that's not a DN.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(expectedExceptions = LocalizedIllegalArgumentException.class)
+  public void testEqualsNonDN() throws Exception
+  {
+    final DN dn = DN.valueOf("dc=example,dc=com");
+
+    assertFalse(dn.equals(DN.valueOf("not a DN")));
+  }
+
+
+
+  /**
+   * Test DN hashCode
+   *
+   * @param first
+   *          First DN to compare.
+   * @param second
+   *          Second DN to compare.
+   * @param result
+   *          Expected comparison result.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createDNEqualityData")
+  public void testHashCode(final String first, final String second,
+      final int result) throws Exception
+  {
+    final DN dn1 = DN.valueOf(first);
+    final DN dn2 = DN.valueOf(second);
+
+    final int h1 = dn1.hashCode();
+    final int h2 = dn2.hashCode();
+
+    if (result == 0)
+    {
+      if (h1 != h2)
+      {
+        fail("Hash codes for <" + first + "> and <" + second
+            + "> should be the same.");
+      }
+    }
+    else
+    {
+      if (h1 == h2)
+      {
+        fail("Hash codes for <" + first + "> and <" + second
+            + "> should be the same.");
+      }
+    }
+  }
+
+
+
+  /**
+   * Test that decoding an illegal DN as a String throws an exception.
+   *
+   * @param dn
+   *          The illegal DN to be tested.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "illegalDNs", expectedExceptions = {
+      StringIndexOutOfBoundsException.class,
+      LocalizedIllegalArgumentException.class, NullPointerException.class })
+  public void testIllegalStringDNs(final String dn) throws Exception
+  {
+    DN.valueOf(dn);
+  }
+
+
+
+  /**
+   * Test the isChildOf method.
+   *
+   * @param s
+   *          The test DN string.
+   * @param d
+   *          The dn parameter.
+   * @param e
+   *          The expected result.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createIsChildOfTestData")
+  public void testIsChildOf(final String s, final String d, final boolean e)
+      throws Exception
+  {
+    final DN dn = DN.valueOf(s);
+    final DN other = DN.valueOf(d);
+
+    assertEquals(dn.isChildOf(other), e, s + " isChildOf " + d);
+  }
+
+
+
+  /**
+   * Test the isChildOf method.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(expectedExceptions = { NullPointerException.class, AssertionError.class })
+  public void testIsChildOfException() throws Exception
+  {
+    final DN dn = DN.valueOf("dc=com");
+    dn.isChildOf((String) null);
+  }
+
+
+
+  /**
+   * Tests the parent method that require iteration.
+   */
+  @Test()
+  public void testIterableParent()
+  {
+    final String str = "ou=people,dc=example,dc=com";
+    final DN dn = DN.valueOf(str);
+    // Parent at index 0 is self.
+    assertEquals(dn, dn.parent(0));
+    assertEquals(dn.parent(1), DN.valueOf("dc=example,dc=com"));
+    assertEquals(dn.parent(2), DN.valueOf("dc=com"));
+    assertEquals(dn.parent(3), DN.rootDN());
+  }
+
+
+
+  /**
+   * Test the getNumComponents method.
+   *
+   * @param s
+   *          The test DN string.
+   * @param sz
+   *          The expected number of RDNs.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createNumComponentsTestData")
+  public void testNumComponents(final String s, final int sz) throws Exception
+  {
+    final DN dn = DN.valueOf(s);
+    assertEquals(dn.size(), sz);
+  }
+
+
+
+  /**
+   * Test the parent method.
+   *
+   * @param s
+   *          The test DN string.
+   * @param p
+   *          The expected parent.
+   * @param r
+   *          The expected rdn.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createParentAndRDNTestData")
+  public void testParent(final String s, final String p, final String r)
+      throws Exception
+  {
+    final DN dn = DN.valueOf(s);
+    final DN parent = (p != null ? DN.valueOf(p) : null);
+
+    assertEquals(dn.parent(), parent, "For DN " + s);
+  }
+
+
+
+  /**
+   * Test the parent method's interaction with other methods.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testParentInteraction() throws Exception
+  {
+    final DN c = DN.valueOf("dc=foo,dc=bar,dc=opends,dc=org");
+    final DN e = DN.valueOf("dc=bar,dc=opends,dc=org");
+    final DN p = c.parent();
+
+    assertEquals(p.size(), 3);
+
+    assertEquals(p.compareTo(c), -1);
+    assertEquals(c.compareTo(p), 1);
+
+    assertTrue(p.isParentOf(c));
+    assertFalse(c.isParentOf(p));
+
+    assertTrue(c.isChildOf(p));
+    assertFalse(p.isChildOf(c));
+
+    assertEquals(p, e);
+    assertEquals(p.hashCode(), e.hashCode());
+
+    assertEquals(p.toNormalizedString(), e.toNormalizedString());
+    assertEquals(p.toString(), e.toString());
+
+    assertEquals(p.rdn(), RDN.valueOf("dc=bar"));
+
+    assertEquals(p.rdn(), RDN.valueOf("dc=bar"));
+
+    assertEquals(p.parent(), DN.valueOf("dc=opends,dc=org"));
+    assertEquals(p.parent(), e.parent());
+
+    assertEquals(p.child(RDN.valueOf("dc=foo")), DN
+        .valueOf("dc=foo,dc=bar,dc=opends,dc=org"));
+    assertEquals(p.child(RDN.valueOf("dc=foo")), c);
+    assertEquals(p.child(DN.valueOf("dc=xxx,dc=foo")), DN
+        .valueOf("dc=xxx,dc=foo,dc=bar,dc=opends,dc=org"));
+  }
+
+
+
+  /**
+   * Test the getRDN method.
+   *
+   * @param s
+   *          The test DN string.
+   * @param p
+   *          The expected parent.
+   * @param r
+   *          The expected rdn.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createParentAndRDNTestData")
+  public void testRDN(final String s, final String p, final String r)
+      throws Exception
+  {
+    final DN dn = DN.valueOf(s);
+    final RDN rdn = (r != null ? RDN.valueOf(r) : null);
+
+    assertEquals(dn.rdn(), rdn, "For DN " + s);
+  }
+
+
+
+  /**
+   * Tests the root DN.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testRootDN1() throws Exception
+  {
+    final DN dn = DN.valueOf("");
+    assertTrue(dn.isRootDN());
+    assertEquals(dn, DN.rootDN());
+  }
+
+
+
+  /**
+   * Tests the root DN.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(expectedExceptions = { NullPointerException.class, AssertionError.class })
+  public void testRootDN2() throws Exception
+  {
+    final DN dn = DN.valueOf(null);
+    assertEquals(dn, DN.rootDN());
+  }
+
+
+
+  /**
+   * Test the root dn.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testRootDN3() throws Exception
+  {
+    final DN nullDN = DN.rootDN();
+    assertTrue(nullDN.isRootDN());
+    assertTrue(nullDN.size() == 0);
+    assertEquals(nullDN.toNormalizedString(), "");
+  }
+
+
+
+  /**
+   * Test the root dn.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testRootDN4() throws Exception
+  {
+    final DN dn = DN.valueOf("dc=com");
+    assertFalse(dn.isRootDN());
+  }
+
+
+
+  /**
+   * Tests the subordinate dns.
+   */
+  @Test(dataProvider = "createSubordinateTestData")
+  public void testSubordinateDN(final String sub, final String base,
+      final boolean e) throws Exception
+  {
+    final DN dn = DN.valueOf(sub);
+    final DN other = DN.valueOf(base);
+    assertEquals(dn.isSubordinateOrEqualTo(other), e, sub + " isSubordinateOf "
+        + base);
+  }
+
+
+
+  /**
+   * Tests the supeiror dns.
+   */
+  @Test(dataProvider = "createSuperiorTestData")
+  public void testSuperiorDN(final String base, final String sub,
+      final boolean e) throws Exception
+  {
+    final DN dn = DN.valueOf(base);
+    final DN other = DN.valueOf(sub);
+    assertEquals(dn.isSuperiorOrEqualTo(other), e, base + " isSuperiorOf "
+        + sub);
+  }
+
+
+
+  /**
+   * Tests the toNoramlizedString methods.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testToNormalizedString() throws Exception
+  {
+    final DN dn = DN.valueOf("dc=example,dc=com");
+    assertEquals(dn.toNormalizedString(), "dc=example,dc=com");
+  }
+
+
+
+  /**
+   * Test the RFC 4514 string representation of the DN.
+   *
+   * @param rawDN
+   *          Raw DN string representation.
+   * @param normDN
+   *          Normalized DN string representation.
+   * @param stringDN
+   *          String representation.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "testDNs")
+  public void testToString(final String rawDN, final String normDN,
+      final String stringDN) throws Exception
+  {
+    // DN dn = DN.valueOf(rawDN);
+    // assertEquals(dn.toString(), stringDN);
+  }
+
+
+
+  /**
+   * Tests the <CODE>valueOf</CODE> method which takes a String argument.
+   *
+   * @param rawDN
+   *          Raw DN string representation.
+   * @param normDN
+   *          Normalized DN string representation.
+   * @param stringDN
+   *          String representation.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "testDNs")
+  public void testValueOfString(final String rawDN, final String normDN,
+      final String stringDN) throws Exception
+  {
+    final DN dn = DN.valueOf(rawDN);
+    final StringBuilder buffer = new StringBuilder();
+    buffer.append(normDN);
+    Platform.normalize(buffer);
+    assertEquals(dn.toNormalizedString(), buffer.toString());
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/EntryTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/EntryTestCase.java
new file mode 100644
index 0000000..1303285
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/EntryTestCase.java
@@ -0,0 +1,119 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * Test {@code BasicAttribute}.
+ */
+public final class EntryTestCase extends SdkTestCase
+{
+  private static interface EntryFactory
+  {
+    Entry newEntry(String... ldifLines);
+  }
+
+
+
+  private static final class LinkedHashMapEntryFactory implements EntryFactory
+  {
+    public Entry newEntry(final String... ldifLines)
+    {
+      return new LinkedHashMapEntry(ldifLines);
+    }
+  }
+
+
+
+  private static final class TreeMapEntryFactory implements EntryFactory
+  {
+    public Entry newEntry(final String... ldifLines)
+    {
+      return new TreeMapEntry(ldifLines);
+    }
+  }
+
+
+
+  @DataProvider(name = "EntryFactory")
+  public Object[][] entryFactory()
+  {
+    // Value, type, options, containsOptions("foo")
+    return new Object[][] { { new TreeMapEntryFactory() },
+        { new LinkedHashMapEntryFactory() } };
+  }
+
+
+
+  @Test(dataProvider = "EntryFactory")
+  public void smokeTest(final EntryFactory factory) throws Exception
+  {
+    final Entry entry1 = factory.newEntry(
+        "dn: cn=Joe Bloggs,dc=example,dc=com", "objectClass: top",
+        "objectClass: person", "cn: Joe Bloggs", "sn: Bloggs",
+        "givenName: Joe", "description: A description");
+
+    final Entry entry2 = factory.newEntry(
+        "dn: cn=Joe Bloggs,dc=example,dc=com", "changetype: add",
+        "objectClass: top", "objectClass: person", "cn: Joe Bloggs",
+        "sn: Bloggs", "givenName: Joe", "description: A description");
+
+    Assert.assertEquals(entry1, entry2);
+
+    for (final Entry e : new Entry[] { entry1, entry2 })
+    {
+      Assert.assertEquals(e.getName(), DN
+          .valueOf("cn=Joe Bloggs,dc=example,dc=com"));
+      Assert.assertEquals(e.getAttributeCount(), 5);
+
+      Assert.assertEquals(e.getAttribute("objectClass").size(), 2);
+      Assert.assertTrue(e.containsAttribute("objectClass", "top", "person"));
+      Assert.assertFalse(e.containsAttribute("objectClass", "top", "person",
+          "foo"));
+
+      Assert.assertTrue(e.containsAttribute("objectClass"));
+      Assert.assertTrue(e.containsAttribute("cn"));
+      Assert.assertTrue(e.containsAttribute("cn", "Joe Bloggs"));
+      Assert.assertFalse(e.containsAttribute("cn", "Jane Bloggs"));
+      Assert.assertTrue(e.containsAttribute("sn"));
+      Assert.assertTrue(e.containsAttribute("givenName"));
+      Assert.assertTrue(e.containsAttribute("description"));
+
+      Assert.assertEquals(e.getAttribute("cn").firstValueAsString(),
+          "Joe Bloggs");
+      Assert.assertEquals(e.getAttribute("sn").firstValueAsString(), "Bloggs");
+    }
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/FilterTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/FilterTestCase.java
new file mode 100644
index 0000000..224b370
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/FilterTestCase.java
@@ -0,0 +1,219 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import java.util.ArrayList;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+public class FilterTestCase extends SdkTestCase
+{
+  @DataProvider(name = "badfilterstrings")
+  public Object[][] getBadFilterStrings() throws Exception
+  {
+    return new Object[][] { { null, null }, { "", null }, { "=", null },
+        { "()", null }, { "(&(objectClass=*)(sn=s*s)", null },
+        { "(dob>12221)", null }, { "(cn=bob\\2 doe)", null },
+        { "(cn=\\4j\\w2\\yu)", null }, { "(cn=ds\\2)", null },
+        { "(&(givenname=bob)|(sn=pep)dob=12))", null }, { "(:=bob)", null },
+        { "(=sally)", null }, { "(cn=billy bob", null },
+        { "(|(!(title=sweep*)(l=Paris*)))", null }, { "(|(!))", null },
+        { "((uid=user.0))", null }, { "(&&(uid=user.0))", null },
+        { "!uid=user.0", null }, { "(:dn:=Sally)", null }, };
+  }
+
+
+
+  @DataProvider(name = "filterstrings")
+  public Object[][] getFilterStrings() throws Exception
+  {
+    final Filter equal = Filter.newEqualityMatchFilter("objectClass",
+        ByteString.valueOf("\\test*(Value)"));
+    final Filter equal2 = Filter.newEqualityMatchFilter("objectClass",
+        ByteString.valueOf(""));
+    final Filter approx = Filter.newApproxMatchFilter("sn", ByteString
+        .valueOf("\\test*(Value)"));
+    final Filter greater = Filter.newGreaterOrEqualFilter("employeeNumber",
+        ByteString.valueOf("\\test*(Value)"));
+    final Filter less = Filter.newLessOrEqualFilter("dob", ByteString
+        .valueOf("\\test*(Value)"));
+    final Filter presense = Filter.newPresentFilter("login");
+
+    final ArrayList<ByteString> any = new ArrayList<ByteString>(0);
+    final ArrayList<ByteString> multiAny = new ArrayList<ByteString>(1);
+    multiAny.add(ByteString.valueOf("\\wid*(get)"));
+    multiAny.add(ByteString.valueOf("*"));
+
+    final Filter substring1 = Filter.newSubstringsFilter("givenName",
+        ByteString.valueOf("\\Jo*()"), any, ByteString.valueOf("\\n*()"));
+    final Filter substring2 = Filter.newSubstringsFilter("givenName",
+        ByteString.valueOf("\\Jo*()"), multiAny, ByteString.valueOf("\\n*()"));
+    final Filter substring3 = Filter.newSubstringsFilter("givenName",
+        ByteString.valueOf(""), any, ByteString.valueOf("\\n*()"));
+    final Filter substring4 = Filter.newSubstringsFilter("givenName",
+        ByteString.valueOf("\\Jo*()"), any, ByteString.valueOf(""));
+    final Filter substring5 = Filter.newSubstringsFilter("givenName",
+        ByteString.valueOf(""), multiAny, ByteString.valueOf(""));
+    final Filter extensible1 = Filter.newExtensibleMatchFilter("2.4.6.8.19",
+        "cn", ByteString.valueOf("\\John* (Doe)"), false);
+    final Filter extensible2 = Filter.newExtensibleMatchFilter("2.4.6.8.19",
+        "cn", ByteString.valueOf("\\John* (Doe)"), true);
+    final Filter extensible3 = Filter.newExtensibleMatchFilter("2.4.6.8.19",
+        null, ByteString.valueOf("\\John* (Doe)"), true);
+    final Filter extensible4 = Filter.newExtensibleMatchFilter(null, "cn",
+        ByteString.valueOf("\\John* (Doe)"), true);
+    final Filter extensible5 = Filter.newExtensibleMatchFilter("2.4.6.8.19",
+        null, ByteString.valueOf("\\John* (Doe)"), false);
+
+    final ArrayList<Filter> list1 = new ArrayList<Filter>();
+    list1.add(equal);
+    list1.add(approx);
+
+    final Filter and = Filter.newAndFilter(list1);
+
+    final ArrayList<Filter> list2 = new ArrayList<Filter>();
+    list2.add(substring1);
+    list2.add(extensible1);
+    list2.add(and);
+
+    return new Object[][] {
+        { "(objectClass=\\5ctest\\2a\\28Value\\29)", equal },
+
+        { "(objectClass=)", equal2 },
+
+        { "(sn~=\\5ctest\\2a\\28Value\\29)", approx },
+
+        { "(employeeNumber>=\\5ctest\\2a\\28Value\\29)", greater },
+
+        { "(dob<=\\5ctest\\2a\\28Value\\29)", less },
+
+        { "(login=*)", presense },
+
+        { "(givenName=\\5cJo\\2a\\28\\29*\\5cn\\2a\\28\\29)", substring1 },
+
+        {
+            "(givenName=\\5cJo\\2a\\28\\29*\\5cwid\\2a\\28get\\29*\\2a*\\5cn\\2a\\28\\29)",
+            substring2 },
+
+        { "(givenName=*\\5cn\\2a\\28\\29)", substring3 },
+
+        { "(givenName=\\5cJo\\2a\\28\\29*)", substring4 },
+
+        { "(givenName=*\\5cwid\\2a\\28get\\29*\\2a*)", substring5 },
+
+        { "(cn:2.4.6.8.19:=\\5cJohn\\2a \\28Doe\\29)", extensible1 },
+
+        { "(cn:dn:2.4.6.8.19:=\\5cJohn\\2a \\28Doe\\29)", extensible2 },
+
+        { "(:dn:2.4.6.8.19:=\\5cJohn\\2a \\28Doe\\29)", extensible3 },
+
+        { "(cn:dn:=\\5cJohn\\2a \\28Doe\\29)", extensible4 },
+
+        { "(:2.4.6.8.19:=\\5cJohn\\2a \\28Doe\\29)", extensible5 },
+
+        {
+            "(&(objectClass=\\5ctest\\2a\\28Value\\29)(sn~=\\5ctest\\2a\\28Value\\29))",
+            Filter.newAndFilter(list1) },
+
+        {
+            "(|(objectClass=\\5ctest\\2a\\28Value\\29)(sn~=\\5ctest\\2a\\28Value\\29))",
+            Filter.newOrFilter(list1) },
+
+        { "(!(objectClass=\\5ctest\\2a\\28Value\\29))",
+            Filter.newNotFilter(equal) },
+
+        {
+            "(|(givenName=\\5cJo\\2a\\28\\29*\\5cn\\2a\\28\\29)(cn:2.4.6.8.19:=\\5cJohn\\2a \\28Doe\\29)"
+                + "(&(objectClass=\\5ctest\\2a\\28Value\\29)(sn~=\\5ctest\\2a\\28Value\\29)))",
+            Filter.newOrFilter(list2) }
+
+    };
+  }
+
+
+
+  /**
+   * Decodes the specified filter strings.
+   *
+   * @param filterStr
+   * @param filter
+   * @throws Exception
+   */
+  @Test(dataProvider = "filterstrings")
+  public void testDecode(final String filterStr, final Filter filter)
+      throws Exception
+  {
+    final Filter decoded = Filter.valueOf(filterStr);
+    assertEquals(decoded.toString(), filter.toString());
+  }
+
+
+
+  /**
+   * Decodes the erroneous filter strings.
+   *
+   * @param filterStr
+   * @param filter
+   * @throws Exception
+   */
+  @Test(dataProvider = "badfilterstrings", expectedExceptions = {
+      LocalizedIllegalArgumentException.class, NullPointerException.class })
+  public void testDecodeException(final String filterStr, final Filter filter)
+      throws Exception
+  {
+    Filter.valueOf(filterStr);
+  }
+
+
+
+  /**
+   * Tests the matcher.
+   *
+   * @throws Exception
+   */
+  @Test
+  public void testMatcher() throws Exception
+  {
+    final Filter equal = Filter.newEqualityMatchFilter("cn", ByteString
+        .valueOf("\\test*(Value)"));
+    final LinkedHashMapEntry entry = new LinkedHashMapEntry(DN
+        .valueOf("cn=\\test*(Value),dc=org"));
+    entry.addAttribute("cn", "\\test*(Value)");
+    entry.addAttribute("objectclass", "top,person");
+    final Matcher matcher = equal.matcher();
+    assertTrue(matcher.matches(entry).toBoolean());
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/HeartBeatConnectionFactoryTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/HeartBeatConnectionFactoryTestCase.java
new file mode 100644
index 0000000..d1adf26
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/HeartBeatConnectionFactoryTestCase.java
@@ -0,0 +1,71 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.util.concurrent.TimeUnit;
+
+import org.opends.sdk.requests.Requests;
+import org.opends.sdk.requests.SearchRequest;
+
+
+
+/**
+ * Tests the Heart beat connection factory.
+ */
+public class HeartBeatConnectionFactoryTestCase extends
+    ConnectionFactoryTestCase
+{
+  // Use custom search request.
+  SearchRequest request = Requests.newSearchRequest(
+      "uid=user.0,ou=people,o=test", SearchScope.BASE_OBJECT, "objectclass=*",
+      "cn");
+
+  // The factory.
+  private final HeartBeatConnectionFactory factory = new HeartBeatConnectionFactory(
+      new LDAPConnectionFactory("localhost", TestCaseUtils.getLdapPort()),
+      1000, TimeUnit.MILLISECONDS, request);
+
+
+
+  @Override
+  protected FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      final ResultHandler<AsynchronousConnection> handler) throws Exception
+  {
+    return factory.getAsynchronousConnection(handler);
+  }
+
+
+
+  @Override
+  protected Connection getConnection() throws Exception
+  {
+    return factory.getConnection();
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/InternalConnectionFactoryTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/InternalConnectionFactoryTestCase.java
new file mode 100644
index 0000000..c462aac
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/InternalConnectionFactoryTestCase.java
@@ -0,0 +1,57 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+/**
+ * Tests the internal connection factory.
+ */
+public class InternalConnectionFactoryTestCase extends
+    ConnectionFactoryTestCase
+{
+  private final ConnectionFactory factory = Connections
+      .newInternalConnectionFactory(LDAPServer.getInstance(), null);
+
+
+
+  @Override
+  protected FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      final ResultHandler<AsynchronousConnection> handler) throws Exception
+  {
+    return factory.getAsynchronousConnection(handler);
+  }
+
+
+
+  @Override
+  protected Connection getConnection() throws Exception
+  {
+    return factory.getConnection();
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPConnectionFactoryTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPConnectionFactoryTestCase.java
new file mode 100644
index 0000000..1ff4b85
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPConnectionFactoryTestCase.java
@@ -0,0 +1,56 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+/**
+ * Tests the LDAP connection factory.
+ */
+public class LDAPConnectionFactoryTestCase extends ConnectionFactoryTestCase
+{
+  private final LDAPConnectionFactory factory = new LDAPConnectionFactory(
+      "localhost", TestCaseUtils.getLdapPort());
+
+
+
+  @Override
+  protected FutureResult<AsynchronousConnection> getAsynchronousConnection(
+      final ResultHandler<AsynchronousConnection> handler) throws Exception
+  {
+    return factory.getAsynchronousConnection(handler);
+  }
+
+
+
+  @Override
+  protected Connection getConnection() throws Exception
+  {
+    return factory.getConnection();
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPServer.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPServer.java
new file mode 100644
index 0000000..689ee2b
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPServer.java
@@ -0,0 +1,590 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+import org.opends.sdk.requests.*;
+import org.opends.sdk.responses.*;
+
+import com.sun.grizzly.TransportFactory;
+import com.sun.grizzly.nio.transport.TCPNIOTransport;
+import com.sun.opends.sdk.controls.AccountUsabilityRequestControl;
+import com.sun.opends.sdk.controls.AccountUsabilityResponseControl;
+import com.sun.opends.sdk.ldap.GrizzlyLDAPListenerOptions;
+
+
+
+/**
+ * A simple ldap server that manages 1000 entries and used for running
+ * testcases. //FIXME: make it MT-safe.
+ */
+public class LDAPServer implements ServerConnection<Integer>,
+    ServerConnectionFactory<LDAPClientContext, Integer>
+{
+  // Creates an abandonable request from the ordinary requests.
+  private static class AbandonableRequest implements Request
+  {
+    // the request.
+    private final Request request;
+
+    // whether is has been cancelled.
+    private final AtomicBoolean isCanceled;
+
+
+
+    // Ctor.
+    AbandonableRequest(final Request request)
+    {
+      this.request = request;
+      this.isCanceled = new AtomicBoolean(false);
+    }
+
+
+
+    public Request addControl(final Control cntrl)
+        throws UnsupportedOperationException, NullPointerException
+    {
+      return request.addControl(cntrl);
+    }
+
+
+
+    public <C extends Control> C getControl(final ControlDecoder<C> decoder,
+        final DecodeOptions options) throws DecodeException,
+        NullPointerException
+    {
+      return request.getControl(decoder, options);
+    }
+
+
+
+    public List<Control> getControls()
+    {
+      return request.getControls();
+    }
+
+
+
+    void cancel()
+    {
+      isCanceled.set(true);
+    }
+
+
+
+    boolean isCanceled()
+    {
+      return isCanceled.get();
+    }
+  }
+
+
+
+  // The singleton instance.
+  private static final LDAPServer instance = new LDAPServer();
+
+
+
+  /**
+   * Returns the singleton instance.
+   *
+   * @return Singleton instance.
+   */
+  public static LDAPServer getInstance()
+  {
+    return instance;
+  }
+
+
+
+  // The mapping between entry DNs and the corresponding entries.
+  private final ConcurrentHashMap<DN, SearchResultEntry> entryMap = new ConcurrentHashMap<DN, SearchResultEntry>();
+
+  // The grizzly transport.
+  private final TCPNIOTransport transport = TransportFactory.getInstance()
+      .createTCPTransport();
+
+  // The LDAP listener.
+  private LDAPListener listener = null;
+
+  // whether the server is running.
+  private volatile boolean isRunning;
+
+  // The mapping between the message id and the requests the server is currently
+  // handling.
+  private final ConcurrentHashMap<Integer, AbandonableRequest> requestsInProgress = new ConcurrentHashMap<Integer, AbandonableRequest>();
+
+  // The Set used for locking dns.
+  private final HashSet<DN> lockedDNs = new HashSet<DN>();
+
+
+
+  private LDAPServer()
+  {
+    // Add the root dse first.
+    entryMap.put(DN.rootDN(), Responses.newSearchResultEntry(DN.rootDN()));
+    for (int i = 0; i < 1000; i++)
+    {
+      final String dn = String.format("uid=user.%d,ou=people,o=test", i);
+      final String cn = String.format("cn: user.%d", i);
+      final String sn = String.format("sn: %d", i);
+      final String uid = String.format("uid: user.%d", i);
+
+      final DN d = DN.valueOf(dn);
+      final SearchResultEntry e = Responses.newSearchResultEntry("dn: " + dn,
+          "objectclass: person", "objectclass: inetorgperson",
+          "objectclass: top", cn, sn, uid);
+      entryMap.put(d, e);
+    }
+  }
+
+
+
+  /**
+   * Abandons the request sent by the client.
+   *
+   * @param context
+   * @param request
+   * @throws UnsupportedOperationException
+   */
+  public void abandon(final Integer context, final AbandonRequest request)
+      throws UnsupportedOperationException
+  {
+    // Check if we have any concurrent operation with this message id.
+    final AbandonableRequest req = requestsInProgress.get(context);
+    if (req == null)
+    {
+      // Nothing to do here.
+      return;
+    }
+    // Cancel the request
+    req.cancel();
+    // No response is needed.
+  }
+
+
+
+  /**
+   * @param context
+   * @return
+   */
+  public ServerConnection<Integer> accept(final LDAPClientContext context)
+  {
+    return this;
+  }
+
+
+
+  /**
+   * Adds the request sent by the client.
+   *
+   * @param context
+   * @param request
+   * @param handler
+   * @param intermediateResponseHandler
+   * @throws UnsupportedOperationException
+   */
+  public void add(final Integer context, final AddRequest request,
+      final ResultHandler<Result> handler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException
+  {
+    Result result = null;
+    final AbandonableRequest abReq = new AbandonableRequest(request);
+    requestsInProgress.put(context, abReq);
+    // Get the DN.
+    final DN dn = request.getName();
+    if (entryMap.containsKey(dn))
+    {
+      // duplicate entry.
+      result = Responses.newResult(ResultCode.ENTRY_ALREADY_EXISTS);
+      final ErrorResultException ere = ErrorResultException.wrap(result);
+      handler.handleErrorResult(ere);
+      // doesn't matter if it was canceled.
+      requestsInProgress.remove(context);
+      return;
+    }
+
+    // Create an entry out of this request.
+    final SearchResultEntry entry = Responses.newSearchResultEntry(dn);
+    for (final Control control : request.getControls())
+    {
+      entry.addControl(control);
+    }
+
+    for (final Attribute attr : request.getAllAttributes())
+    {
+      entry.addAttribute(attr);
+    }
+
+    if (abReq.isCanceled())
+    {
+      result = Responses.newResult(ResultCode.CANCELLED);
+      final ErrorResultException ere = ErrorResultException.wrap(result);
+      handler.handleErrorResult(ere);
+      requestsInProgress.remove(context);
+      return;
+    }
+    // Add this to the map.
+    entryMap.put(dn, entry);
+    requestsInProgress.remove(context);
+    result = Responses.newResult(ResultCode.SUCCESS);
+    handler.handleResult(result);
+  }
+
+
+
+  /**
+   * @param context
+   * @param version
+   * @param request
+   * @param resultHandler
+   * @param intermediateResponseHandler
+   * @throws UnsupportedOperationException
+   */
+  public void bind(final Integer context, final int version,
+      final BindRequest request,
+      final ResultHandler<? super BindResult> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException
+  {
+    // TODO: all bind types.
+    final AbandonableRequest abReq = new AbandonableRequest(request);
+    requestsInProgress.put(context, abReq);
+    resultHandler.handleResult(Responses.newBindResult(ResultCode.SUCCESS));
+    requestsInProgress.remove(context);
+  }
+
+
+
+  /**
+   * @param context
+   * @param request
+   */
+  public void closed(final Integer context, final UnbindRequest request)
+  {
+
+  }
+
+
+
+  /**
+   * @param error
+   */
+  public void closed(final Throwable error)
+  {
+
+  }
+
+
+
+  /**
+   * @param context
+   * @param request
+   * @param resultHandler
+   * @param intermediateResponseHandler
+   * @throws UnsupportedOperationException
+   */
+  public void compare(final Integer context, final CompareRequest request,
+      final ResultHandler<? super CompareResult> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException
+  {
+    CompareResult result = null;
+    final AbandonableRequest abReq = new AbandonableRequest(request);
+    requestsInProgress.put(context, abReq);
+    // Get the DN.
+    final DN dn = request.getName();
+    if (!entryMap.containsKey(dn))
+    {
+      // entry not found.
+      result = Responses.newCompareResult(ResultCode.NO_SUCH_ATTRIBUTE);
+      final ErrorResultException ere = ErrorResultException.wrap(result);
+      resultHandler.handleErrorResult(ere);
+      // doesn't matter if it was canceled.
+      requestsInProgress.remove(context);
+      return;
+    }
+
+    // Get the entry.
+    final SearchResultEntry entry = entryMap.get(dn);
+    final AttributeDescription attrDesc = request.getAttributeDescription();
+    for (final Attribute attr : entry.getAllAttributes(attrDesc))
+    {
+      final Iterator<ByteString> it = attr.iterator();
+      while (it.hasNext())
+      {
+        final ByteString s = it.next();
+        if (abReq.isCanceled())
+        {
+          final Result r = Responses.newResult(ResultCode.CANCELLED);
+          final ErrorResultException ere = ErrorResultException.wrap(r);
+          resultHandler.handleErrorResult(ere);
+          requestsInProgress.remove(context);
+          return;
+        }
+        if (s.equals(request.getAssertionValue()))
+        {
+          result = Responses.newCompareResult(ResultCode.COMPARE_TRUE);
+          resultHandler.handleResult(result);
+        }
+      }
+    }
+    result = Responses.newCompareResult(ResultCode.COMPARE_FALSE);
+    resultHandler.handleResult(result);
+    requestsInProgress.remove(context);
+  }
+
+
+
+  /**
+   * @param context
+   * @param request
+   * @param handler
+   * @param intermediateResponseHandler
+   * @throws UnsupportedOperationException
+   */
+  public void delete(final Integer context, final DeleteRequest request,
+      final ResultHandler<Result> handler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException
+  {
+    Result result = null;
+    final AbandonableRequest abReq = new AbandonableRequest(request);
+    requestsInProgress.put(context, abReq);
+    // Get the DN.
+    final DN dn = request.getName();
+    if (!entryMap.containsKey(dn))
+    {
+      // entry is not found.
+      result = Responses.newResult(ResultCode.NO_SUCH_OBJECT);
+      final ErrorResultException ere = ErrorResultException.wrap(result);
+      handler.handleErrorResult(ere);
+      // doesn't matter if it was canceled.
+      requestsInProgress.remove(context);
+      return;
+    }
+
+    if (abReq.isCanceled())
+    {
+      result = Responses.newResult(ResultCode.CANCELLED);
+      final ErrorResultException ere = ErrorResultException.wrap(result);
+      handler.handleErrorResult(ere);
+      requestsInProgress.remove(context);
+      return;
+    }
+    // Remove this from the map.
+    entryMap.remove(dn);
+    requestsInProgress.remove(context);
+  }
+
+
+
+  /**
+   * @param context
+   * @param request
+   * @param resultHandler
+   * @param intermediateResponseHandler
+   * @throws UnsupportedOperationException
+   */
+  public <R extends ExtendedResult> void extendedRequest(final Integer context,
+      final ExtendedRequest<R> request, final ResultHandler<R> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException
+  {
+    // TODO:
+  }
+
+
+
+  /**
+   * Returns whether the server is running or not.
+   *
+   * @return Whether the server is running.
+   */
+  public boolean isRunning()
+  {
+    return isRunning;
+  }
+
+
+
+  /**
+   * @param context
+   * @param request
+   * @param resultHandler
+   * @param intermediateResponseHandler
+   * @throws UnsupportedOperationException
+   */
+  public void modify(final Integer context, final ModifyRequest request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException
+  {
+    // TODO:
+  }
+
+
+
+  /**
+   * @param context
+   * @param request
+   * @param resultHandler
+   * @param intermediateResponseHandler
+   * @throws UnsupportedOperationException
+   */
+  public void modifyDN(final Integer context, final ModifyDNRequest request,
+      final ResultHandler<Result> resultHandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException
+  {
+    // TODO
+  }
+
+
+
+  /**
+   * @param context
+   * @param request
+   * @param resultHandler
+   * @param searchResulthandler
+   * @param intermediateResponseHandler
+   * @throws UnsupportedOperationException
+   */
+  public void search(final Integer context, final SearchRequest request,
+      final ResultHandler<Result> resultHandler,
+      final SearchResultHandler searchResulthandler,
+      final IntermediateResponseHandler intermediateResponseHandler)
+      throws UnsupportedOperationException
+  {
+    Result result = null;
+    final AbandonableRequest abReq = new AbandonableRequest(request);
+    requestsInProgress.put(context, abReq);
+    // Get the DN.
+    final DN dn = request.getName();
+    if (!entryMap.containsKey(dn))
+    {
+      // Entry not found.
+      result = Responses.newResult(ResultCode.NO_SUCH_OBJECT);
+      final ErrorResultException ere = ErrorResultException.wrap(result);
+      resultHandler.handleErrorResult(ere);
+      // Should searchResultHandler handle anything?
+
+      // doesn't matter if it was canceled.
+      requestsInProgress.remove(context);
+      return;
+    }
+
+    if (abReq.isCanceled())
+    {
+      result = Responses.newResult(ResultCode.CANCELLED);
+      final ErrorResultException ere = ErrorResultException.wrap(result);
+      resultHandler.handleErrorResult(ere);
+      requestsInProgress.remove(context);
+      return;
+    }
+
+    final SearchResultEntry e = entryMap.get(dn);
+    // Check we have had any controls in the request.
+    for (final Control control : request.getControls())
+    {
+      if (control.getOID().equals(AccountUsabilityRequestControl.OID))
+      {
+        e.addControl(AccountUsabilityResponseControl.newControl(false, false,
+            false, 10, false, 0));
+      }
+    }
+    searchResulthandler.handleEntry(e);
+    result = Responses.newResult(ResultCode.SUCCESS);
+    resultHandler.handleResult(result);
+    requestsInProgress.remove(context);
+  }
+
+
+
+  /**
+   * Starts the server.
+   *
+   * @param port
+   * @exception IOException
+   */
+  public void start(final int port) throws IOException
+  {
+    if (isRunning)
+    {
+      return;
+    }
+    transport.setSelectorRunnersCount(2);
+    listener = new LDAPListener(port, new LDAPServer(),
+        new GrizzlyLDAPListenerOptions().setTCPNIOTransport(transport)
+            .setBacklog(4096));
+    transport.start();
+    isRunning = true;
+  }
+
+
+
+  /**
+   * Stops the server.
+   */
+  public void stop()
+  {
+    if (!isRunning)
+    {
+      return;
+    }
+    try
+    {
+      listener.close();
+    }
+    catch (final IOException e)
+    {
+      e.printStackTrace();
+    }
+    try
+    {
+      transport.stop();
+    }
+    catch (final IOException e)
+    {
+      e.printStackTrace();
+    }
+    TransportFactory.getInstance().close();
+    isRunning = false;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPUrlTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPUrlTestCase.java
new file mode 100644
index 0000000..df0222d
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPUrlTestCase.java
@@ -0,0 +1,232 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * This class defines a set of tests for the org.opends.sdk.LDAPUrl class.
+ */
+public class LDAPUrlTestCase extends SdkTestCase
+{
+  /**
+   * LDAPUrl encoding test data provider.
+   *
+   * @return The array of test encoding of LDAP URL strings.
+   */
+  @DataProvider(name = "ldapurls")
+  public Object[][] createEncodingData()
+  {
+    return new Object[][] {
+        { "ldap://", "ldap://", true },
+        { "ldap:///", "ldap:///", true },
+        { "ldap://ldap.example.net", "ldap://ldap.example.net", true },
+        { "ldap://ldap.example.net/", "ldap://ldap.example.net/", true },
+        { "ldap://ldap.example.net/?", "ldap://ldap.example.net/?", true },
+        { "ldap:///o=University of Michigan,c=US",
+            "ldap:///o=University%20of%20Michigan,c=US", true },
+        { "ldap://ldap1.example.net/o=University of Michigan,c=US",
+            "ldap://ldap1.example.net/o=University%20of%20Michigan,c=US", true },
+        {
+            "ldap://ldap1.example.net/o=University of Michigan,c=US?postalAddress",
+            "ldap://ldap1.example.net/o=University%20of%20Michigan,c=US?postalAddress",
+            true },
+        {
+            "ldap://ldap1.example.net:6666/o=University of Michigan,c=US??sub?(cn=Babs Jensen)",
+            "ldap://ldap1.example.net:6666/o=University%20of%20Michigan,c=US??sub?(cn=Babs%20Jensen)",
+            true },
+        { "LDAP://ldap1.example.com/c=GB?objectClass?ONE",
+            "LDAP://ldap1.example.com/c=GB?objectClass?ONE", true },
+        // { "ldap://ldap2.example.com/o=Question?,c=US?mail",
+        // "ldap://ldap2.example.com/o=Question%3f,c=US?mail",true },
+        {
+            "ldap://ldap3.example.com/o=Babsco,c=US???(four-octet=\00\00\00\04)",
+            "ldap://ldap3.example.com/o=Babsco,c=US???(four-octet=%5c00%5c00%5c00%5c04)",
+            true },
+        { "ldap://ldap.example.com/o=An Example\\2C Inc.,c=US",
+            "ldap://ldap.example.com/o=An%20Example%5C2C%20Inc.,c=US", true },
+        { "ldap:///", "ldap:///", true }, { "ldap:///", "ldap:///", true },
+        { "ldap:///", "ldap:///", true }, };
+  }
+
+
+
+  /**
+   * LDAPUrl construction test data provider.
+   *
+   * @return The array of test construction of LDAPUrl objects.
+   */
+  @DataProvider(name = "urlobjects1")
+  public Object[][] createURLObjects1()
+  {
+    return new Object[][] {
+        { new LDAPUrl(false, null, null, null, null, null), "ldap:///???" },
+        { new LDAPUrl(true, null, null, null, null, null), "ldaps:///???" },
+        { new LDAPUrl(true, "void.central.sun.com", null, null, null, null),
+            "ldaps://void.central.sun.com/???" },
+        { new LDAPUrl(true, null, 1245, null, null, null), "ldaps://:1245/???" },
+        { new LDAPUrl(true, "void.central", 123, null, null, null),
+            "ldaps://void.central:123/???" },
+        { new LDAPUrl(true, null, null, null, null, null, "cn", "sn"),
+            "ldaps:///?cn,sn??" },
+        {
+            new LDAPUrl(true, null, null, null, null, Filter
+                .newEqualityMatchFilter("uid", "abc"), "cn"),
+            "ldaps:///?cn??(uid=abc)" },
+        {
+            new LDAPUrl(true, null, null, null, SearchScope.WHOLE_SUBTREE,
+                Filter.newEqualityMatchFilter("uid", "abc"), "cn"),
+            "ldaps:///?cn?sub?(uid=abc)" },
+        {
+            new LDAPUrl(true, null, null, DN.valueOf("uid=abc,o=target"),
+                SearchScope.WHOLE_SUBTREE, Filter.newEqualityMatchFilter("uid",
+                    "abc"), "cn"), "ldaps:///uid=abc,o=target?cn?sub?(uid=abc)" },
+        {
+            new LDAPUrl(true, "localhost", 1345,
+                DN.valueOf("uid=abc,o=target"), SearchScope.WHOLE_SUBTREE,
+                Filter.newEqualityMatchFilter("uid", "abc"), "cn"),
+            "ldaps://localhost:1345/uid=abc,o=target?cn?sub?(uid=abc)" }, };
+  }
+
+
+
+  /**
+   * LDAPUrl construction test data provider.
+   *
+   * @return The array of test construction of LDAPUrl objects.
+   */
+  @DataProvider(name = "urlobjects2")
+  public Object[][] createURLObjects2()
+  {
+    return new Object[][] {
+        { new LDAPUrl(false, null, null, null, null, null),
+            LDAPUrl.valueOf("ldap:///") },
+        { new LDAPUrl(true, null, null, null, null, null),
+            LDAPUrl.valueOf("ldaps:///") },
+        { new LDAPUrl(true, "void.central.sun.com", null, null, null, null),
+            LDAPUrl.valueOf("ldaps://void.central.sun.com") },
+        { new LDAPUrl(true, null, 1245, null, null, null),
+            LDAPUrl.valueOf("ldaps://:1245") },
+        { new LDAPUrl(true, "void.central", 123, null, null, null),
+            LDAPUrl.valueOf("ldaps://void.central:123") },
+        { new LDAPUrl(true, null, null, null, null, null, "cn", "sn"),
+            LDAPUrl.valueOf("ldaps:///?cn,sn??") },
+        {
+            new LDAPUrl(true, null, null, null, null, Filter
+                .newEqualityMatchFilter("uid", "abc"), "cn"),
+            LDAPUrl.valueOf("ldaps:///?cn??(uid=abc)") },
+        {
+            new LDAPUrl(true, null, null, null, SearchScope.WHOLE_SUBTREE,
+                Filter.newEqualityMatchFilter("uid", "abc"), "cn"),
+            LDAPUrl.valueOf("ldaps:///?cn?sub?(uid=abc)") },
+        {
+            new LDAPUrl(true, null, null, DN.valueOf("uid=abc,o=target"),
+                SearchScope.WHOLE_SUBTREE, Filter.newEqualityMatchFilter("uid",
+                    "abc"), "cn"),
+            LDAPUrl.valueOf("ldaps:///uid=abc,o=target?cn?sub?(uid=abc)") },
+        {
+            new LDAPUrl(true, "localhost", 1345,
+                DN.valueOf("uid=abc,o=target"), SearchScope.WHOLE_SUBTREE,
+                Filter.newEqualityMatchFilter("uid", "abc"), "cn"),
+            LDAPUrl
+                .valueOf("ldaps://localhost:1345/uid=abc,o=target?cn?sub?(uid=abc)") }, };
+  }
+
+
+
+  /**
+   * Tests equals method of the LDAP URL.
+   *
+   * @param urlObj1
+   *          The LDAPUrl object.
+   * @param urlObj2
+   *          The LDAPUrl object.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "urlobjects2")
+  public void testLDAPURLCtor(final LDAPUrl urlObj1, final LDAPUrl urlObj2)
+      throws Exception
+  {
+    assertTrue(urlObj1.equals(urlObj2));
+  }
+
+
+
+  /**
+   * Test Whether the LDAP URL (non-encoded) is constructed properly from the
+   * arguments.
+   *
+   * @param urlObj
+   *          The LDAPUrl object.
+   * @param urlString
+   *          The non-encoded ldap url.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "urlobjects1")
+  public void testLDAPURLCtor(final LDAPUrl urlObj, final String urlString)
+      throws Exception
+  {
+    assertEquals(urlString, urlObj.toString());
+  }
+
+
+
+  /**
+   * Test the LDAP URL encoding.
+   *
+   * @param toEncode
+   *          The URL that needs encoding.
+   * @param encoded
+   *          The encoded URL.
+   * @param valid
+   *          if the encoding is valid.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "ldapurls")
+  public void testURLEncoding(final String toEncode, final String encoded,
+      final boolean valid) throws Exception
+  {
+    final LDAPUrl url1 = LDAPUrl.valueOf(toEncode);
+    final LDAPUrl url2 = LDAPUrl.valueOf(encoded);
+    if (valid)
+    {
+      assertTrue(url1.equals(url2));
+    }
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTestCase.java
similarity index 75%
rename from sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTest.java
rename to sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTestCase.java
index d4e53e9..9a84966 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTestCase.java
@@ -22,7 +22,7 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2009-2010 Sun Microsystems, Inc.
  */
 
 package org.opends.sdk;
@@ -33,23 +33,20 @@
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
-import org.opends.sdk.ByteString;
-
 
 
 /**
  * Test {@code BasicAttribute}.
  */
-@Test(groups = { "precommit", "types", "sdk" }, sequential = true)
-public final class LinkedAttributeTest extends OpenDSTestCase
+
+public final class LinkedAttributeTestCase extends SdkTestCase
 {
   @Test
-  public void SmokeTest() throws Exception
+  public void smokeTest() throws Exception
   {
     // TODO: write a proper test suite.
-    AbstractAttribute attribute = new LinkedAttribute(
-        AttributeDescription.valueOf("ALTSERVER", Schema
-            .getCoreSchema()));
+    final AbstractAttribute attribute = new LinkedAttribute(
+        AttributeDescription.valueOf("ALTSERVER", Schema.getCoreSchema()));
 
     attribute.add(1);
     attribute.add("a value");
@@ -57,8 +54,7 @@
 
     Assert.assertTrue(attribute.contains(1));
     Assert.assertTrue(attribute.contains("a value"));
-    Assert.assertTrue(attribute.contains(ByteString
-        .valueOf("another value")));
+    Assert.assertTrue(attribute.contains(ByteString.valueOf("another value")));
 
     Assert.assertEquals(attribute.size(), 3);
     Assert.assertTrue(attribute.remove(1));
@@ -67,8 +63,7 @@
     Assert.assertEquals(attribute.size(), 2);
     Assert.assertTrue(attribute.remove("a value"));
     Assert.assertEquals(attribute.size(), 1);
-    Assert.assertTrue(attribute.remove(ByteString
-        .valueOf("another value")));
+    Assert.assertTrue(attribute.remove(ByteString.valueOf("another value")));
     Assert.assertEquals(attribute.size(), 0);
   }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/OpenDSTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/OpenDSTestCase.java
index 54ff24c..99a903f 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/OpenDSTestCase.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/OpenDSTestCase.java
@@ -40,11 +40,11 @@
 
 
 /**
- * This class defines a base test case that should be subclassed by all
- * unit tests used by OpenDS.
+ * This class defines a base test case that should be subclassed by all unit
+ * tests used by OpenDS.
  * <p>
- * This class adds the ability to print error messages and automatically
- * have them include the class name.
+ * This class adds the ability to print error messages and automatically have
+ * them include the class name.
  */
 @Test(sequential = true)
 public abstract class OpenDSTestCase
@@ -60,64 +60,36 @@
   //
 
   /**
-   * A list of all parameters that were generated by a @DataProvider and
-   * passed to a test method of this class. TestListener helps us keep
-   * this so that once all of the tests are finished, we can clear it
-   * out in an @AfterClass method. We can't just clear it out right away
-   * in the TestListener because some methods share a @DataProvider.
+   * A list of all parameters that were generated by a @DataProvider and passed
+   * to a test method of this class. TestListener helps us keep this so that
+   * once all of the tests are finished, we can clear it out in an @AfterClass
+   * method. We can't just clear it out right away in the TestListener because
+   * some methods share a @DataProvider.
    */
   private final IdentityHashMap<Object[], Object> successfulTestParams = new IdentityHashMap<Object[], Object>();
 
   /**
-   * These are test parameters from a test that has failed. We need to
-   * keep these around because the test report expects to find them when
-   * printing out failures.
+   * These are test parameters from a test that has failed. We need to keep
+   * these around because the test report expects to find them when printing out
+   * failures.
    */
   private final IdentityHashMap<Object[], Object> failedTestParams = new IdentityHashMap<Object[], Object>();
 
 
 
   /**
-   * Adds testParams to the list of all test parameters, so it can be
-   * null'ed out later if it's not part.
-   */
-  void addParamsFromSuccessfulTests(Object[] testParams)
-  {
-    if (testParams != null)
-    {
-      successfulTestParams.put(testParams, testParams);
-    }
-  }
-
-
-
-  /**
-   * Adds testParams to the list of all failed test parameters, so that
-   * we know to NOT null it out later.
-   */
-  void addParamsFromFailedTest(Object[] testParams)
-  {
-    if (testParams != null)
-    {
-      failedTestParams.put(testParams, testParams);
-    }
-  }
-
-
-
-  /**
-   * null out all test parameters except the ones used in failed tests
-   * since we might need these again.
+   * null out all test parameters except the ones used in failed tests since we
+   * might need these again.
    */
   @AfterClass(alwaysRun = true)
   public void clearSuccessfulTestParams()
   {
-    Set<Object[]> paramsSet = successfulTestParams.keySet();
+    final Set<Object[]> paramsSet = successfulTestParams.keySet();
     if (paramsSet == null)
     { // Can this ever happen?
       return;
     }
-    for (Object[] params : paramsSet)
+    for (final Object[] params : paramsSet)
     {
       if (failedTestParams.containsKey(params))
       {
@@ -136,12 +108,11 @@
 
 
   /**
-   * The member variables of a test class can prevent lots of memory
-   * from being reclaimed, so we use reflection to null out all of the
-   * member variables after the tests have run. Since all tests must
-   * inherit from DirectoryServerTestCase, TestNG guarantees that this
-   * method runs after all of the subclass methods, so this isn't too
-   * dangerous.
+   * The member variables of a test class can prevent lots of memory from being
+   * reclaimed, so we use reflection to null out all of the member variables
+   * after the tests have run. Since all tests must inherit from
+   * DirectoryServerTestCase, TestNG guarantees that this method runs after all
+   * of the subclass methods, so this isn't too dangerous.
    */
   @AfterClass(alwaysRun = true)
   public void nullMemberVariablesAfterTest()
@@ -152,27 +123,25 @@
     while (OpenDSTestCase.class.isAssignableFrom(cls)
         && !OpenDSTestCase.class.equals(cls))
     {
-      Field fields[] = cls.getDeclaredFields();
-      for (int i = 0; i < fields.length; i++)
+      final Field fields[] = cls.getDeclaredFields();
+      for (final Field field : fields)
       {
-        Field field = fields[i];
-        int modifiers = field.getModifiers();
-        Class<?> fieldClass = field.getType();
+        final int modifiers = field.getModifiers();
+        final Class<?> fieldClass = field.getType();
         // If it's a non-static non-final non-primitive type, then null
         // it out
         // so that the garbage collector can reclaim it and everything
         // it
         // references.
         if (!fieldClass.isPrimitive() && !fieldClass.isEnum()
-            && !Modifier.isFinal(modifiers)
-            && !Modifier.isStatic(modifiers))
+            && !Modifier.isFinal(modifiers) && !Modifier.isStatic(modifiers))
         {
           field.setAccessible(true);
           try
           {
             field.set(this, null);
           }
-          catch (IllegalAccessException e)
+          catch (final IllegalAccessException e)
           {
             // We're only doing this to save memory, so it's no big deal
             // if we can't set it.
@@ -182,4 +151,32 @@
       cls = cls.getSuperclass();
     }
   }
+
+
+
+  /**
+   * Adds testParams to the list of all failed test parameters, so that we know
+   * to NOT null it out later.
+   */
+  void addParamsFromFailedTest(final Object[] testParams)
+  {
+    if (testParams != null)
+    {
+      failedTestParams.put(testParams, testParams);
+    }
+  }
+
+
+
+  /**
+   * Adds testParams to the list of all test parameters, so it can be null'ed
+   * out later if it's not part.
+   */
+  void addParamsFromSuccessfulTests(final Object[] testParams)
+  {
+    if (testParams != null)
+    {
+      successfulTestParams.put(testParams, testParams);
+    }
+  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/RDNTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/RDNTestCase.java
new file mode 100644
index 0000000..584fbfb
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/RDNTestCase.java
@@ -0,0 +1,481 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
+import java.util.Iterator;
+
+import org.opends.sdk.schema.AttributeType;
+import org.opends.sdk.schema.Schema;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.sun.opends.sdk.util.Platform;
+
+
+
+/**
+ * This class defines a set of tests for the {@link org.opends.sdk.RDN} class.
+ */
+public final class RDNTestCase extends TypesTestCase
+{
+
+  // Domain component attribute type.
+  private AttributeType AT_DC;
+
+  // Common name attribute type.
+  private AttributeType AT_CN;
+
+  // Test attribute value.
+  private AVA AV_DC_ORG;
+
+  // org bytestring.
+  private static final ByteString ORG = ByteString.valueOf("org");
+
+  // opends bytestring.
+  private static final ByteString OPENDS = ByteString.valueOf("opends");
+
+
+
+  /**
+   * RDN test data provider.
+   *
+   * @return The array of test RDN strings.
+   */
+  @DataProvider(name = "testRDNs")
+  public Object[][] createData()
+  {
+    return new Object[][] {
+        { "dc=hello world", "dc=hello world", "dc=hello world" },
+        { "dc =hello world", "dc=hello world", "dc=hello world" },
+        { "dc  =hello world", "dc=hello world", "dc=hello world" },
+        { "dc= hello world", "dc=hello world", "dc=hello world" },
+        { "dc=  hello world", "dc=hello world", "dc=hello world" },
+        { "undefined=hello", "undefined=hello", "undefined=hello" },
+        { "DC=HELLO WORLD", "dc=hello world", "DC=HELLO WORLD" },
+        { "dc = hello    world", "dc=hello world", "dc=hello    world" },
+        { "   dc = hello world   ", "dc=hello world", "dc=hello world" },
+        { "givenName=John+cn=Doe", "cn=doe+givenname=john",
+            "givenName=John+cn=Doe" },
+        { "givenName=John\\+cn=Doe", "givenname=john\\+cn\\=doe",
+            "givenName=John\\+cn=Doe" },
+        { "cn=Doe\\, John", "cn=doe\\, john", "cn=Doe\\, John" },
+        { "OU=Sales+CN=J. Smith", "cn=j. smith+ou=sales",
+            "OU=Sales+CN=J. Smith" },
+        { "CN=James \\\"Jim\\\" Smith\\, III",
+            "cn=james \\\"jim\\\" smith\\, iii",
+            "CN=James \\\"Jim\\\" Smith\\, III" },
+        // \0d is a hex representation of Carriage return. It is mapped
+        // to a SPACE as defined in the MAP ( RFC 4518)
+        { "CN=Before\\0dAfter", "cn=before after", "CN=Before\\0dAfter" },
+        { "cn=#04024869",
+        // Unicode codepoints from 0000-0008 are mapped to nothing.
+            "cn=hi", "cn=\\04\\02Hi" },
+        { "CN=Lu\\C4\\8Di\\C4\\87", "cn=lu\u010di\u0107", "CN=Lu\u010di\u0107" },
+        { "ou=\\e5\\96\\b6\\e6\\a5\\ad\\e9\\83\\a8", "ou=\u55b6\u696d\u90e8",
+            "ou=\u55b6\u696d\u90e8" },
+        { "photo=\\ john \\ ", "photo=\\ john \\ ", "photo=\\ john \\ " },
+        { "AB-global=", "ab-global=", "AB-global=" },
+        { "cn=John+a=", "a=+cn=john", "cn=John+a=" },
+        { "O=\"Sue, Grabbit and Runn\"", "o=sue\\, grabbit and runn",
+            "O=Sue\\, Grabbit and Runn" }, };
+  }
+
+
+
+  /**
+   * Illegal RDN test data provider.
+   *
+   * @return The array of illegal test RDN strings.
+   */
+  @DataProvider(name = "illegalRDNs")
+  public Object[][] createIllegalData()
+  {
+    return new Object[][] { { null }, { "" }, { " " }, { "=" }, { "manager" },
+        { "manager " }, { "cn+" },
+        { "cn+Jim" },
+        { "cn=Jim+" },
+        { "cn=Jim +" },
+        { "cn=Jim+ " },
+        { "cn=Jim+sn" },
+        { "cn=Jim+sn " },
+        { "cn=Jim+sn equals" },// { "cn=Jim," }, { "cn=Jim;" }, { "cn=Jim,  " },
+        // { "cn=Jim+sn=a," }, { "cn=Jim, sn=Jam " }, { "cn+uid=Jim" },
+        { "-cn=Jim" }, { "/tmp=a" }, { "\\tmp=a" }, { "cn;lang-en=Jim" },
+        { "@cn=Jim" }, { "_name_=Jim" }, { "\u03c0=pi" }, { "v1.0=buggy" },
+        { "cn=Jim+sn=Bob++" }, { "cn=Jim+sn=Bob+," },
+        { "1.3.6.1.4.1.1466..0=#04024869" }, };
+  }
+
+
+
+  /**
+   * RDN equality test data provider.
+   *
+   * @return The array of test RDN strings.
+   */
+  @DataProvider(name = "createRDNEqualityData")
+  public Object[][] createRDNEqualityData()
+  {
+    return new Object[][] {
+        { "cn=hello world", "cn=hello world", 0 },
+        { "cn=hello world", "CN=hello world", 0 },
+        { "cn=hello   world", "cn=hello world", 0 },
+        { "  cn =  hello world  ", "cn=hello world", 0 },
+        { "cn=hello world\\ ", "cn=hello world", 0 },
+        { "cn=HELLO WORLD", "cn=hello world", 0 },
+        { "cn=HELLO+sn=WORLD", "sn=world+cn=hello", 0 },
+        { "cn=HELLO+sn=WORLD", "cn=hello+sn=nurse", 1 },
+        { "cn=HELLO+sn=WORLD", "cn=howdy+sn=yall", -1 },
+        { "cn=hello", "cn=hello+sn=world", -1 },
+        { "cn=hello+sn=world", "cn=hello", 1 },
+        { "cn=hello+sn=world", "cn=hello+description=world", 1 },
+        { "cn=hello", "sn=world", -1 },
+        { "sn=hello", "cn=world", 1 },
+        // { "x-test-integer-type=10", "x-test-integer-type=9", 1 },
+        // { "x-test-integer-type=999", "x-test-integer-type=1000", -1 },
+        // { "x-test-integer-type=-1", "x-test-integer-type=0", -1 },
+        // { "x-test-integer-type=0", "x-test-integer-type=-1", 1 },
+        { "cn=aaa", "cn=aaaa", -1 }, { "cn=AAA", "cn=aaaa", -1 },
+        { "cn=aaa", "cn=AAAA", -1 }, { "cn=aaaa", "cn=aaa", 1 },
+        { "cn=AAAA", "cn=aaa", 1 }, { "cn=aaaa", "cn=AAA", 1 },
+        { "cn=aaab", "cn=aaaa", 1 }, { "cn=aaaa", "cn=aaab", -1 } };
+  }
+
+
+
+  /**
+   * Set up the environment for performing the tests in this suite.
+   *
+   * @throws Exception
+   *           If the environment could not be set up.
+   */
+  @BeforeClass
+  public void setUp() throws Exception
+  {
+    AT_DC = Schema.getCoreSchema().getAttributeType("dc");
+    AT_CN = Schema.getCoreSchema().getAttributeType("cn");
+    // Set the avas.
+    AV_DC_ORG = new AVA(AT_DC, ByteString.valueOf("org"));
+  }
+
+
+
+  /**
+   * Test RDN compareTo
+   *
+   * @param first
+   *          First RDN to compare.
+   * @param second
+   *          Second RDN to compare.
+   * @param result
+   *          Expected comparison result.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createRDNEqualityData")
+  public void testCompareTo(final String first, final String second,
+      final int result) throws Exception
+  {
+    final RDN rdn1 = RDN.valueOf(first);
+    final RDN rdn2 = RDN.valueOf(second);
+
+    int rc = rdn1.compareTo(rdn2);
+
+    // Normalize the result.
+    if (rc < 0)
+    {
+      rc = -1;
+    }
+    else if (rc > 0)
+    {
+      rc = 1;
+    }
+
+    assertEquals(rc, result, "Comparison for <" + first + "> and <" + second
+        + ">.");
+  }
+
+
+
+  /**
+   * Test RDN construction with single AVA.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testConstructor() throws Exception
+  {
+    final RDN rdn = new RDN(AT_DC, ORG);
+
+    assertEquals(rdn.size(), 1);
+    assertEquals(rdn.isMultiValued(), false);
+    assertEquals(rdn.getFirstAVA().getAttributeType(), AT_DC);
+    assertEquals(rdn.getFirstAVA().getAttributeType().getNameOrOID(), AT_DC
+        .getNameOrOID());
+    assertEquals(rdn.getFirstAVA(), AV_DC_ORG);
+  }
+
+
+
+  /**
+   * Test RDN construction with String attribute type and value.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testConstructorWithString() throws Exception
+  {
+    final RDN rdn = new RDN("dc", "org");
+    assertEquals(rdn.size(), 1);
+    assertEquals(rdn.getFirstAVA().getAttributeType(), AT_DC);
+    assertEquals(rdn.getFirstAVA().getAttributeType().getNameOrOID(), "dc");
+    assertEquals(rdn.getFirstAVA(), AV_DC_ORG);
+  }
+
+
+
+  /**
+   * Test RDN string decoder against illegal strings.
+   *
+   * @param rawRDN
+   *          Illegal RDN string representation.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "illegalRDNs", expectedExceptions = {
+      NullPointerException.class, LocalizedIllegalArgumentException.class,
+      StringIndexOutOfBoundsException.class })
+  public void testDecodeIllegalString(final String rawRDN) throws Exception
+  {
+    RDN.valueOf(rawRDN);
+
+    fail("Expected exception for value \"" + rawRDN + "\"");
+  }
+
+
+
+  /**
+   * Test RDN string decoder.
+   *
+   * @param rawRDN
+   *          Raw RDN string representation.
+   * @param normRDN
+   *          Normalized RDN string representation.
+   * @param stringRDN
+   *          String representation.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  /**
+   * @Test(dataProvider = "testRDNs") public void testToString(String rawRDN,
+   *                    String normRDN, String stringRDN) throws Exception { RDN
+   *                    rdn = RDN.valueOf(rawRDN); assertEquals(rdn.toString(),
+   *                    stringRDN); }
+   **/
+
+  /**
+   * Test RDN string decoder.
+   *
+   * @param rawRDN
+   *          Raw RDN string representation.
+   * @param normRDN
+   *          Normalized RDN string representation.
+   * @param stringRDN
+   *          String representation.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "testRDNs")
+  public void testDecodeString(final String rawRDN, final String normRDN,
+      final String stringRDN) throws Exception
+  {
+    final RDN rdn = RDN.valueOf(rawRDN);
+    final StringBuilder buffer = new StringBuilder();
+    buffer.append(normRDN);
+    Platform.normalize(buffer);
+    final StringBuilder normalBuffer = new StringBuilder();
+    rdn.toNormalizedString(normalBuffer);
+    assertEquals(normalBuffer.toString(), buffer.toString());
+  }
+
+
+
+  /**
+   * Tests the valueof with ctor.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testDuplicateSingle()
+  {
+    final RDN rdn1 = new RDN(AT_DC, ORG);
+    final RDN rdn2 = RDN.valueOf("dc=org");
+
+    assertFalse(rdn1 == rdn2);
+    assertEquals(rdn1, rdn2);
+  }
+
+
+
+  /**
+   * Test RDN equality
+   *
+   * @param first
+   *          First RDN to compare.
+   * @param second
+   *          Second RDN to compare.
+   * @param result
+   *          Expected comparison result.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createRDNEqualityData")
+  public void testEquality(final String first, final String second,
+      final int result) throws Exception
+  {
+    final RDN rdn1 = RDN.valueOf(first);
+    final RDN rdn2 = RDN.valueOf(second);
+
+    if (result == 0)
+    {
+      assertTrue(rdn1.equals(rdn2), "RDN equality for <" + first + "> and <"
+          + second + ">");
+    }
+    else
+    {
+      assertFalse(rdn1.equals(rdn2), "RDN equality for <" + first + "> and <"
+          + second + ">");
+    }
+  }
+
+
+
+  /**
+   * Tests the equals method with a non-RDN argument.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testEqualityNonRDN()
+  {
+    final RDN rdn = new RDN(AT_DC, ORG);
+
+    assertFalse(rdn.equals("this isn't an RDN"));
+  }
+
+
+
+  /**
+   * Tests the equals method with a null argument.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testEqualityNull()
+  {
+    final RDN rdn = new RDN(AT_DC, ORG);
+
+    assertFalse(rdn.equals(null));
+  }
+
+
+
+  /**
+   * Test getAttributeName.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testGetAttributeName() throws Exception
+  {
+    final RDN rdn = RDN.valueOf("dc=opends+cn=org");
+    assertTrue(rdn.isMultiValued());
+    assertEquals(rdn.size(), 2);
+    final Iterator<AVA> it = rdn.iterator();
+    assertEquals(it.next().getAttributeType().getNameOrOID(), AT_DC
+        .getNameOrOID());
+    assertEquals(it.next().getAttributeType().getNameOrOID(), AT_CN
+        .getNameOrOID());
+  }
+
+
+
+  /**
+   * Test RDN hashCode
+   *
+   * @param first
+   *          First RDN to compare.
+   * @param second
+   *          Second RDN to compare.
+   * @param result
+   *          Expected comparison result.
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dataProvider = "createRDNEqualityData")
+  public void testHashCode(final String first, final String second,
+      final int result) throws Exception
+  {
+    final RDN rdn1 = RDN.valueOf(first);
+    final RDN rdn2 = RDN.valueOf(second);
+
+    final int h1 = rdn1.hashCode();
+    final int h2 = rdn2.hashCode();
+
+    if (result == 0)
+    {
+      if (h1 != h2)
+      {
+        fail("Hash codes for <" + first + "> and <" + second
+            + "> should be the same.");
+      }
+    }
+    else
+    {
+      if (h1 == h2)
+      {
+        fail("Hash codes for <" + first + "> and <" + second
+            + "> should be the same.");
+      }
+    }
+  }
+}
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/SdkTestCase.java
similarity index 70%
rename from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
rename to sdk/tests/unit-tests-testng/src/org/opends/sdk/SdkTestCase.java
index 62b3ae3..92da12a 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/SdkTestCase.java
@@ -22,21 +22,22 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
-
-package org.opends.sdk.sasl;
+package org.opends.sdk;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.testng.annotations.Test;
 
 
 
 /**
- * Password call-back.
+ * An abstract class that all types unit tests should extend. A type represents
+ * the classes found directly under the package org.opends.sdk.
  */
-public interface PasswordCallbackHandler
+
+@Test(groups = { "precommit", "types", "sdk" }, sequential = true)
+public abstract class SdkTestCase extends OpenDSTestCase
 {
-  public boolean handle(PasswordCallback callback);
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/SortedEntryTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/SortedEntryTest.java
deleted file mode 100644
index f0e572c..0000000
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/SortedEntryTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License").  You may not use this file except in compliance
- * with the License.
- *
- * You can obtain a copy of the license at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE
- * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at
- * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
- * add the following below this CDDL HEADER, with the fields enclosed
- * by brackets "[]" replaced with your own identifying information:
- *      Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- *
- *
- *      Copyright 2009 Sun Microsystems, Inc.
- */
-
-package org.opends.sdk;
-
-
-
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
-
-
-/**
- * Test {@code BasicAttribute}.
- */
-@Test(groups = { "precommit", "types", "sdk" }, sequential = true)
-public final class SortedEntryTest extends OpenDSTestCase
-{
-  @Test
-  public void SmokeTest() throws Exception
-  {
-    Entry entry1 = new SortedEntry(
-        "dn: cn=Joe Bloggs,dc=example,dc=com",
-        "objectClass: top",
-        "objectClass: person",
-        "cn: Joe Bloggs",
-        "sn: Bloggs",
-        "givenName: Joe",
-        "description: A description");
-
-    Entry entry2 = new SortedEntry(
-        "dn: cn=Joe Bloggs,dc=example,dc=com",
-        "changetype: add",
-        "objectClass: top",
-        "objectClass: person",
-        "cn: Joe Bloggs",
-        "sn: Bloggs",
-        "givenName: Joe",
-        "description: A description");
-
-    Assert.assertEquals(entry1, entry2);
-
-    for (Entry e : new Entry[] { entry1, entry2 })
-    {
-      Assert.assertEquals(e.getName(), DN
-          .valueOf("cn=Joe Bloggs,dc=example,dc=com"));
-      Assert.assertEquals(e.getAttributeCount(), 5);
-
-      Assert.assertEquals(e.getAttribute("objectClass").size(), 2);
-      Assert.assertTrue(e.containsObjectClass("top"));
-      Assert.assertTrue(e.containsObjectClass("person"));
-      Assert.assertFalse(e.containsObjectClass("foo"));
-
-      Assert.assertTrue(e.containsAttribute("objectClass"));
-      Assert.assertTrue(e.containsAttribute("cn"));
-      Assert.assertTrue(e.containsAttribute("sn"));
-      Assert.assertTrue(e.containsAttribute("givenName"));
-      Assert.assertTrue(e.containsAttribute("description"));
-
-      Assert.assertEquals(e.getAttribute("cn").firstValueAsString(), "Joe Bloggs");
-      Assert.assertEquals(e.getAttribute("sn").firstValueAsString(), "Bloggs");
-    }
-  }
-}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/SuiteRunner.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/SuiteRunner.java
index e8bbb7b..1e9fd98 100755
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/SuiteRunner.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/SuiteRunner.java
@@ -33,18 +33,18 @@
 
 
 /**
- * This class wraps TestNG so that we can force the process to exit if
- * there is an uncaught exception (e.g. OutOfMemoryError).
+ * This class wraps TestNG so that we can force the process to exit if there is
+ * an uncaught exception (e.g. OutOfMemoryError).
  */
 public class SuiteRunner
 {
-  public static void main(String[] args)
+  public static void main(final String[] args)
   {
     try
     {
       TestNG.main(args);
     }
-    catch (Throwable e)
+    catch (final Throwable e)
     {
       System.err.println("TestNG.main threw an expected exception:");
       e.printStackTrace(System.err);
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/SynchronousConnectionTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/SynchronousConnectionTestCase.java
new file mode 100644
index 0000000..aa38494
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/SynchronousConnectionTestCase.java
@@ -0,0 +1,164 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+
+import org.opends.sdk.requests.Requests;
+import org.opends.sdk.responses.BindResult;
+import org.opends.sdk.responses.CompareResult;
+import org.opends.sdk.responses.Result;
+import org.opends.sdk.responses.SearchResultEntry;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * This class tests the Synchronous Connection API.
+ */
+public class SynchronousConnectionTestCase extends TypesTestCase
+{
+  private AsynchronousConnection asyncCon;
+
+
+
+  /**
+   * Ensures that the LDAP Server is running.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @BeforeClass()
+  public void startServer() throws Exception
+  {
+    TestCaseUtils.startServer();
+    final ConnectionFactory factory = Connections.newInternalConnectionFactory(
+        LDAPServer.getInstance(), null);
+    asyncCon = factory.getAsynchronousConnection(null).get();
+  }
+
+
+
+  /**
+   * Ensures that the LDAP server is stopped.
+   */
+  @AfterClass()
+  public void stopServer()
+  {
+    asyncCon.close();
+    // Don't stop the server as some futures might get stuck.
+    // TestCaseUtils.stopServer();
+  }
+
+
+
+  /**
+   * Tests the ADD request.
+   *
+   * @throws Exception
+   */
+  @Test()
+  public void testAddRequest() throws Exception
+  {
+    final SynchronousConnection con = new SynchronousConnection(asyncCon);
+    final Result result = con.add(Requests.newAddRequest(DN.valueOf(""
+        + "uid=syncconnectiontestcase,ou=people,o=test")));
+    assertTrue(result.isSuccess());
+  }
+
+
+
+  /**
+   * Tests the BIND request.
+   *
+   * @throws Exception
+   */
+  @Test()
+  public void testBindRequest() throws Exception
+  {
+    final SynchronousConnection con = new SynchronousConnection(asyncCon);
+    final BindResult result = con.bind(Requests.newSimpleBindRequest());
+    assertTrue(result.isSuccess());
+  }
+
+
+
+  /**
+   * Tests the COMPARE request.
+   *
+   * @throws Exception
+   */
+  @Test()
+  public void testCompareRequest() throws Exception
+  {
+    final SynchronousConnection con = new SynchronousConnection(asyncCon);
+    final CompareResult result = con.compare("uid=user.0,ou=people,o=test",
+        "uid", "user.0");
+    assertTrue(result.matched());
+  }
+
+
+
+  /**
+   * Tests the ctor.
+   *
+   * @throws Exception
+   */
+  @Test()
+  public void testCtor() throws Exception
+  {
+    final SynchronousConnection con = new SynchronousConnection(asyncCon);
+    assertFalse(con.isClosed());
+  }
+
+
+
+  /**
+   * Tests the SEARCH request.
+   *
+   * @throws Exception
+   */
+  @Test()
+  public void testSearchRequest() throws Exception
+  {
+    final SynchronousConnection con = new SynchronousConnection(asyncCon);
+    final List<SearchResultEntry> entries = con.search(
+        "uid=user.0,ou=people,o=test", SearchScope.BASE_OBJECT,
+        "objectclass=*", "cn");
+    assertEquals(entries.size(), 1);
+  }
+  // TODO: add more tests.
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/TestCaseUtils.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/TestCaseUtils.java
new file mode 100644
index 0000000..f419fc3
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/TestCaseUtils.java
@@ -0,0 +1,141 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk;
+
+
+
+import java.io.File;
+import java.io.FileWriter;
+
+
+
+/**
+ * This class defines some utility functions which can be used by test cases.
+ */
+public final class TestCaseUtils
+{
+  /**
+   * The name of the system property that specifies the ldap port. Set this
+   * property when running the server if you want to use a given port number,
+   * otherwise a port is chosen randomly at test startup time.
+   */
+  public static final String PROPERTY_LDAP_PORT = "org.opends.server.LdapPort";
+
+  /**
+   * Port number that's used by the server. Need to be used by the testcases to
+   * create connections.
+   */
+  public static int port = 11389;
+
+  static
+  {
+    final String ldapPort = System.getProperty(PROPERTY_LDAP_PORT);
+    if (ldapPort != null)
+    {
+      port = Integer.valueOf(ldapPort);
+    }
+  }
+
+
+
+  /**
+   * Creates a temporary text file with the specified contents. It will be
+   * marked for automatic deletion when the JVM exits.
+   *
+   * @return The absolute path to the file that was created.
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  public static String createTempFile(final String... lines) throws Exception
+  {
+    final File f = File.createTempFile("LDIFBasedTestCase", ".txt");
+    f.deleteOnExit();
+
+    final FileWriter w = new FileWriter(f);
+    for (final String s : lines)
+    {
+      w.write(s + System.getProperty("line.separator"));
+    }
+
+    w.close();
+
+    return f.getAbsolutePath();
+  }
+
+
+
+  /**
+   * Returns an internal client connection to the running ldap server.
+   *
+   * @return The internal client connection.
+   * @throws Exception
+   *           When an error occurs.
+   */
+  public static Connection getInternalConnection() throws Exception
+  {
+    startServer();
+    final ConnectionFactory factory = Connections.newInternalConnectionFactory(
+        LDAPServer.getInstance(), null);
+    return factory.getConnection();
+  }
+
+
+
+  /**
+   * Returns the port which the test server listens on.
+   *
+   * @return The LDAP port.
+   */
+  public static int getLdapPort()
+  {
+    return port;
+  }
+
+
+
+  /**
+   * Starts the test ldap server.
+   *
+   * @throws Exception
+   */
+  public static void startServer() throws Exception
+  {
+    // TODO:Try a couple of random ports before throwing exception.
+    LDAPServer.getInstance().start(port);
+  }
+
+
+
+  /**
+   * Stops the test ldap server.
+   */
+  public static void stopServer()
+  {
+    LDAPServer.getInstance().stop();
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/TestListener.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/TestListener.java
index e2294bf..a95a92b 100755
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/TestListener.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/TestListener.java
@@ -28,35 +28,29 @@
 
 
 
-import org.testng.TestListenerAdapter;
-import org.testng.IReporter;
-import org.testng.ISuite;
-import org.testng.ITestResult;
-import org.testng.IClass;
-import org.testng.ITestNGMethod;
-import org.testng.ITestContext;
-import org.testng.annotations.Test;
-import org.testng.annotations.DataProvider;
-import org.testng.xml.XmlSuite;
 import static com.sun.opends.sdk.util.StaticUtils.EOL;
 
-import java.util.*;
-import java.io.PrintStream;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
 import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.*;
+
+import org.testng.*;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+import org.testng.xml.XmlSuite;
 
 
 
 /**
- * This class is our replacement for the test results that TestNG
- * generates. It prints out test to the console as they happen.
+ * This class is our replacement for the test results that TestNG generates. It
+ * prints out test to the console as they happen.
  */
-public class TestListener extends TestListenerAdapter implements
-    IReporter
+public class TestListener extends TestListenerAdapter implements IReporter
 {
 
   /**
@@ -73,35 +67,21 @@
     private long _totalDurationMs = 0;
 
     // Indexed by SUCCESS, FAILURE, SKIP, SUCCESS_PERCENTAGE_FAILURE
-    private int[] _resultCounts = new int[STATUSES.length];
+    private final int[] _resultCounts = new int[STATUSES.length];
 
 
 
-    public TestClassResults(IClass cls)
+    public TestClassResults(final IClass cls)
     {
       _cls = cls;
     }
 
 
 
-    private TestMethodResults getResultsForMethod(ITestNGMethod method)
-    {
-      TestMethodResults results = _methods.get(method);
-      if (results == null)
-      {
-        results = new TestMethodResults(method);
-        _methods.put(method, results);
-      }
-      return results;
-    }
-
-
-
-    synchronized void addTestResult(ITestResult result)
+    synchronized void addTestResult(final ITestResult result)
     {
       _totalInvocations++;
-      _totalDurationMs += result.getEndMillis()
-          - result.getStartMillis();
+      _totalDurationMs += result.getEndMillis() - result.getStartMillis();
 
       getResultsForMethod(result.getMethod()).addTestResult(result);
       int status = result.getStatus();
@@ -121,7 +101,7 @@
 
 
 
-    synchronized void getSummaryTimingInfo(StringBuilder timingOutput)
+    synchronized void getSummaryTimingInfo(final StringBuilder timingOutput)
     {
       timingOutput.append(_cls.getRealClass().getName() + "    ");
       timingOutput.append(getTotalDurationMs() + " ms" + " ("
@@ -130,11 +110,11 @@
 
 
 
-    synchronized void getTimingInfo(StringBuilder timingOutput)
+    synchronized void getTimingInfo(final StringBuilder timingOutput)
     {
       getSummaryTimingInfo(timingOutput);
       timingOutput.append(EOL);
-      for (TestMethodResults results : getAllMethodResults())
+      for (final TestMethodResults results : getAllMethodResults())
       {
         results.getTimingInfo(timingOutput, false);
       }
@@ -155,6 +135,19 @@
     {
       return _totalInvocations;
     }
+
+
+
+    private TestMethodResults getResultsForMethod(final ITestNGMethod method)
+    {
+      TestMethodResults results = _methods.get(method);
+      if (results == null)
+      {
+        results = new TestMethodResults(method);
+        _methods.put(method, results);
+      }
+      return results;
+    }
   }
 
 
@@ -171,22 +164,21 @@
     long _totalDurationMs = 0;
 
     // Indexed by SUCCESS, FAILURE, SKIP, SUCCESS_PERCENTAGE_FAILURE
-    private int[] _resultCounts = new int[STATUSES.length];
+    private final int[] _resultCounts = new int[STATUSES.length];
 
 
 
-    public TestMethodResults(ITestNGMethod method)
+    public TestMethodResults(final ITestNGMethod method)
     {
       _method = method;
     }
 
 
 
-    synchronized void addTestResult(ITestResult result)
+    synchronized void addTestResult(final ITestResult result)
     {
       _totalInvocations++;
-      _totalDurationMs += result.getEndMillis()
-          - result.getStartMillis();
+      _totalDurationMs += result.getEndMillis() - result.getStartMillis();
 
       int status = result.getStatus();
       if (status < 0 || status >= _resultCounts.length)
@@ -198,18 +190,17 @@
 
 
 
-    synchronized void getTimingInfo(StringBuilder timingOutput,
-        boolean includeClassName)
+    synchronized void getTimingInfo(final StringBuilder timingOutput,
+        final boolean includeClassName)
     {
       timingOutput.append("    ");
       if (includeClassName)
       {
-        timingOutput.append(_method.getRealClass().getName()).append(
-            "#");
+        timingOutput.append(_method.getRealClass().getName()).append("#");
       }
       timingOutput.append(_method.getMethodName() + "  ");
-      timingOutput.append(_totalDurationMs + " ms" + " ("
-          + _totalInvocations + ")");
+      timingOutput.append(_totalDurationMs + " ms" + " (" + _totalInvocations
+          + ")");
       if (_resultCounts[ITestResult.FAILURE] > 0)
       {
         timingOutput.append(" " + _resultCounts[ITestResult.FAILURE]
@@ -291,7 +282,7 @@
       System.err.println("**** Pausing test execution until file "
           + tempFile.getCanonicalPath() + " is removed.");
     }
-    catch (Exception e)
+    catch (final Exception e)
     {
       System.err.println("**** ERROR:  Could not create a watchdog "
           + "file.  Pausing test execution indefinitely.");
@@ -305,7 +296,7 @@
       {
         Thread.sleep(100);
       }
-      catch (Exception e)
+      catch (final Exception e)
       {
       }
     }
@@ -323,27 +314,27 @@
    */
   public static String threadStacksToString()
   {
-    Map<Thread, StackTraceElement[]> threadStacks = Thread
+    final Map<Thread, StackTraceElement[]> threadStacks = Thread
         .getAllStackTraces();
 
     // Re-arrange all of the elements by thread ID so that there is some
     // logical
     // order.
-    TreeMap<Long, Map.Entry<Thread, StackTraceElement[]>> orderedStacks = new TreeMap<Long, Map.Entry<Thread, StackTraceElement[]>>();
-    for (Map.Entry<Thread, StackTraceElement[]> e : threadStacks
+    final TreeMap<Long, Map.Entry<Thread, StackTraceElement[]>> orderedStacks = new TreeMap<Long, Map.Entry<Thread, StackTraceElement[]>>();
+    for (final Map.Entry<Thread, StackTraceElement[]> e : threadStacks
         .entrySet())
     {
       orderedStacks.put(e.getKey().getId(), e);
     }
 
     final StringBuilder buffer = new StringBuilder();
-    for (Map.Entry<Thread, StackTraceElement[]> e : orderedStacks
+    for (final Map.Entry<Thread, StackTraceElement[]> e : orderedStacks
         .values())
     {
-      Thread t = e.getKey();
-      StackTraceElement[] stackElements = e.getValue();
+      final Thread t = e.getKey();
+      final StackTraceElement[] stackElements = e.getValue();
 
-      long id = t.getId();
+      final long id = t.getId();
 
       buffer.append("id=");
       buffer.append(id);
@@ -354,21 +345,21 @@
 
       if (stackElements != null)
       {
-        for (int j = 0; j < stackElements.length; j++)
+        for (final StackTraceElement stackElement : stackElements)
         {
-          buffer.append("   ").append(stackElements[j].getClassName());
+          buffer.append("   ").append(stackElement.getClassName());
           buffer.append(".");
-          buffer.append(stackElements[j].getMethodName());
+          buffer.append(stackElement.getMethodName());
           buffer.append("(");
-          buffer.append(stackElements[j].getFileName());
+          buffer.append(stackElement.getFileName());
           buffer.append(":");
-          if (stackElements[j].isNativeMethod())
+          if (stackElement.isNativeMethod())
           {
             buffer.append("native");
           }
           else
           {
-            buffer.append(stackElements[j].getLineNumber());
+            buffer.append(stackElement.getLineNumber());
           }
           buffer.append(")").append(EOL);
         }
@@ -381,10 +372,10 @@
 
 
 
-  private static String center(String header)
+  private static String center(final String header)
   {
-    StringBuilder buffer = new StringBuilder();
-    int indent = (PAGE_WIDTH - header.length()) / 2;
+    final StringBuilder buffer = new StringBuilder();
+    final int indent = (PAGE_WIDTH - header.length()) / 2;
     for (int i = 0; i < indent; i++)
     {
       buffer.append(" ");
@@ -395,7 +386,7 @@
 
 
 
-  private Set<Class<?>> _checkedForTypeAndAnnotations = new HashSet<Class<?>>();
+  private final Set<Class<?>> _checkedForTypeAndAnnotations = new HashSet<Class<?>>();
 
   private final LinkedHashSet<Class<?>> _classesWithTestsRunInterleaved = new LinkedHashSet<Class<?>>();
 
@@ -403,7 +394,7 @@
 
   private final IdentityHashMap<Object, Object> _previousTestObjects = new IdentityHashMap<Object, Object>();
 
-  private Set<Method> _checkedForAnnotation = new HashSet<Method>();
+  private final Set<Method> _checkedForAnnotation = new HashSet<Method>();
 
   private boolean statusHeaderPrinted = false;
 
@@ -433,10 +424,10 @@
 
 
 
-  public void generateReport(List<XmlSuite> xmlSuites,
-      List<ISuite> suites, String outputDirectory)
+  public void generateReport(final List<XmlSuite> xmlSuites,
+      final List<ISuite> suites, final String outputDirectory)
   {
-    File reportFile = new File(outputDirectory, REPORT_FILE_NAME);
+    final File reportFile = new File(outputDirectory, REPORT_FILE_NAME);
 
     writeReportToFile(reportFile);
     writeReportToScreen(reportFile);
@@ -445,30 +436,29 @@
 
 
 
-  public void onConfigurationFailure(ITestResult tr)
+  public void onConfigurationFailure(final ITestResult tr)
   {
     super.onConfigurationFailure(tr);
 
-    IClass cls = tr.getTestClass();
-    ITestNGMethod method = tr.getMethod();
+    final IClass cls = tr.getTestClass();
+    final ITestNGMethod method = tr.getMethod();
 
-    String fqMethod = cls.getName() + "#" + method.getMethodName();
+    final String fqMethod = cls.getName() + "#" + method.getMethodName();
 
-    StringBuilder failureInfo = new StringBuilder();
+    final StringBuilder failureInfo = new StringBuilder();
     failureInfo.append("Failed Test:  ").append(fqMethod).append(EOL);
     // Object[] parameters = tr.getParameters();
 
-    Throwable cause = tr.getThrowable();
+    final Throwable cause = tr.getThrowable();
     if (cause != null)
     {
-      failureInfo.append("Failure Cause:  ").append(
-          getTestngLessStack(cause));
+      failureInfo.append("Failure Cause:  ").append(getTestngLessStack(cause));
     }
 
     failureInfo.append(EOL + EOL);
     System.err.print(EOL + EOL + EOL
-        + "         C O N F I G U R A T I O N   F A I L U R E ! ! !"
-        + EOL + EOL);
+        + "         C O N F I G U R A T I O N   F A I L U R E ! ! !" + EOL
+        + EOL);
     System.err.print(failureInfo);
     System.err.print(DIVIDER_LINE + EOL + EOL);
 
@@ -477,18 +467,17 @@
 
 
 
-  public void onStart(ITestContext testContext)
+  public void onStart(final ITestContext testContext)
   {
     super.onStart(testContext);
 
     // Delete the previous report if it's there.
-    new File(testContext.getOutputDirectory(), REPORT_FILE_NAME)
-        .delete();
+    new File(testContext.getOutputDirectory(), REPORT_FILE_NAME).delete();
   }
 
 
 
-  public void onTestFailedButWithinSuccessPercentage(ITestResult tr)
+  public void onTestFailedButWithinSuccessPercentage(final ITestResult tr)
   {
     super.onTestFailedButWithinSuccessPercentage(tr);
     onTestFinished(tr);
@@ -496,29 +485,28 @@
 
 
 
-  public void onTestFailure(ITestResult tr)
+  public void onTestFailure(final ITestResult tr)
   {
     super.onTestFailure(tr);
 
-    IClass cls = tr.getTestClass();
-    ITestNGMethod method = tr.getMethod();
+    final IClass cls = tr.getTestClass();
+    final ITestNGMethod method = tr.getMethod();
 
-    String fqMethod = cls.getName() + "#" + method.getMethodName();
+    final String fqMethod = cls.getName() + "#" + method.getMethodName();
 
-    StringBuilder failureInfo = new StringBuilder();
+    final StringBuilder failureInfo = new StringBuilder();
     failureInfo.append("Failed Test:  ").append(fqMethod).append(EOL);
-    Object[] parameters = tr.getParameters();
+    final Object[] parameters = tr.getParameters();
 
-    Throwable cause = tr.getThrowable();
+    final Throwable cause = tr.getThrowable();
     if (cause != null)
     {
-      failureInfo.append("Failure Cause:  ").append(
-          getTestngLessStack(cause));
+      failureInfo.append("Failure Cause:  ").append(getTestngLessStack(cause));
     }
 
     for (int i = 0; (parameters != null) && (i < parameters.length); i++)
     {
-      Object parameter = parameters[i];
+      final Object parameter = parameters[i];
       failureInfo.append("parameter[" + i + "]: ").append(parameter)
           .append(EOL);
     }
@@ -531,7 +519,7 @@
 
     _bufferedTestFailures.append(failureInfo);
 
-    String pauseStr = System
+    final String pauseStr = System
         .getProperty("org.opends.test.pauseOnFailure");
     if ((pauseStr != null) && pauseStr.equalsIgnoreCase("true"))
     {
@@ -543,7 +531,7 @@
 
 
 
-  public void onTestSkipped(ITestResult tr)
+  public void onTestSkipped(final ITestResult tr)
   {
     super.onTestSkipped(tr);
     onTestFinished(tr);
@@ -551,7 +539,7 @@
 
 
 
-  public void onTestStart(ITestResult tr)
+  public void onTestStart(final ITestResult tr)
   {
     super.onTestStart(tr);
 
@@ -562,7 +550,7 @@
 
 
 
-  public void onTestSuccess(ITestResult tr)
+  public void onTestSuccess(final ITestResult tr)
   {
     super.onTestSuccess(tr);
     onTestFinished(tr);
@@ -570,20 +558,38 @@
 
 
 
-  private void addTestResult(ITestResult result)
+  synchronized StringBuilder getTimingInfo()
+  {
+    final StringBuilder timingOutput = new StringBuilder();
+    timingOutput.append(center("TESTS RUN BY CLASS")).append(EOL);
+    timingOutput.append(center("[method-name total-time (total-invocations)]"))
+        .append(EOL + EOL);
+    for (final TestClassResults results : _classResults.values())
+    {
+      results.getTimingInfo(timingOutput);
+    }
+
+    timingOutput.append(EOL + DIVIDER_LINE + DIVIDER_LINE + EOL);
+
+    getSlowestTestsOutput(timingOutput);
+    return timingOutput;
+  }
+
+
+
+  private void addTestResult(final ITestResult result)
   {
     getResultsForClass(result.getTestClass()).addTestResult(result);
 
     // Read the comments in DirectoryServerTestCase to understand what's
     // going on here.
-    Object[] testInstances = result.getMethod().getInstances();
-    for (int i = 0; i < testInstances.length; i++)
+    final Object[] testInstances = result.getMethod().getInstances();
+    for (final Object testInstance : testInstances)
     {
-      Object testInstance = testInstances[i];
       if (testInstance instanceof OpenDSTestCase)
       {
-        OpenDSTestCase openDSTestCase = (OpenDSTestCase) testInstance;
-        Object[] parameters = result.getParameters();
+        final OpenDSTestCase openDSTestCase = (OpenDSTestCase) testInstance;
+        final Object[] parameters = result.getParameters();
         if (result.getStatus() == ITestResult.SUCCESS)
         {
           openDSTestCase.addParamsFromSuccessfulTests(parameters);
@@ -612,9 +618,9 @@
 
 
 
-  private void checkForInterleavedBetweenClasses(ITestResult tr)
+  private void checkForInterleavedBetweenClasses(final ITestResult tr)
   {
-    Object[] testInstances = tr.getMethod().getInstances();
+    final Object[] testInstances = tr.getMethod().getInstances();
     // This will almost always have a single element. If it doesn't,
     // just
     // skip it.
@@ -623,7 +629,7 @@
       return;
     }
 
-    Object testInstance = testInstances[0];
+    final Object testInstance = testInstances[0];
 
     // We're running another test on the same test object. Everything is
     // fine.
@@ -653,14 +659,14 @@
 
 
 
-  private String[] convertToStringParameters(Object[] parameters)
+  private String[] convertToStringParameters(final Object[] parameters)
   {
     if (parameters == null)
     {
       return null;
     }
 
-    String[] strParams = new String[parameters.length];
+    final String[] strParams = new String[parameters.length];
     for (int i = 0; i < parameters.length; i++)
     {
       strParams[i] = String.valueOf(parameters[i]).intern();
@@ -674,7 +680,7 @@
   private int countTestMethods()
   {
     int count = 0;
-    for (TestClassResults results : _classResults.values())
+    for (final TestClassResults results : _classResults.values())
     {
       count += results._methods.size();
     }
@@ -683,10 +689,10 @@
 
 
 
-  private int countTestsWithStatus(int status)
+  private int countTestsWithStatus(final int status)
   {
     int count = 0;
-    for (TestClassResults results : _classResults.values())
+    for (final TestClassResults results : _classResults.values())
     {
       count += results._resultCounts[status];
     }
@@ -698,7 +704,7 @@
   private int countTotalInvocations()
   {
     int count = 0;
-    for (TestClassResults results : _classResults.values())
+    for (final TestClassResults results : _classResults.values())
     {
       count += results._totalInvocations;
     }
@@ -707,23 +713,23 @@
 
 
 
-  private void enforceMethodHasAnnotation(ITestResult tr)
+  private void enforceMethodHasAnnotation(final ITestResult tr)
   {
     // Only warn once per method.
-    Method testMethod = tr.getMethod().getMethod();
+    final Method testMethod = tr.getMethod().getMethod();
     if (_checkedForAnnotation.contains(testMethod))
     {
       return;
     }
     _checkedForAnnotation.add(testMethod);
 
-    Annotation testAnnotation = testMethod.getAnnotation(Test.class);
-    Annotation dataProviderAnnotation = testMethod
+    final Annotation testAnnotation = testMethod.getAnnotation(Test.class);
+    final Annotation dataProviderAnnotation = testMethod
         .getAnnotation(DataProvider.class);
 
     if ((testAnnotation == null) && (dataProviderAnnotation == null))
     {
-      String errorMessage = "The test method "
+      final String errorMessage = "The test method "
           + testMethod
           + " does not have a @Test annotation.  "
           + "However, TestNG assumes it is a test method because it's a public method "
@@ -735,7 +741,7 @@
 
 
 
-  private void enforceTestClassTypeAndAnnotations(ITestResult tr)
+  private void enforceTestClassTypeAndAnnotations(final ITestResult tr)
   {
     Class<?> testClass = null;
     testClass = tr.getMethod().getRealClass();
@@ -749,18 +755,18 @@
 
     if (!OpenDSTestCase.class.isAssignableFrom(testClass))
     {
-      String errorMessage = "The test class " + testClass.getName()
+      final String errorMessage = "The test class " + testClass.getName()
           + " must inherit (directly or indirectly) "
           + "from DirectoryServerTestCase.";
       System.err.println("\n\nERROR: " + errorMessage + "\n\n");
       throw new RuntimeException(errorMessage);
     }
 
-    Class<?> classWithTestAnnotation = findClassWithTestAnnotation(testClass);
+    final Class<?> classWithTestAnnotation = findClassWithTestAnnotation(testClass);
 
     if (classWithTestAnnotation == null)
     {
-      String errorMessage = "The test class "
+      final String errorMessage = "The test class "
           + testClass.getName()
           + " does not have a @Test annotation.  "
           + "All test classes must have a @Test annotation, and this annotation must have "
@@ -769,12 +775,12 @@
       throw new RuntimeException(errorMessage);
     }
 
-    Test testAnnotation = classWithTestAnnotation
+    final Test testAnnotation = classWithTestAnnotation
         .getAnnotation(Test.class);
     if (!testAnnotation.sequential())
     {
       // Give an error message that is as specific as possible.
-      String errorMessage = "The @Test annotation for class "
+      final String errorMessage = "The @Test annotation for class "
           + testClass.getName()
           + (classWithTestAnnotation.equals(testClass) ? " "
               : (", which is declared by class "
@@ -809,8 +815,8 @@
 
   synchronized private List<TestMethodResults> getAllMethodResults()
   {
-    List<TestMethodResults> allResults = new ArrayList<TestMethodResults>();
-    for (TestClassResults results : _classResults.values())
+    final List<TestMethodResults> allResults = new ArrayList<TestMethodResults>();
+    for (final TestClassResults results : _classResults.values())
     {
       allResults.addAll(results.getAllMethodResults());
     }
@@ -821,11 +827,11 @@
 
   private List<TestClassResults> getClassesDescendingSortedByDuration()
   {
-    List<TestClassResults> allClasses = new ArrayList<TestClassResults>(
+    final List<TestClassResults> allClasses = new ArrayList<TestClassResults>(
         _classResults.values());
     Collections.sort(allClasses, new Comparator<TestClassResults>()
     {
-      public int compare(TestClassResults o1, TestClassResults o2)
+      public int compare(final TestClassResults o1, final TestClassResults o2)
       {
         if (o1._totalDurationMs > o2._totalDurationMs)
         {
@@ -846,10 +852,10 @@
 
 
 
-  private String getFqMethod(ITestResult result)
+  private String getFqMethod(final ITestResult result)
   {
-    IClass cls = result.getTestClass();
-    ITestNGMethod method = result.getMethod();
+    final IClass cls = result.getTestClass();
+    final ITestNGMethod method = result.getMethod();
 
     return cls.getName() + "#" + method.getMethodName();
   }
@@ -858,10 +864,10 @@
 
   private List<TestMethodResults> getMethodsDescendingSortedByDuration()
   {
-    List<TestMethodResults> allMethods = getAllMethodResults();
+    final List<TestMethodResults> allMethods = getAllMethodResults();
     Collections.sort(allMethods, new Comparator<TestMethodResults>()
     {
-      public int compare(TestMethodResults o1, TestMethodResults o2)
+      public int compare(final TestMethodResults o1, final TestMethodResults o2)
       {
         if (o1._totalDurationMs > o2._totalDurationMs)
         {
@@ -882,7 +888,7 @@
 
 
 
-  private TestClassResults getResultsForClass(IClass cls)
+  private TestClassResults getResultsForClass(final IClass cls)
   {
     TestClassResults results = _classResults.get(cls);
     if (results == null)
@@ -895,17 +901,15 @@
 
 
 
-  private void getSlowestTestsOutput(StringBuilder timingOutput)
+  private void getSlowestTestsOutput(final StringBuilder timingOutput)
   {
-    timingOutput.append(center("CLASS SUMMARY SORTED BY DURATION"))
-        .append(EOL);
-    timingOutput.append(
-        center("[class-name total-time (total-invocations)]")).append(
-        EOL + EOL);
-    List<TestClassResults> sortedClasses = getClassesDescendingSortedByDuration();
+    timingOutput.append(center("CLASS SUMMARY SORTED BY DURATION")).append(EOL);
+    timingOutput.append(center("[class-name total-time (total-invocations)]"))
+        .append(EOL + EOL);
+    final List<TestClassResults> sortedClasses = getClassesDescendingSortedByDuration();
     for (int i = 0; i < sortedClasses.size(); i++)
     {
-      TestClassResults results = sortedClasses.get(i);
+      final TestClassResults results = sortedClasses.get(i);
       timingOutput.append("  ");
       results.getSummaryTimingInfo(timingOutput);
       timingOutput.append(EOL);
@@ -913,29 +917,27 @@
 
     timingOutput.append(EOL + DIVIDER_LINE + EOL + EOL);
     timingOutput.append(center("SLOWEST METHODS")).append(EOL);
-    timingOutput.append(
-        center("[method-name total-time (total-invocations)]")).append(
-        EOL + EOL);
-    List<TestMethodResults> sortedMethods = getMethodsDescendingSortedByDuration();
-    for (int i = 0; i < Math.min(sortedMethods.size(),
-        NUM_SLOWEST_METHODS); i++)
+    timingOutput.append(center("[method-name total-time (total-invocations)]"))
+        .append(EOL + EOL);
+    final List<TestMethodResults> sortedMethods = getMethodsDescendingSortedByDuration();
+    for (int i = 0; i < Math.min(sortedMethods.size(), NUM_SLOWEST_METHODS); i++)
     {
-      TestMethodResults results = sortedMethods.get(i);
+      final TestMethodResults results = sortedMethods.get(i);
       results.getTimingInfo(timingOutput, true);
     }
   }
 
 
 
-  private String getTestngLessStack(Throwable t)
+  private String getTestngLessStack(final Throwable t)
   {
-    StackTraceElement[] elements = t.getStackTrace();
+    final StackTraceElement[] elements = t.getStackTrace();
 
     int lowestOpenDSFrame;
     for (lowestOpenDSFrame = elements.length - 1; lowestOpenDSFrame >= 0; lowestOpenDSFrame--)
     {
-      StackTraceElement element = elements[lowestOpenDSFrame];
-      String clsName = element.getClassName();
+      final StackTraceElement element = elements[lowestOpenDSFrame];
+      final String clsName = element.getClassName();
       if (clsName.startsWith("org.opends.")
           && !clsName.equals("org.opends.server.SuiteRunner"))
       {
@@ -943,22 +945,19 @@
       }
     }
 
-    StringBuilder buffer = new StringBuilder();
+    final StringBuilder buffer = new StringBuilder();
     buffer.append(t).append(EOL);
     for (int i = 0; i <= lowestOpenDSFrame; i++)
     {
       buffer.append("    ").append(elements[i]).append(EOL);
     }
 
-    Throwable cause = t.getCause();
-    if (t != null)
+    final Throwable cause = t.getCause();
+    if (cause instanceof InvocationTargetException)
     {
-      if (cause instanceof InvocationTargetException)
-      {
-        InvocationTargetException invocation = ((InvocationTargetException) cause);
-        buffer.append("Invocation Target Exception: "
-            + getTestngLessStack(invocation));
-      }
+      final InvocationTargetException invocation = ((InvocationTargetException) cause);
+      buffer.append("Invocation Target Exception: "
+          + getTestngLessStack(invocation));
     }
 
     return buffer.toString();
@@ -975,7 +974,7 @@
     }
 
     prop = prop.toLowerCase();
-    List<String> progressValues = Arrays.asList(prop
+    final List<String> progressValues = Arrays.asList(prop
         .split("\\s*\\W+\\s*"));
 
     if ((prop.length() == 0) || progressValues.isEmpty())
@@ -1006,11 +1005,9 @@
     {
       doProgressNone = false;
       doProgressTime = progressValues.contains(TEST_PROGRESS_TIME);
-      doProgressTestCount = progressValues
-          .contains(TEST_PROGRESS_TEST_COUNT);
+      doProgressTestCount = progressValues.contains(TEST_PROGRESS_TEST_COUNT);
       doProgressMemory = progressValues.contains(TEST_PROGRESS_MEMORY);
-      doProgressMemoryGcs = progressValues
-          .contains(TEST_PROGRESS_MEMORY_GCS);
+      doProgressMemoryGcs = progressValues.contains(TEST_PROGRESS_MEMORY_GCS);
       doProgressThreadCount = progressValues
           .contains(TEST_PROGRESS_THREAD_COUNT);
       doProgressThreadChanges = progressValues
@@ -1030,23 +1027,23 @@
 
   private List<String> listAllThreadNames()
   {
-    Thread currentThread = Thread.currentThread();
+    final Thread currentThread = Thread.currentThread();
     ThreadGroup topGroup = currentThread.getThreadGroup();
     while (topGroup.getParent() != null)
     {
       topGroup = topGroup.getParent();
     }
 
-    Thread threads[] = new Thread[topGroup.activeCount() * 2];
-    int numThreads = topGroup.enumerate(threads);
+    final Thread threads[] = new Thread[topGroup.activeCount() * 2];
+    final int numThreads = topGroup.enumerate(threads);
 
-    List<String> activeThreads = new ArrayList<String>();
+    final List<String> activeThreads = new ArrayList<String>();
     for (int i = 0; i < numThreads; i++)
     {
-      Thread thread = threads[i];
+      final Thread thread = threads[i];
       if (thread.isAlive())
       {
-        String fullName = thread.getName();
+        final String fullName = thread.getName();
         activeThreads.add(fullName);
       }
     }
@@ -1057,7 +1054,7 @@
 
 
 
-  private void onTestFinished(ITestResult tr)
+  private void onTestFinished(final ITestResult tr)
   {
     // Clear when a test finishes instead before the next one starts
     // so that we get the output generated by any @BeforeClass method
@@ -1067,7 +1064,7 @@
 
 
 
-  private void outputTestProgress(Object finishedTestObject)
+  private void outputTestProgress(final Object finishedTestObject)
   {
     if (doProgressNone)
     {
@@ -1078,9 +1075,9 @@
 
     if (doProgressTime)
     {
-      long curTimeMs = System.currentTimeMillis();
-      long durationSec = (curTimeMs - startTimeMs) / 1000;
-      long durationLastMs = curTimeMs - prevTimeMs;
+      final long curTimeMs = System.currentTimeMillis();
+      final long durationSec = (curTimeMs - startTimeMs) / 1000;
+      final long durationLastMs = curTimeMs - prevTimeMs;
       System.err.printf("{%2d:%02d (%3.0fs)}  ", (durationSec / 60),
           (durationSec % 60), (durationLastMs / 1000.0));
       prevTimeMs = curTimeMs;
@@ -1095,26 +1092,25 @@
 
     if (doProgressMemory)
     {
-      Runtime runtime = Runtime.getRuntime();
-      long beforeGc = System.currentTimeMillis();
-      int gcs = runGc();
-      long gcDuration = System.currentTimeMillis() - beforeGc;
+      final Runtime runtime = Runtime.getRuntime();
+      final long beforeGc = System.currentTimeMillis();
+      final int gcs = runGc();
+      final long gcDuration = System.currentTimeMillis() - beforeGc;
 
-      long totalMemory = runtime.totalMemory();
-      long freeMemory = runtime.freeMemory();
-      long curMemInUse = totalMemory - freeMemory;
-      long memDelta = curMemInUse - prevMemInUse;
-      double perMegaByte = 1.0 / (1024.0 * 1024.0);
+      final long totalMemory = runtime.totalMemory();
+      final long freeMemory = runtime.freeMemory();
+      final long curMemInUse = totalMemory - freeMemory;
+      final long memDelta = curMemInUse - prevMemInUse;
+      final double perMegaByte = 1.0 / (1024.0 * 1024.0);
 
       maxMemInUse = Math.max(maxMemInUse, curMemInUse);
 
-      System.err.printf("{%5.1fMB  %+5.1fMB}  ", curMemInUse
-          * perMegaByte, memDelta * perMegaByte);
+      System.err.printf("{%5.1fMB  %+5.1fMB}  ", curMemInUse * perMegaByte,
+          memDelta * perMegaByte);
 
       if (doProgressMemoryGcs)
       {
-        System.err.printf("{%2d gcs  %4.1fs}  ", gcs,
-            gcDuration / 1000.0);
+        System.err.printf("{%2d gcs  %4.1fs}  ", gcs, gcDuration / 1000.0);
       }
       prevMemInUse = curMemInUse;
     }
@@ -1130,30 +1126,28 @@
     }
     else
     {
-      String abbrClass = packageLessClass(finishedTestObject);
+      final String abbrClass = packageLessClass(finishedTestObject);
       System.err.printf(": %s ", abbrClass).flush();
       System.err.println();
     }
 
     if (doProgressThreadChanges)
     {
-      List<String> currentThreads = listAllThreadNames();
-      List<String> newThreads = removeExactly(prevThreads,
-          currentThreads);
-      List<String> oldThreads = removeExactly(currentThreads,
-          prevThreads);
+      final List<String> currentThreads = listAllThreadNames();
+      final List<String> newThreads = removeExactly(prevThreads, currentThreads);
+      final List<String> oldThreads = removeExactly(currentThreads, prevThreads);
 
       if (!newThreads.isEmpty())
       {
         System.err.println("  Thread changes:");
         for (int i = 0; i < oldThreads.size(); i++)
         {
-          String threadName = oldThreads.get(i);
+          final String threadName = oldThreads.get(i);
           System.err.println("    + " + threadName);
         }
         for (int i = 0; i < newThreads.size(); i++)
         {
-          String threadName = newThreads.get(i);
+          final String threadName = newThreads.get(i);
           System.err.println("    - " + threadName);
         }
       }
@@ -1164,7 +1158,7 @@
 
 
 
-  private String packageLessClass(Object obj)
+  private String packageLessClass(final Object obj)
   {
     return obj.getClass().getName().replaceAll(".*\\.", "");
   }
@@ -1230,18 +1224,18 @@
 
 
   /**
-   * Removes toRemove from base. If there are duplicate items in base,
-   * then only one is removed for each item in toRemove.
+   * Removes toRemove from base. If there are duplicate items in base, then only
+   * one is removed for each item in toRemove.
    *
    * @return a new List with base with toRemove items removed from it
    */
-  private List<String> removeExactly(List<String> base,
-      List<String> toRemove)
+  private List<String> removeExactly(final List<String> base,
+      final List<String> toRemove)
   {
-    List<String> diff = new ArrayList<String>(base);
+    final List<String> diff = new ArrayList<String>(base);
     for (int i = 0; i < toRemove.size(); i++)
     {
-      String item = toRemove.get(i);
+      final String item = toRemove.get(i);
       diff.remove(item);
     }
     return diff;
@@ -1251,11 +1245,11 @@
 
   private int runGc()
   {
-    Runtime runtime = Runtime.getRuntime();
+    final Runtime runtime = Runtime.getRuntime();
     int numGcs;
     long curMem = usedMemory();
     long prevMem = Long.MAX_VALUE;
-    StringBuilder gcConvergence = new StringBuilder();
+    final StringBuilder gcConvergence = new StringBuilder();
     for (numGcs = 0; (prevMem > curMem) && numGcs < 100; numGcs++)
     {
       runtime.runFinalization();
@@ -1266,8 +1260,8 @@
       prevMem = curMem;
       curMem = usedMemory();
 
-      gcConvergence.append("[" + numGcs + "]: " + (prevMem - curMem))
-          .append("  ");
+      gcConvergence.append("[" + numGcs + "]: " + (prevMem - curMem)).append(
+          "  ");
     }
     return numGcs;
   }
@@ -1276,13 +1270,13 @@
 
   private long usedMemory()
   {
-    Runtime runtime = Runtime.getRuntime();
+    final Runtime runtime = Runtime.getRuntime();
     return runtime.totalMemory() - runtime.freeMemory();
   }
 
 
 
-  private void writeAntTestsFailedMarker(String outputDirectory)
+  private void writeAntTestsFailedMarker(final String outputDirectory)
   {
     // Signal 'ant' that all of the tests passed by removing this
     // special file.
@@ -1295,14 +1289,14 @@
 
 
 
-  private void writeReportToFile(File reportFile)
+  private void writeReportToFile(final File reportFile)
   {
     PrintStream reportStream = null;
     try
     {
       reportStream = new PrintStream(new FileOutputStream(reportFile));
     }
-    catch (FileNotFoundException e)
+    catch (final FileNotFoundException e)
     {
       System.err
           .println("Could not open "
@@ -1326,10 +1320,8 @@
     reportStream.println(EOL + DIVIDER_LINE + DIVIDER_LINE + EOL + EOL);
     reportStream.println(center("TEST CLASSES RUN INTERLEAVED"));
     reportStream.println(EOL + EOL);
-    for (Iterator<Class<?>> iterator = _classesWithTestsRunInterleaved
-        .iterator(); iterator.hasNext();)
+    for (final Class<?> cls : _classesWithTestsRunInterleaved)
     {
-      Class<?> cls = iterator.next();
       reportStream.println("  " + cls.getName());
     }
 
@@ -1355,17 +1347,17 @@
 
 
 
-  private void writeReportToScreen(File reportFile)
+  private void writeReportToScreen(final File reportFile)
   {
     // HACK: print out status for the last test object
     outputTestProgress(_lastTestObject);
 
-    List<ITestResult> failedTests = getFailedTests();
-    StringBuilder failed = new StringBuilder();
+    final List<ITestResult> failedTests = getFailedTests();
+    final StringBuilder failed = new StringBuilder();
     for (int i = 0; i < failedTests.size(); i++)
     {
-      ITestResult failedTest = failedTests.get(i);
-      String fqMethod = getFqMethod(failedTest);
+      final ITestResult failedTest = failedTests.get(i);
+      final String fqMethod = getFqMethod(failedTest);
       int numFailures = 1;
       // Peek ahead to see if we had multiple failures for the same
       // method
@@ -1416,8 +1408,7 @@
       System.err.printf("Maximum amount of memory in use: %.1f MB",
           (maxMemInUse / (1024.0 * 1024.0))).println();
     }
-    System.err.println("Final number of threads: "
-        + Thread.activeCount());
+    System.err.println("Final number of threads: " + Thread.activeCount());
 
     System.err.println();
 
@@ -1435,24 +1426,4 @@
               + "have been reported already or there has been a regression with TestNG.");
     }
   }
-
-
-
-  synchronized StringBuilder getTimingInfo()
-  {
-    StringBuilder timingOutput = new StringBuilder();
-    timingOutput.append(center("TESTS RUN BY CLASS")).append(EOL);
-    timingOutput.append(
-        center("[method-name total-time (total-invocations)]")).append(
-        EOL + EOL);
-    for (TestClassResults results : _classResults.values())
-    {
-      results.getTimingInfo(timingOutput);
-    }
-
-    timingOutput.append(EOL + DIVIDER_LINE + DIVIDER_LINE + EOL);
-
-    getSlowestTestsOutput(timingOutput);
-    return timingOutput;
-  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/TypesTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/TypesTestCase.java
new file mode 100644
index 0000000..fc5d201
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/TypesTestCase.java
@@ -0,0 +1,156 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk;
+
+
+
+import static org.testng.Assert.assertTrue;
+
+import org.opends.sdk.schema.Schema;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * An abstract class that all types unit tests should extend. A type represents
+ * the classes found directly under the package org.opends.sdk.
+ */
+
+@Test(groups = { "precommit", "types", "sdk" }, sequential = true)
+public class TypesTestCase extends SdkTestCase
+{
+  /**
+   * Data provider for attribute descriptions.
+   *
+   * @return
+   */
+  @DataProvider(name = "dataForAttributeDescriptions")
+  public Object[][] dataForAttributeDescriptions()
+  {
+    // Value, type, options, containsOptions("foo")
+    return new Object[][] { { "cn" }, { "CN" }, { "objectClass" },
+        { "cn;foo" }, { "cn;FOO" }, { "cn;bar" }, { "cn;BAR" },
+        { "cn;foo;bar" }, { "cn;FOO;bar" }, };
+  }
+
+
+
+  /**
+   * Data provider for old and new attributes
+   *
+   * @return
+   */
+  @DataProvider(name = "dataForAttributeRename")
+  public Object[][] dataForAttributeRename()
+  {
+    return new Object[][] { { "cn", "cn", true }, { "CN", "cn", true },
+        { "objectClass", "cn", false }, { "cn;foo", "cn", true } };
+  }
+
+
+
+  /**
+   * Tests the attribute renaming method.
+   *
+   * @throws Exception
+   */
+  @Test(dataProvider = "dataForAttributeRename")
+  public void testAttributeRename(final String attr, final String desc,
+      final boolean valid) throws Exception
+  {
+    final AttributeDescription desc1 = AttributeDescription.valueOf(attr,
+        Schema.getCoreSchema());
+    final AttributeDescription desc2 = AttributeDescription.valueOf(desc,
+        Schema.getCoreSchema());
+    final Attribute attr1 = Types.emptyAttribute(desc1);
+    try
+    {
+      Types.renameAttribute(attr1, desc2);
+    }
+    catch (final Exception e)
+    {
+      if (valid)
+      {
+        // shouldn't have come here.
+        throw e;
+      }
+    }
+  }
+
+
+
+  /**
+   * Tests the empty attribute method.
+   *
+   * @throws Exception
+   */
+  @Test(dataProvider = "dataForAttributeDescriptions")
+  public void testEmptyAttribute(final String attrDesc) throws Exception
+  {
+    final AttributeDescription desc = AttributeDescription.valueOf(attrDesc,
+        Schema.getCoreSchema());
+    final Attribute attr = Types.emptyAttribute(desc);
+    assertTrue(attr.isEmpty());
+  }
+
+
+
+  /**
+   * Tests the unmodifiable attribute method.
+   *
+   * @throws Exception
+   */
+  @Test(dataProvider = "dataForAttributeDescriptions", expectedExceptions = UnsupportedOperationException.class)
+  public void testUnmodifiableAttribute(final String attrDesc) throws Exception
+  {
+    final AttributeDescription desc = AttributeDescription.valueOf(attrDesc,
+        Schema.getCoreSchema());
+    final Attribute attr = Types.emptyAttribute(desc);
+    attr.add("test"); // should go through.
+    // Make it unmodifiable.
+    final Attribute attr1 = Types.unmodifiableAttribute(attr);
+    attr1.add("test");
+  }
+
+
+
+  /**
+   * Tests the unmodifiable entry method.
+   *
+   * @throws Exception
+   */
+  @Test(expectedExceptions = UnsupportedOperationException.class)
+  public void testUnmodifiableEntry() throws Exception
+  {
+    final Entry entry = new LinkedHashMapEntry("cn=test");
+    // add a value.
+    entry.clearAttributes();
+    final Entry entry1 = Types.unmodifiableEntry(entry);
+    entry1.clearAttributes();
+  }
+}
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ByteSequenceReaderTestCase.java
similarity index 65%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ByteSequenceReaderTestCase.java
index 62b3ae3..8444b38 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ByteSequenceReaderTestCase.java
@@ -22,21 +22,27 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package org.opends.sdk.asn1;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.opends.sdk.ByteSequenceReader;
+import org.opends.sdk.ByteString;
 
 
 
 /**
- * Password call-back.
+ * Test class for ASN1ByteSequenceReaderTestCase
  */
-public interface PasswordCallbackHandler
+public class ASN1ByteSequenceReaderTestCase extends ASN1ReaderTestCase
 {
-  public boolean handle(PasswordCallback callback);
+  @Override
+  protected ASN1Reader getReader(final byte[] b, final int maxElementSize)
+  {
+    final ByteSequenceReader reader = ByteString.wrap(b).asReader();
+    return ASN1.getReader(reader, maxElementSize);
+  }
 }
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1InputStreamReaderTestCase.java
similarity index 66%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1InputStreamReaderTestCase.java
index 62b3ae3..36db156 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1InputStreamReaderTestCase.java
@@ -22,21 +22,25 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
-
-package org.opends.sdk.sasl;
+package org.opends.sdk.asn1;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import java.io.ByteArrayInputStream;
 
 
 
 /**
- * Password call-back.
+ * Test class for ASN1InputStreamReader
  */
-public interface PasswordCallbackHandler
+public class ASN1InputStreamReaderTestCase extends ASN1ReaderTestCase
 {
-  public boolean handle(PasswordCallback callback);
+  @Override
+  protected ASN1Reader getReader(final byte[] b, final int maxElementSize)
+  {
+    final ByteArrayInputStream inStream = new ByteArrayInputStream(b);
+    return new ASN1InputStreamReader(inStream, maxElementSize);
+  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1OutputStreamWriterTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1OutputStreamWriterTestCase.java
new file mode 100644
index 0000000..16ab7fe
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1OutputStreamWriterTestCase.java
@@ -0,0 +1,69 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.asn1;
+
+
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+
+
+
+/**
+ * Test class for ASN1OutputStreamWriter
+ */
+public class ASN1OutputStreamWriterTestCase extends ASN1WriterTestCase
+{
+  private final ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+  private final ASN1Writer writer = new ASN1OutputStreamWriter(outStream);
+
+
+
+  @Override
+  protected byte[] getEncodedBytes()
+  {
+    return outStream.toByteArray();
+  }
+
+
+
+  @Override
+  protected ASN1Reader getReader(final byte[] encodedBytes)
+  {
+    final ByteArrayInputStream inStream = new ByteArrayInputStream(encodedBytes);
+    return new ASN1InputStreamReader(inStream, 0);
+  }
+
+
+
+  @Override
+  protected ASN1Writer getWriter()
+  {
+    outStream.reset();
+    return writer;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ReaderTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ReaderTestCase.java
new file mode 100644
index 0000000..0299f79
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ReaderTestCase.java
@@ -0,0 +1,922 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.asn1;
+
+
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.ByteStringBuilder;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.OpenDSTestCase;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * An abstract base class for all ASN1Reader test cases.
+ */
+@Test(groups = { "precommit", "asn1", "sdk" }, sequential = true)
+public abstract class ASN1ReaderTestCase extends OpenDSTestCase
+{
+
+  /**
+   * Retrieves the set of byte array values that may be used for testing.
+   *
+   * @return The set of byte array values that may be used for testing.
+   */
+  @DataProvider(name = "byteValues")
+  public Object[][] getByteValues()
+  {
+    final Object[][] array = new Object[256][1];
+    for (int i = 0; i < 256; i++)
+    {
+      array[i] = new Object[] { new byte[] { (byte) (i & 0xFF) } };
+    }
+
+    return array;
+  }
+
+
+
+  /**
+   * Create byte arrays with encoded ASN.1 elements to test decoding them as
+   * octet strings.
+   *
+   * @return A list of byte arrays with encoded ASN.1 elements that can be
+   *         decoded as octet strings.
+   */
+  @DataProvider(name = "elementArrays")
+  public Object[][] getElementArrays()
+  {
+    return new Object[][] {
+        new Object[] { new byte[] { 0x04, 0x00 } },
+        new Object[] { new byte[] { (byte) 0x50, 0x00 } },
+        new Object[] { new byte[] { 0x04, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F } },
+        new Object[] { new byte[] { 0x01, 0x01, 0x00 } },
+        new Object[] { new byte[] { 0x01, 0x01, (byte) 0xFF } },
+        new Object[] { new byte[] { 0x0A, 0x01, 0x00 } },
+        new Object[] { new byte[] { 0x0A, 0x01, 0x01 } },
+        new Object[] { new byte[] { 0x0A, 0x01, 0x7F } },
+        new Object[] { new byte[] { 0x0A, 0x01, (byte) 0x80 } },
+        new Object[] { new byte[] { 0x0A, 0x01, (byte) 0xFF } },
+        new Object[] { new byte[] { 0x0A, 0x02, 0x01, 0x00 } },
+        new Object[] { new byte[] { 0x02, 0x01, 0x00 } },
+        new Object[] { new byte[] { 0x02, 0x01, 0x01 } },
+        new Object[] { new byte[] { 0x02, 0x01, 0x7F } },
+        new Object[] { new byte[] { 0x02, 0x02, 0x00, (byte) 0x80 } },
+        new Object[] { new byte[] { 0x02, 0x02, 0x00, (byte) 0xFF } },
+        new Object[] { new byte[] { 0x02, 0x02, 0x01, 0x00 } },
+        new Object[] { new byte[] { 0x05, 0x00 } },
+        new Object[] { new byte[] { 0x30, 0x00 } },
+        new Object[] { new byte[] { 0x31, 0x00 } },
+        new Object[] { new byte[] { 0x05, (byte) 0x81, 0x00 } },
+        new Object[] { new byte[] { 0x05, (byte) 0x82, 0x00, 0x00 } },
+        new Object[] { new byte[] { 0x05, (byte) 0x83, 0x00, 0x00, 0x00 } },
+        new Object[] { new byte[] { 0x05, (byte) 0x84, 0x00, 0x00, 0x00, 0x00 } }, };
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsNull</CODE> method that takes a byte array argument
+   * with an arry with a zero length that takes multiple bytes to encode.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test()
+  public void testDecodeExtendedZeroLengthArrayAsNull() throws Exception
+  {
+    final byte[] b = new byte[] { 0x05, (byte) 0x81, 0x00 };
+    getReader(b, 0).readNull();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsBoolean</CODE> method that takes a byte array
+   * argument with an array that has less bytes than indicated by the length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLengthMismatchArrayAsBoolean() throws Exception
+  {
+    final byte[] b = { 0x01, 0x01 };
+    getReader(b, 0).readBoolean();
+  }
+
+
+
+  /**
+   * Tests the <CODE>readEnumerated</CODE> method that takes a byte array with a
+   * length mismatch.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLengthMismatchArrayAsEnumerated() throws Exception
+  {
+    final byte[] b = { 0x02, (byte) 0x81, 0x01 };
+    getReader(b, 0).readEnumerated();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsInteger</CODE> method that takes a byte array with
+   * a length mismatch.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLengthMismatchArrayAsInteger() throws Exception
+  {
+    final byte[] b = { 0x02, (byte) 0x81, 0x01 };
+    getReader(b, 0).readInteger();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
+   * using an array whose actual length doesn't match with the decoded length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLengthMismatchArrayAsOctetString() throws Exception
+  {
+    final byte[] b = { 0x04, 0x02, 0x00 };
+    getReader(b, 0).readOctetString();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsBoolean</CODE> method that takes a byte array
+   * argument with an array that takes too many bytes to expressthe length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLongLengthArrayAsBoolean() throws Exception
+  {
+    final byte[] b = { 0x01, (byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 };
+    getReader(b, 0).readBoolean();
+  }
+
+
+
+  /**
+   * Tests the <CODE>readEnumerated</CODE> method that takes a byte array with a
+   * long length array.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLongLengthArrayAsEnumerated() throws Exception
+  {
+    final byte[] b = { 0x02, (byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 };
+    getReader(b, 0).readEnumerated();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsInteger</CODE> method that takes a byte array with
+   * a long length array.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLongLengthArrayAsInteger() throws Exception
+  {
+    final byte[] b = { 0x02, (byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 };
+    getReader(b, 0).readInteger();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsNull</CODE> method that takes a byte array argument
+   * with an array with a long length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLongLengthArrayAsNull() throws Exception
+  {
+    final byte[] b = new byte[] { 0x05, (byte) 0x85, 0x00, 0x00, 0x00, 0x00,
+        0x00 };
+    getReader(b, 0).readNull();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
+   * using an array that indicates it takes more than four bytes to encode the
+   * length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLongLengthArrayAsOctetString() throws Exception
+  {
+    final byte[] b = { 0x04, (byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    getReader(b, 0).readOctetString();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
+   * argument with an array that takes too many bytes to encode the length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLongLengthArrayAsSequence() throws Exception
+  {
+    final byte[] b = { 0x30, (byte) 0x85, 0x00, 0x00, 0x00, 0x00, 0x00 };
+    getReader(b, 0).readStartSequence();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsBoolean</CODE> method that takes a byte array
+   * argument with an array that has an invalid number of bytes in the value.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeLongValueArrayAsBoolean() throws Exception
+  {
+    final byte[] b = { 0x01, 0x02, 0x00, 0x00 };
+    getReader(b, 0).readBoolean();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsNull</CODE> method that takes a byte array argument
+   * with an arry with a nonzero length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeNonZeroLengthArrayAsNull() throws Exception
+  {
+    final byte[] b = new byte[] { 0x05, 0x01, 0x00 };
+    getReader(b, 0).readNull();
+  }
+
+
+
+  /**
+   * Tests the <CODE>readOctetString</CODE> method when the max element size is
+   * exceeded.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeOctetStringExceedMaxSize() throws Exception
+  {
+    final byte[] b = new byte[] { 0x04, 0x05, 0x48, 0x65, 0x6C, 0x6C, 0x6F };
+    getReader(b, 3).readOctetString();
+  }
+
+
+
+  /**
+   * Tests the <CODE>readOctetString</CODE> method when the max element size is
+   * exceeded.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeSequenceExceedMaxSize() throws Exception
+  {
+    final byte[] b = new byte[] { 0x30, 0x07, 0x04, 0x05, 0x48, 0x65, 0x6C,
+        0x6C, 0x6F };
+    getReader(b, 3).readOctetString();
+  }
+
+
+
+  /**
+   * Tests to make sure trailing components are ignored if not used.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test
+  public void testDecodeSequenceIncompleteRead() throws Exception
+  {
+    // An ASN.1 sequence of booleans missing one boolean element at the end
+    final byte[] b = new byte[] { 0x30, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01,
+        0x01, 0x01, 0x01, 0x00 };
+    final ASN1Reader reader = getReader(b, 0);
+    reader.readStartSequence();
+    reader.readEndSequence();
+    assertFalse(reader.readBoolean());
+  }
+
+
+
+  /**
+   * Tests to make sure a premature EOF while reading a sub sequence can be
+   * detected.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeSequencePrematureEof() throws Exception
+  {
+    // An ASN.1 sequence of booleans missing one boolean element at the end
+    final byte[] b = new byte[] { 0x30, 0x09, 0x01, 0x01, 0x00, 0x01, 0x01,
+        0x00 };
+    final ASN1Reader reader = getReader(b, 0);
+    reader.readStartSequence();
+    while (reader.hasNextElement())
+    {
+      reader.readBoolean();
+    }
+    reader.readEndSequence();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsBoolean</CODE> method that takes a byte array
+   * argument with a short array.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeShortArrayAsBoolean() throws Exception
+  {
+    final byte[] b = new byte[1];
+    getReader(b, 0).readBoolean();
+  }
+
+
+
+  /**
+   * Tests the <CODE>readEnumerated</CODE> method that takes a byte array with a
+   * short array.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeShortArrayAsEnumerated() throws Exception
+  {
+    final byte[] b = new byte[0];
+    getReader(b, 0).readEnumerated();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsInteger</CODE> method that takes a byte array with
+   * a short array.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeShortArrayAsInteger() throws Exception
+  {
+    final byte[] b = new byte[0];
+    getReader(b, 0).readInteger();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsNull</CODE> method that takes a byte array argument
+   * with a short array.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeShortArrayAsNull() throws Exception
+  {
+    final byte[] b = new byte[1];
+    getReader(b, 0).readNull();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
+   * using a short array.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeShortArrayAsOctetString() throws Exception
+  {
+    final byte[] b = new byte[1];
+    getReader(b, 0).readOctetString();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
+   * argument with a short array.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeShortArrayAsSequence() throws Exception
+  {
+    final byte[] b = new byte[1];
+    getReader(b, 0).readStartSequence();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsBoolean</CODE> method that takes a byte array
+   * argument with an array that has an invalid number of bytes in the value.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeShortValueArrayAsBoolean() throws Exception
+  {
+    final byte[] b = { 0x01, 0x00, 0x00, 0x00 };
+    getReader(b, 0).readBoolean();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsBoolean</CODE> method that takes a byte array
+   * argument with an array that doesn't contain a full length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeTruncatedLengthArrayAsBoolean() throws Exception
+  {
+    final byte[] b = { 0x01, (byte) 0x82, 0x00 };
+    getReader(b, 0).readBoolean();
+  }
+
+
+
+  /**
+   * Tests the <CODE>readEnumerated</CODE> method that takes a byte array with a
+   * truncated length array.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeTruncatedLengthArrayAsEnumerated() throws Exception
+  {
+    final byte[] b = { 0x02, (byte) 0x82, 0x00 };
+    getReader(b, 0).readEnumerated();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsInteger</CODE> method that takes a byte array with
+   * a truncated length array.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeTruncatedLengthArrayAsInteger() throws Exception
+  {
+    final byte[] b = { 0x02, (byte) 0x82, 0x00 };
+    getReader(b, 0).readInteger();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsNull</CODE> method that takes a byte array argument
+   * with an array with a truncated length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeTruncatedLengthArrayAsNull() throws Exception
+  {
+    final byte[] b = new byte[] { 0x05, (byte) 0x82, 0x00 };
+    getReader(b, 0).readNull();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
+   * using an array that doesn't fully contain the length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeTruncatedLengthArrayAsOctetString() throws Exception
+  {
+    final byte[] b = { 0x04, (byte) 0x82, 0x00 };
+    getReader(b, 0).readOctetString();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
+   * argument with an array that doesn't fully describe the length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testDecodeTruncatedLengthArrayAsSequence() throws Exception
+  {
+    final byte[] b = { 0x30, (byte) 0x82, 0x00 };
+    getReader(b, 0).readStartSequence();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsBoolean</CODE> method that takes a byte array
+   * argument with valid arrays.
+   *
+   * @param b
+   *          The byte array to use for the element values.
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(dataProvider = "byteValues")
+  public void testDecodeValidArrayAsBoolean(final byte[] b) throws Exception
+  {
+    // First, test with the standard Boolean type.
+    final byte[] elementArray = new byte[] { 0x01, 0x01, b[0] };
+    assertEquals(getReader(elementArray, 0).readBoolean(), (b[0] != 0x00));
+
+    // Next, test with a nonstandard Boolean type.
+    elementArray[0] = (byte) 0x50;
+    assertEquals(getReader(elementArray, 0).readBoolean(), (b[0] != 0x00));
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsOctetString</CODE> method that takes a byte array
+   * using a valid array.
+   *
+   * @param b
+   *          The byte array to decode.
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(dataProvider = "elementArrays")
+  public void testDecodeValidArrayAsOctetString(final byte[] b)
+      throws Exception
+  {
+    final ByteStringBuilder bsb = new ByteStringBuilder();
+    bsb.append(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE);
+    bsb.appendBERLength(b.length);
+    bsb.append(b);
+
+    assertEquals(getReader(bsb.toByteArray(), 0).readOctetString(), ByteString
+        .wrap(b));
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsOctetStringAsString</CODE> method that takes a byte
+   * array using a valid array.
+   *
+   * @param b
+   *          The byte array to decode.
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(dataProvider = "elementArrays")
+  public void testDecodeValidArrayAsOctetStringAsString(final byte[] b)
+      throws Exception
+  {
+    final ByteStringBuilder bsb = new ByteStringBuilder();
+    bsb.append(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE);
+    bsb.appendBERLength(b.length);
+    bsb.append(b);
+
+    assertEquals(getReader(bsb.toByteArray(), 0).readOctetStringAsString(),
+        new String(b, "UTF-8"));
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsOctetStringAsString</CODE> method that takes a byte
+   * array using a valid array.
+   *
+   * @param b
+   *          The byte array to decode.
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(dataProvider = "elementArrays")
+  public void testDecodeValidArrayAsOctetStringAsStringCharSet(final byte[] b)
+      throws Exception
+  {
+    final ByteStringBuilder bsb = new ByteStringBuilder();
+    bsb.append(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE);
+    bsb.appendBERLength(b.length);
+    bsb.append(b);
+
+    assertEquals(getReader(bsb.toByteArray(), 0).readOctetStringAsString(),
+        new String(b, "UTF-8"));
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsOctetStringBuilder</CODE> method that takes a byte
+   * array using a valid array.
+   *
+   * @param b
+   *          The byte array to decode.
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(dataProvider = "elementArrays")
+  public void testDecodeValidArrayAsOctetStringBuilder(final byte[] b)
+      throws Exception
+  {
+    final ByteStringBuilder bsb = new ByteStringBuilder();
+    bsb.append(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE);
+    bsb.appendBERLength(b.length);
+    bsb.append(b);
+
+    final ByteStringBuilder bsb2 = new ByteStringBuilder();
+    getReader(bsb.toByteArray(), 0).readOctetString(bsb2);
+    assertEquals(bsb2.toByteString(), ByteString.wrap(b));
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsSequence</CODE> method that takes a byte array
+   * argument with valid arrays.
+   *
+   * @param encodedElements
+   *          Byte arrays that may be used as valid values for encoded elements.
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(dataProvider = "elementArrays")
+  public void testDecodeValidArrayAsSequence(final byte[] encodedElements)
+      throws Exception
+  {
+    final ByteStringBuilder bsb = new ByteStringBuilder();
+    bsb.append(ASN1Constants.UNIVERSAL_SEQUENCE_TYPE);
+    bsb.appendBERLength(encodedElements.length + 2);
+    bsb.append(ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE);
+    bsb.appendBERLength(encodedElements.length);
+    bsb.append(encodedElements);
+
+    final ASN1Reader reader = getReader(bsb.toByteArray(), 0);
+    assertEquals(reader.peekLength(), encodedElements.length + 2);
+    reader.readStartSequence();
+    assertEquals(reader.peekType(), ASN1Constants.UNIVERSAL_OCTET_STRING_TYPE);
+    assertEquals(reader.peekLength(), encodedElements.length);
+    reader.readOctetString().equals(ByteString.wrap(encodedElements));
+    reader.readEndSequence();
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsBoolean</CODE> method that takes a byte array
+   * argument with valid arrays using extended lengths.
+   *
+   * @param b
+   *          The byte array to use for the element values.
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(dataProvider = "byteValues")
+  public void testDecodeValidExtendedArrayAsBoolean(final byte[] b)
+      throws Exception
+  {
+    // First, test with the standard Boolean type.
+    final byte[] elementArray = new byte[] { 0x01, (byte) 0x81, 0x01, b[0] };
+    assertEquals(getReader(elementArray, 0).readBoolean(), (b[0] != 0x00));
+
+    // Next, test with a nonstandard Boolean type.
+    elementArray[0] = (byte) 0x50;
+    assertEquals(getReader(elementArray, 0).readBoolean(), (b[0] != 0x00));
+  }
+
+
+
+  /**
+   * Tests the <CODE>decodeAsNull</CODE> method that takes a byte array argument
+   * with an arry with a zero length.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test()
+  public void testDecodeZeroLengthArrayAsNull() throws Exception
+  {
+    final byte[] b = new byte[] { 0x05, 0x00 };
+    getReader(b, 0).readNull();
+  }
+
+
+
+  /**
+   * Tests the <CODE>elementAvailable</CODE> method.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test
+  public void testElementAvailable() throws Exception
+  {
+    // An ASN.1 sequence of booleans missing one boolean element at the end
+    byte[] b = new byte[] { 0x30, 0x06, 0x02, 0x01, 0x00, 0x02 };
+    ASN1Reader reader = getReader(b, 0);
+    assertFalse(reader.elementAvailable());
+
+    b = new byte[] { 0x30, 0x03, 0x02, 0x01, 0x00 };
+    reader = getReader(b, 0);
+    assertTrue(reader.elementAvailable());
+    reader.readStartSequence();
+    assertTrue(reader.elementAvailable());
+    reader.readInteger();
+    assertFalse(reader.elementAvailable());
+  }
+
+
+
+  /**
+   * Tests the <CODE>hasNextElement</CODE> method.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test
+  public void testHasNextElement() throws Exception
+  {
+    // An ASN.1 sequence of booleans missing one boolean element at the end
+    byte[] b = new byte[] { 0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x00, 0x03 };
+    ASN1Reader reader = getReader(b, 0);
+    assertTrue(reader.hasNextElement());
+    reader.readStartSequence();
+    assertTrue(reader.hasNextElement());
+    reader.readInteger();
+    assertTrue(reader.hasNextElement());
+
+    b = new byte[] { 0x30, 0x03, 0x02, 0x01, 0x00 };
+    reader = getReader(b, 0);
+    assertTrue(reader.hasNextElement());
+    reader.readStartSequence();
+    assertTrue(reader.hasNextElement());
+    reader.readInteger();
+    assertFalse(reader.hasNextElement());
+  }
+
+
+
+  /**
+   * Tests the <CODE>readEndSequence</CODE> method without first calling
+   * readStartSequence.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { IllegalStateException.class, IOException.class })
+  public void testReadEndSequenceNoStartSequence() throws Exception
+  {
+    final byte[] b = { 0x30, 0x01, 0x00 };
+    getReader(b, 0).readEndSequence();
+  }
+
+
+
+  /**
+   * Tests the <CODE>skipElement</CODE> method.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test
+  public void testSkipElement() throws Exception
+  {
+    // An ASN.1 sequence of booleans missing one boolean element at the end
+    final byte[] b = new byte[] { 0x30, 0x09, 0x02, 0x01, 0x00, 0x02, 0x01,
+        0x01, 0x02, 0x01, 0x02 };
+    final ASN1Reader reader = getReader(b, 0);
+    reader.readStartSequence();
+    reader.readInteger();
+    reader.skipElement();
+    assertEquals(reader.readInteger(), 2);
+    reader.readEndSequence();
+  }
+
+
+
+  /**
+   * Tests the <CODE>skipElement</CODE> method.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test(expectedExceptions = { DecodeException.class, IOException.class })
+  public void testSkipElementIncompleteRead() throws Exception
+  {
+    // An ASN.1 sequence of booleans missing one boolean element at the end
+    final byte[] b = new byte[] { 0x30, 0x09, 0x01, 0x01, 0x00, 0x01, 0x02 };
+    final ASN1Reader reader = getReader(b, 0);
+    reader.readStartSequence();
+    reader.readBoolean();
+    reader.skipElement();
+    reader.readEndSequence();
+  }
+
+
+
+  /**
+   * Gets the reader to be use for the unit tests.
+   *
+   * @param b
+   *          The array of bytes to be read.
+   * @param maxElementSize
+   *          The max element size.
+   * @return The reader to be use for the unit tests.
+   * @throws IOException
+   *           In an unexpected IO exception occurred.
+   */
+  protected abstract ASN1Reader getReader(byte[] b, int maxElementSize)
+      throws IOException;
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1WriterTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1WriterTestCase.java
new file mode 100644
index 0000000..f43f9f7
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1WriterTestCase.java
@@ -0,0 +1,742 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+package org.opends.sdk.asn1;
+
+
+
+import static org.opends.sdk.asn1.ASN1Constants.*;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.IOException;
+
+import org.opends.sdk.ByteString;
+import org.opends.sdk.ByteStringBuilder;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.OpenDSTestCase;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.sun.opends.sdk.util.StaticUtils;
+
+
+
+/**
+ * An abstract base class for all ASN1Writer test cases.
+ */
+@Test(groups = { "precommit", "asn1", "sdk" }, sequential = true)
+public abstract class ASN1WriterTestCase extends OpenDSTestCase
+{
+
+  // Create an array with all of the valid single-byte types. We don't
+  // support multi-byte types, so this should be a comprehensive data set.
+  private final byte[] testTypes = new byte[0xFF];
+  {
+    for (int i = 0x00; i < 0xFF; i++)
+    {
+      testTypes[i] = (byte) (i & 0xFF);
+    }
+  }
+
+
+
+  /**
+   * Create byte arrays to use for element values.
+   *
+   * @return A list of byte arrays that can be used as element values.
+   */
+  @DataProvider(name = "binaryValues")
+  public Object[][] getBinaryValues()
+  {
+    // NOTE -- Don't make these arrays too big since they consume memory.
+    return new Object[][] { new Object[] { new byte[0x00] }, // The zero-byte
+        // value
+        new Object[] { new byte[0x01] }, // The single-byte value
+        new Object[] { new byte[0x7F] }, // The largest 1-byte length encoding
+        new Object[] { new byte[0x80] }, // The smallest 2-byte length encoding
+        new Object[] { new byte[0xFF] }, // The largest 2-byte length encoding
+        new Object[] { new byte[0x0100] }, // The smallest 3-byte length
+        // encoding
+        new Object[] { new byte[0xFFFF] }, // The largest 3-byte length encoding
+        new Object[] { new byte[0x010000] } // The smallest 4-byte length
+    // encoding
+    };
+  }
+
+
+
+  /**
+   * Retrieves the set of boolean values that may be used for testing.
+   *
+   * @return The set of boolean values that may be used for testing.
+   */
+  @DataProvider(name = "booleanValues")
+  public Object[][] getBooleanValues()
+  {
+    return new Object[][] { new Object[] { false }, new Object[] { true } };
+  }
+
+
+
+  /**
+   * Retrieves the set of int values that should be used for testing.
+   *
+   * @return The set of int values that should be used for testing.
+   */
+  @DataProvider(name = "intValues")
+  public Object[][] getIntValues()
+  {
+    return new Object[][] { new Object[] { 0x00000000, 1 },
+        new Object[] { 0x00000001, 1 }, new Object[] { 0x0000000F, 1 },
+        new Object[] { 0x00000010, 1 }, new Object[] { 0x0000007F, 1 },
+        new Object[] { 0x00000080, 2 }, new Object[] { 0x000000FF, 2 },
+        new Object[] { 0x00000100, 2 }, new Object[] { 0x00000FFF, 2 },
+        new Object[] { 0x00001000, 2 }, new Object[] { 0x0000FFFF, 3 },
+        new Object[] { 0x00010000, 3 }, new Object[] { 0x000FFFFF, 3 },
+        new Object[] { 0x00100000, 3 }, new Object[] { 0x00FFFFFF, 4 },
+        new Object[] { 0x01000000, 4 }, new Object[] { 0x0FFFFFFF, 4 },
+        new Object[] { 0x10000000, 4 }, new Object[] { 0x7FFFFFFF, 4 },
+        new Object[] { -0x00000001, 1 }, new Object[] { -0x0000000F, 1 },
+        new Object[] { -0x00000010, 1 }, new Object[] { -0x0000007F, 1 },
+        new Object[] { -0x00000080, 1 }, new Object[] { -0x000000FF, 2 },
+        new Object[] { -0x00000100, 2 }, new Object[] { -0x00000FFF, 2 },
+        new Object[] { -0x00001000, 2 }, new Object[] { -0x0000FFFF, 3 },
+        new Object[] { -0x00010000, 3 }, new Object[] { -0x000FFFFF, 3 },
+        new Object[] { -0x00100000, 3 }, new Object[] { -0x00FFFFFF, 4 },
+        new Object[] { -0x01000000, 4 }, new Object[] { -0x0FFFFFFF, 4 },
+        new Object[] { -0x10000000, 4 }, new Object[] { -0x7FFFFFFF, 4 },
+        new Object[] { 0x80000000, 4 } };
+  }
+
+
+
+  /**
+   * Retrieves the set of long values that should be used for testing.
+   *
+   * @return The set of long values that should be used for testing.
+   */
+  @DataProvider(name = "longValues")
+  public Object[][] getLongValues()
+  {
+    return new Object[][] { new Object[] { 0x0000000000000000L, 1 },
+        new Object[] { 0x0000000000000001L, 1 },
+        new Object[] { 0x000000000000007FL, 1 },
+        new Object[] { 0x0000000000000080L, 2 },
+        new Object[] { 0x00000000000000FFL, 2 },
+        new Object[] { 0x0000000000000100L, 2 },
+        new Object[] { 0x000000000000FFFFL, 3 },
+        new Object[] { 0x0000000000010000L, 3 },
+        new Object[] { 0x0000000000FFFFFFL, 4 },
+        new Object[] { 0x0000000001000000L, 4 },
+        new Object[] { 0x00000000FFFFFFFFL, 5 },
+        new Object[] { 0x0000000100000000L, 5 },
+        new Object[] { 0x000000FFFFFFFFFFL, 6 },
+        new Object[] { 0x0000010000000000L, 6 },
+        new Object[] { 0x0000FFFFFFFFFFFFL, 7 },
+        new Object[] { 0x0001000000000000L, 7 },
+        new Object[] { 0x00FFFFFFFFFFFFFFL, 8 },
+        new Object[] { 0x0100000000000000L, 8 },
+        new Object[] { 0x7FFFFFFFFFFFFFFFL, 8 },
+        new Object[] { -0x0000000000000001L, 1 },
+        new Object[] { -0x000000000000007FL, 1 },
+        new Object[] { -0x0000000000000080L, 1 },
+        new Object[] { -0x00000000000000FFL, 2 },
+        new Object[] { -0x0000000000000100L, 2 },
+        new Object[] { -0x000000000000FFFFL, 3 },
+        new Object[] { -0x0000000000010000L, 3 },
+        new Object[] { -0x0000000000FFFFFFL, 4 },
+        new Object[] { -0x0000000001000000L, 4 },
+        new Object[] { -0x00000000FFFFFFFFL, 5 },
+        new Object[] { -0x0000000100000000L, 5 },
+        new Object[] { -0x000000FFFFFFFFFFL, 6 },
+        new Object[] { -0x0000010000000000L, 6 },
+        new Object[] { -0x0000FFFFFFFFFFFFL, 7 },
+        new Object[] { -0x0001000000000000L, 7 },
+        new Object[] { -0x00FFFFFFFFFFFFFFL, 8 },
+        new Object[] { -0x0100000000000000L, 8 },
+        new Object[] { -0x7FFFFFFFFFFFFFFFL, 8 },
+        new Object[] { 0x8000000000000000L, 8 } };
+  }
+
+
+
+  /**
+   * Create strings to use for element values.
+   *
+   * @return A list of strings that can be used as element values.
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @DataProvider(name = "stringValues")
+  public Object[][] getStringValues() throws Exception
+  {
+    return new Object[][] { new Object[] { null }, new Object[] { "" },
+        new Object[] { "\u0000" }, new Object[] { "\t" },
+        new Object[] { "\n" }, new Object[] { "\r\n" }, new Object[] { " " },
+        new Object[] { "a" }, new Object[] { "Test1\tTest2\tTest3" },
+        new Object[] { "Test1\nTest2\nTest3" },
+        new Object[] { "Test1\r\nTest2\r\nTest3" },
+        new Object[] { "The Quick Brown Fox Jumps Over The Lazy Dog" },
+        new Object[] { "\u00BFD\u00F3nde est\u00E1 el ba\u00F1o?" } };
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readBoolean</CODE> methods.
+   *
+   * @param b
+   *          The boolean value to use in the test.
+   */
+  @Test(dataProvider = "booleanValues")
+  public void testEncodeDecodeBoolean(final boolean b) throws Exception
+  {
+    getWriter().writeBoolean(b);
+
+    final ASN1Reader r = getReader(getEncodedBytes());
+    assertEquals(r.peekLength(), 1);
+    assertEquals(r.peekType(), UNIVERSAL_BOOLEAN_TYPE);
+    assertEquals(r.readBoolean(), b);
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readBoolean</CODE> methods.
+   *
+   * @param b
+   *          The boolean value to use in the test.
+   */
+  @Test(dataProvider = "booleanValues")
+  public void testEncodeDecodeBooleanType(final boolean b) throws Exception
+  {
+    for (final byte type : testTypes)
+    {
+      getWriter().writeBoolean(type, b);
+
+      final ASN1Reader r = getReader(getEncodedBytes());
+      assertEquals(r.peekLength(), 1);
+      assertEquals(r.peekType(), type);
+      assertEquals(r.readBoolean(), b);
+    }
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readInteger</CODE> methods with Java ints.
+   *
+   * @param i
+   *          The integer value to use for the test.
+   */
+  @Test(dataProvider = "intValues")
+  public void testEncodeDecodeEnuerated(final int i, final int length)
+      throws Exception
+  {
+    getWriter().writeEnumerated(i);
+
+    final ASN1Reader r = getReader(getEncodedBytes());
+    assertEquals(r.peekLength(), length);
+    assertEquals(r.peekType(), UNIVERSAL_ENUMERATED_TYPE);
+    assertEquals(r.readInteger(), i);
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readInteger</CODE> methods with Java ints.
+   *
+   * @param i
+   *          The integer value to use for the test.
+   */
+  @Test(dataProvider = "intValues")
+  public void testEncodeDecodeInteger(final int i, final int length)
+      throws Exception
+  {
+    getWriter().writeInteger(i);
+
+    final ASN1Reader r = getReader(getEncodedBytes());
+    assertEquals(r.peekLength(), length);
+    assertEquals(r.peekType(), UNIVERSAL_INTEGER_TYPE);
+    assertEquals(r.readInteger(), i);
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readInteger</CODE> methods with Java longs.
+   *
+   * @param l
+   *          The long value to use for the test.
+   */
+  @Test(dataProvider = "longValues")
+  public void testEncodeDecodeInteger(final long l, final int length)
+      throws Exception
+  {
+    getWriter().writeInteger(l);
+
+    final ASN1Reader r = getReader(getEncodedBytes());
+    assertEquals(r.peekLength(), length);
+    assertEquals(r.peekType(), UNIVERSAL_INTEGER_TYPE);
+    assertEquals(r.readInteger(), l);
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readInteger</CODE> methods with Java ints.
+   *
+   * @param i
+   *          The integer value to use for the test.
+   */
+  @Test(dataProvider = "intValues")
+  public void testEncodeDecodeIntegerType(final int i, final int length)
+      throws Exception
+  {
+    for (final byte type : testTypes)
+    {
+      getWriter().writeInteger(type, i);
+
+      final ASN1Reader r = getReader(getEncodedBytes());
+      assertEquals(r.peekLength(), length);
+      assertEquals(r.peekType(), type);
+      assertEquals(r.readInteger(), i);
+    }
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readInteger</CODE> methods wiht JavaLongs.
+   *
+   * @param l
+   *          The long value to use for the test.
+   */
+  @Test(dataProvider = "longValues")
+  public void testEncodeDecodeIntegerType(final long l, final int length)
+      throws Exception
+  {
+    for (final byte type : testTypes)
+    {
+      getWriter().writeInteger(type, l);
+
+      final ASN1Reader r = getReader(getEncodedBytes());
+      assertEquals(r.peekLength(), length);
+      assertEquals(r.peekType(), type);
+      assertEquals(r.readInteger(), l);
+    }
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readNull</CODE> methods.
+   */
+  @Test
+  public void testEncodeDecodeNull() throws Exception
+  {
+    getWriter().writeNull();
+
+    final ASN1Reader r = getReader(getEncodedBytes());
+    assertEquals(r.peekLength(), 0);
+    assertEquals(r.peekType(), UNIVERSAL_NULL_TYPE);
+    r.readNull();
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readNull</CODE> methods.
+   */
+  @Test
+  public void testEncodeDecodeNullType() throws Exception
+  {
+    for (final byte type : testTypes)
+    {
+      getWriter().writeNull(type);
+
+      final ASN1Reader r = getReader(getEncodedBytes());
+      assertEquals(r.peekLength(), 0);
+      assertEquals(r.peekType(), type);
+      r.readNull();
+    }
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readOctetString</CODE> methods.
+   */
+  @Test(dataProvider = "binaryValues")
+  public void testEncodeDecodeOctetString(final byte[] b) throws Exception
+  {
+    final ByteString bs = ByteString.wrap(b);
+
+    getWriter().writeOctetString(bs);
+
+    ASN1Reader r = getReader(getEncodedBytes());
+    assertEquals(r.peekLength(), b.length);
+    assertEquals(r.peekType(), UNIVERSAL_OCTET_STRING_TYPE);
+    assertTrue(bs.equals(r.readOctetString()));
+
+    getWriter().writeOctetString(b, 0, b.length);
+
+    r = getReader(getEncodedBytes());
+    assertEquals(r.peekLength(), b.length);
+    assertEquals(r.peekType(), UNIVERSAL_OCTET_STRING_TYPE);
+    assertTrue(bs.equals(r.readOctetString()));
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readOctetString</CODE> methods.
+   */
+  @Test(dataProvider = "stringValues")
+  public void testEncodeDecodeOctetString(final String s) throws Exception
+  {
+    getWriter().writeOctetString(s);
+
+    final ASN1Reader r = getReader(getEncodedBytes());
+    if (s == null)
+    {
+      assertEquals(r.peekLength(), 0);
+    }
+    else
+    {
+      assertEquals(r.peekLength(), StaticUtils.getBytes(s).length);
+    }
+    assertEquals(r.peekType(), UNIVERSAL_OCTET_STRING_TYPE);
+    if (s == null)
+    {
+      assertTrue(r.readOctetStringAsString().equals(""));
+    }
+    else
+    {
+      assertTrue(s.equals(r.readOctetStringAsString()));
+    }
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readOctetString</CODE> methods.
+   */
+  @Test
+  public void testEncodeDecodeOctetStringOffLen() throws Exception
+  {
+    final byte[] b = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
+
+    for (int i = 0; i < 5; i += 2)
+    {
+      final byte[] bsb = new byte[3];
+      System.arraycopy(b, i, bsb, 0, 3);
+      final ByteString bs = ByteString.wrap(bsb);
+      getWriter().writeOctetString(b, i, 3);
+
+      final ASN1Reader r = getReader(getEncodedBytes());
+      assertEquals(r.peekLength(), 3);
+      assertEquals(r.peekType(), UNIVERSAL_OCTET_STRING_TYPE);
+      assertTrue(bs.equals(r.readOctetString()));
+    }
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readOctetString</CODE> methods.
+   */
+  @Test(dataProvider = "binaryValues")
+  public void testEncodeDecodeOctetStringType(final byte[] b) throws Exception
+  {
+    final ByteString bs = ByteString.wrap(b);
+    final ByteStringBuilder bsb = new ByteStringBuilder();
+
+    for (final byte type : testTypes)
+    {
+      bsb.clear();
+      getWriter().writeOctetString(type, bs);
+
+      ASN1Reader r = getReader(getEncodedBytes());
+      assertEquals(r.peekLength(), b.length);
+      assertEquals(r.peekType(), type);
+      r.readOctetString(bsb);
+      assertTrue(bs.equals(bsb));
+
+      bsb.clear();
+      getWriter().writeOctetString(type, b, 0, b.length);
+
+      r = getReader(getEncodedBytes());
+      assertEquals(r.peekLength(), b.length);
+      assertEquals(r.peekType(), type);
+      r.readOctetString(bsb);
+      assertTrue(bs.equals(bsb));
+    }
+  }
+
+
+
+  /**
+   * Tests the <CODE>write/readOctetString</CODE> methods.
+   */
+  @Test(dataProvider = "stringValues")
+  public void testEncodeDecodeOctetStringType(final String s) throws Exception
+  {
+    for (final byte type : testTypes)
+    {
+      getWriter().writeOctetString(type, s);
+
+      final ASN1Reader r = getReader(getEncodedBytes());
+      if (s == null)
+      {
+        assertEquals(r.peekLength(), 0);
+      }
+      else
+      {
+        assertEquals(r.peekLength(), StaticUtils.getBytes(s).length);
+      }
+      assertEquals(r.peekType(), type);
+      if (s == null)
+      {
+        assertTrue(r.readOctetStringAsString().equals(""));
+      }
+      else
+      {
+        assertTrue(s.equals(r.readOctetStringAsString()));
+      }
+    }
+  }
+
+
+
+  @Test
+  public void testEncodeDecodeSequence() throws Exception
+  {
+    final ASN1Writer writer = getWriter();
+
+    writer.writeStartSequence();
+
+    writer.writeBoolean(true);
+    writer.writeBoolean(false);
+    writer.writeInteger(0);
+    writer.writeInteger(10L);
+    writer.writeNull();
+    writer.writeOctetString("test value");
+    writer.writeOctetString("skip value");
+
+    writer.writeStartSequence();
+    writer.writeOctetString("nested sequence");
+    writer.writeEndSequence();
+
+    writer.writeStartSet();
+    writer.writeOctetString("nested set");
+    writer.writeEndSet();
+
+    writer.writeEndSequence();
+
+    final ASN1Reader reader = getReader(getEncodedBytes());
+    assertEquals(reader.peekType(), UNIVERSAL_SEQUENCE_TYPE);
+    assertEquals(reader.peekLength(), 71);
+
+    assertTrue(reader.hasNextElement());
+    reader.readStartSequence();
+    assertTrue(reader.hasNextElement());
+
+    assertEquals(true, reader.readBoolean());
+    assertEquals(false, reader.readBoolean());
+    assertEquals(0, reader.readInteger());
+    assertEquals(10, reader.readInteger());
+    reader.readNull();
+    assertEquals("test value", reader.readOctetStringAsString());
+    reader.skipElement();
+
+    assertEquals(reader.peekLength(), 17);
+    assertEquals(reader.peekType(), UNIVERSAL_SEQUENCE_TYPE);
+    reader.readStartSequence();
+    assertEquals("nested sequence", reader.readOctetStringAsString());
+    reader.readEndSequence();
+
+    assertEquals(reader.peekLength(), 12);
+    assertEquals(reader.peekType(), UNIVERSAL_SET_TYPE);
+    reader.readStartSequence();
+    assertEquals("nested set", reader.readOctetStringAsString());
+    reader.readEndSequence();
+
+    assertFalse(reader.hasNextElement());
+    reader.readEndSequence();
+    assertFalse(reader.elementAvailable());
+  }
+
+
+
+  /**
+   * Tests that negative integers are encoded according to ASN.1 BER
+   * specification.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test()
+  public void testNegativeIntEncoding() throws Exception
+  {
+    // Some negative integers of interest
+    // to test specific ranges/boundaries.
+    getWriter().writeInteger(-1);
+    byte[] value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFF);
+
+    getWriter().writeInteger(-2);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFE);
+
+    getWriter().writeInteger(-127);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0x81);
+
+    getWriter().writeInteger(-128);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0x80);
+
+    getWriter().writeInteger(-255);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFF);
+    assertEquals(value[3], (byte) 0x01);
+
+    getWriter().writeInteger(-256);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFF);
+    assertEquals(value[3], (byte) 0x00);
+
+    getWriter().writeInteger(-65535);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFF);
+    assertEquals(value[3], (byte) 0x00);
+    assertEquals(value[4], (byte) 0x01);
+
+    getWriter().writeInteger(-65536);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFF);
+    assertEquals(value[3], (byte) 0x00);
+    assertEquals(value[4], (byte) 0x00);
+
+    getWriter().writeInteger(-2147483647);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0x80);
+    assertEquals(value[3], (byte) 0x00);
+    assertEquals(value[4], (byte) 0x00);
+    assertEquals(value[5], (byte) 0x01);
+
+    getWriter().writeInteger(-2147483648);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0x80);
+    assertEquals(value[3], (byte) 0x00);
+    assertEquals(value[4], (byte) 0x00);
+    assertEquals(value[5], (byte) 0x00);
+  }
+
+
+
+  /**
+   * Tests that negative integers are encoded according to ASN.1 BER
+   * specification.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @Test()
+  public void testNegativeLongEncoding() throws Exception
+  {
+    // Some negative integers of interest
+    // to test specific ranges/boundaries.
+    getWriter().writeInteger(-1L);
+    byte[] value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFF);
+
+    getWriter().writeInteger(-2L);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFE);
+
+    getWriter().writeInteger(-127L);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0x81);
+
+    getWriter().writeInteger(-128L);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0x80);
+
+    getWriter().writeInteger(-255L);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFF);
+    assertEquals(value[3], (byte) 0x01);
+
+    getWriter().writeInteger(-256L);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFF);
+    assertEquals(value[3], (byte) 0x00);
+
+    getWriter().writeInteger(-65535L);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFF);
+    assertEquals(value[3], (byte) 0x00);
+    assertEquals(value[4], (byte) 0x01);
+
+    getWriter().writeInteger(-65536L);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0xFF);
+    assertEquals(value[3], (byte) 0x00);
+    assertEquals(value[4], (byte) 0x00);
+
+    getWriter().writeInteger(-2147483647L);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0x80);
+    assertEquals(value[3], (byte) 0x00);
+    assertEquals(value[4], (byte) 0x00);
+    assertEquals(value[5], (byte) 0x01);
+
+    getWriter().writeInteger(-2147483648L);
+    value = getEncodedBytes();
+    assertEquals(value[2], (byte) 0x80);
+    assertEquals(value[3], (byte) 0x00);
+    assertEquals(value[4], (byte) 0x00);
+    assertEquals(value[5], (byte) 0x00);
+  }
+
+
+
+  protected abstract byte[] getEncodedBytes() throws IOException,
+      DecodeException;
+
+
+
+  protected abstract ASN1Reader getReader(byte[] encodedBytes)
+      throws DecodeException, IOException;
+
+
+
+  protected abstract ASN1Writer getWriter() throws IOException;
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/controls/ControlsTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/controls/ControlsTestCase.java
new file mode 100644
index 0000000..6f0ec5e
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/controls/ControlsTestCase.java
@@ -0,0 +1,60 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.controls;
+
+
+
+import org.opends.sdk.OpenDSTestCase;
+import org.opends.sdk.TestCaseUtils;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * An abstract class that all controls unit tests should extend. A control
+ * represents the classes found directly under the package
+ * org.opends.sdk.controls.
+ */
+
+@Test(groups = { "precommit", "controls", "sdk" }, sequential = true)
+public abstract class ControlsTestCase extends OpenDSTestCase
+{
+  /**
+   * Set up the environment for performing the tests in this suite.
+   *
+   * @throws Exception
+   *           If the environment could not be set up.
+   */
+  @BeforeClass
+  public void setUp() throws Exception
+  {
+    // This test suite depends on having the schema available.
+    TestCaseUtils.startServer();
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryReaderTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryReaderTestCase.java
new file mode 100644
index 0000000..78c5b94
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryReaderTestCase.java
@@ -0,0 +1,88 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2009 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.ldif;
+
+
+
+import static org.testng.Assert.assertNotNull;
+
+import java.io.FileInputStream;
+
+import org.opends.sdk.AbstractEntry;
+import org.opends.sdk.TestCaseUtils;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * This class tests the LDIFEntryReader functionality.
+ */
+public final class LDIFEntryReaderTestCase extends LDIFTestCase
+{
+  /**
+   * Tests readEntry method of LDIFEntryReader class.See
+   * https://opends.dev.java.net/issues/show_bug.cgi?id=4545 for more details.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test()
+  public void testReadEntry() throws Exception
+  {
+    final String path = TestCaseUtils
+        .createTempFile(
+            "dn: uid=1,ou=people,dc=ucsf,dc=edu",
+            "objectClass: top",
+            "objectClass: person",
+            "objectClass: organizationalperson",
+            "objectClass: inetorgperson",
+            "givenName: Aaccf",
+            "sn: Amar",
+            "cn: Aaccf Amar",
+            "initials: ASA",
+            "employeeNumber: 020000001",
+            "uid: 1",
+            "mail: Aaccf.Amar@ucsf.edu",
+            "userPassword: password",
+            "telephoneNumber: +1 685 622 6202",
+            "homePhone: +1 225 216 5900",
+            "pager: +1 779 041 6341",
+            "mobile: +1 010 154 3228",
+            "street: 01251 Chestnut Street",
+            "l: Panama City",
+            "st: DE",
+            "postalCode: 50369",
+            "postalAddress: Aaccf Amar$01251 Chestnut Street$Panama City, DE  50369",
+            "description: This is the description for Aaccf Amar.");
+    final FileInputStream in = new FileInputStream(path);
+    final LDIFEntryReader entryReader = new LDIFEntryReader(in);
+    entryReader.setValidateSchema(false);
+    final AbstractEntry entry = (AbstractEntry) entryReader.readEntry();
+    assertNotNull(entry);
+  }
+}
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFTestCase.java
similarity index 68%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFTestCase.java
index 62b3ae3..e656589 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFTestCase.java
@@ -22,21 +22,23 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
-
-package org.opends.sdk.sasl;
+package org.opends.sdk.ldif;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.opends.sdk.OpenDSTestCase;
+import org.testng.annotations.Test;
 
 
 
 /**
- * Password call-back.
+ * An abstract class that all LDIF unit tests should extend. LDIF represents the
+ * classes found directly under the package org.opends.sdk.ldif.
  */
-public interface PasswordCallbackHandler
+
+@Test(groups = { "precommit", "types", "sdk" }, sequential = true)
+public abstract class LDIFTestCase extends OpenDSTestCase
 {
-  public boolean handle(PasswordCallback callback);
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AbandonRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AbandonRequestTestCase.java
new file mode 100644
index 0000000..2270531
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AbandonRequestTestCase.java
@@ -0,0 +1,67 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests Abandon requests.
+ */
+public class AbandonRequestTestCase extends RequestTestCase
+{
+  @DataProvider(name = "abandonRequests")
+  public Object[][] getAbandonRequests() throws Exception
+  {
+    final AbandonRequest[] requests = { Requests.newAbandonRequest(-1),
+        Requests.newAbandonRequest(0), Requests.newAbandonRequest(1) };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected AbandonRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getAbandonRequests();
+    final AbandonRequest[] ops = new AbandonRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (AbandonRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AddRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AddRequestTestCase.java
new file mode 100644
index 0000000..e3166ae
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AddRequestTestCase.java
@@ -0,0 +1,71 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.DN;
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests ADD requests.
+ */
+public class AddRequestTestCase extends RequestTestCase
+{
+  @DataProvider(name = "addRequests")
+  public Object[][] getAddRequests() throws Exception
+  {
+    final AddRequest[] requests = {
+        Requests.newAddRequest(DN.valueOf("uid=addrequest1")),
+        Requests.newAddRequest("cn=addrequesttestcase"),
+        Requests.newAddRequest("dn: ou=People,o=test", "objectClass: top",
+            "objectClass: organizationalUnit", "ou: People") };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected AddRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getAddRequests();
+    final AddRequest[] ops = new AddRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (AddRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AnonymousSASLBindRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AnonymousSASLBindRequestTestCase.java
new file mode 100644
index 0000000..db46a6e
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AnonymousSASLBindRequestTestCase.java
@@ -0,0 +1,68 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests anonymous SASL bind requests.
+ */
+public class AnonymousSASLBindRequestTestCase extends BindRequestTestCase
+{
+  @DataProvider(name = "anonymousSASLBindRequests")
+  public Object[][] getAnonymousSASLBindRequests() throws Exception
+  {
+    final AnonymousSASLBindRequest[] requests = {
+        Requests.newAnonymousSASLBindRequest(""),
+        Requests.newAnonymousSASLBindRequest("test") };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected AnonymousSASLBindRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getAnonymousSASLBindRequests();
+    final AnonymousSASLBindRequest[] ops = new AnonymousSASLBindRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (AnonymousSASLBindRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/BindRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/BindRequestTestCase.java
new file mode 100644
index 0000000..bb3f49a
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/BindRequestTestCase.java
@@ -0,0 +1,71 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import static org.testng.Assert.assertNotNull;
+
+import org.testng.annotations.Test;
+
+import com.sun.opends.sdk.ldap.LDAPConstants;
+
+
+
+/**
+ * Tests the BIND requests.
+ */
+public abstract class BindRequestTestCase extends RequestTestCase
+{
+  @Test(dataProvider = "testRequests")
+  public void testAuthType(final BindRequest request) throws Exception
+  {
+    final byte b = request.getAuthenticationType();
+    if (!(b == LDAPConstants.TYPE_AUTHENTICATION_SASL || b == LDAPConstants.TYPE_AUTHENTICATION_SIMPLE))
+    {
+      throw new Exception("Invalid bind type");
+    }
+  }
+
+
+
+  @Test(dataProvider = "testRequests")
+  public void testBindClient(final BindRequest request) throws Exception
+  {
+    final BindClient client = request.createBindClient("localhost");
+    assertNotNull(client);
+  }
+
+
+
+  @Test(dataProvider = "testRequests")
+  public void testName(final BindRequest request) throws Exception
+  {
+    assertNotNull(request.getName());
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestTestCase.java
new file mode 100644
index 0000000..437625f
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestTestCase.java
@@ -0,0 +1,69 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.ByteString;
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests CRAM MD5 SASL bind requests.
+ */
+public class CRAMMD5SASLBindRequestTestCase extends BindRequestTestCase
+{
+  @DataProvider(name = "CRAMMD5SASLBindRequests")
+  public Object[][] getCRAMMD5SASLBindRequests() throws Exception
+  {
+    final CRAMMD5SASLBindRequest[] requests = {
+        Requests.newCRAMMD5SASLBindRequest("id1", ByteString.empty()),
+        Requests.newCRAMMD5SASLBindRequest("id2", ByteString.valueOf("test")) };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected CRAMMD5SASLBindRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getCRAMMD5SASLBindRequests();
+    final CRAMMD5SASLBindRequest[] ops = new CRAMMD5SASLBindRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (CRAMMD5SASLBindRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CompareRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CompareRequestTestCase.java
new file mode 100644
index 0000000..8f006a8
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CompareRequestTestCase.java
@@ -0,0 +1,71 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * @author sin
+ */
+public class CompareRequestTestCase extends RequestTestCase
+{
+  @DataProvider(name = "CompareRequests")
+  public Object[][] getCompareRequests() throws Exception
+  {
+    final CompareRequest[] requests = {
+        Requests.newCompareRequest("uid=user.0,ou=people,o=test", "cn",
+            "user.0"),
+        Requests.newCompareRequest("uid=user.0,ou=people,o=test", "uid",
+            "user.0") };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected CompareRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getCompareRequests();
+    final CompareRequest[] ops = new CompareRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (CompareRequest) objs[i][0];
+    }
+    return ops;
+  }
+
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DeleteRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DeleteRequestTestCase.java
new file mode 100644
index 0000000..c3e73e5
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DeleteRequestTestCase.java
@@ -0,0 +1,70 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.DN;
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests the delete request.
+ */
+public class DeleteRequestTestCase extends RequestTestCase
+{
+  @DataProvider(name = "DeleteRequests")
+  public Object[][] getDeleteRequests() throws Exception
+  {
+    final DeleteRequest[] requests = {
+        Requests.newDeleteRequest(DN.valueOf("uid=Deleterequest1")),
+        Requests.newDeleteRequest("cn=Deleterequesttestcase"),
+        Requests.newDeleteRequest("uid=user.999,ou=people,o=test") };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected DeleteRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getDeleteRequests();
+    final DeleteRequest[] ops = new DeleteRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (DeleteRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DigestMD5SASLBindRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DigestMD5SASLBindRequestTestCase.java
new file mode 100644
index 0000000..1e12bcb
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DigestMD5SASLBindRequestTestCase.java
@@ -0,0 +1,71 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.ByteString;
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests Digest MD5 SASL requests.
+ */
+public class DigestMD5SASLBindRequestTestCase extends BindRequestTestCase
+{
+  @DataProvider(name = "DigestMD5SASLBindRequests")
+  public Object[][] getDigestMD5SASLBindRequests() throws Exception
+  {
+    final DigestMD5SASLBindRequest[] requests = {
+        Requests.newDigestMD5SASLBindRequest("id1", ByteString.empty()),
+        Requests.newDigestMD5SASLBindRequest("id2", ByteString
+            .valueOf("password")) };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected DigestMD5SASLBindRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getDigestMD5SASLBindRequests();
+    final DigestMD5SASLBindRequest[] ops = new DigestMD5SASLBindRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (DigestMD5SASLBindRequest) objs[i][0];
+    }
+    return ops;
+  }
+
+}
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExtendedRequestTestCase.java
similarity index 62%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExtendedRequestTestCase.java
index 62b3ae3..2c6f851 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExtendedRequestTestCase.java
@@ -22,21 +22,29 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package org.opends.sdk.requests;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import static org.testng.Assert.assertNotNull;
+
+import org.opends.sdk.responses.ExtendedResultDecoder;
+import org.testng.annotations.Test;
 
 
 
 /**
- * Password call-back.
+ * Tests various extended requests.
  */
-public interface PasswordCallbackHandler
+public abstract class ExtendedRequestTestCase extends RequestTestCase
 {
-  public boolean handle(PasswordCallback callback);
+  @Test(dataProvider = "testRequests")
+  public void testDecoder(final ExtendedRequest<?> request) throws Exception
+  {
+    final ExtendedResultDecoder<?> decoder = request.getResultDecoder();
+    assertNotNull(decoder);
+  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExternalSASLBindRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExternalSASLBindRequestTestCase.java
new file mode 100644
index 0000000..427205d
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExternalSASLBindRequestTestCase.java
@@ -0,0 +1,67 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests the external SASL Bind requests.
+ */
+public class ExternalSASLBindRequestTestCase extends BindRequestTestCase
+{
+  @DataProvider(name = "ExternalSASLBindRequests")
+  public Object[][] getExternalSASLBindRequests() throws Exception
+  {
+    final ExternalSASLBindRequest[] requests = { Requests
+        .newExternalSASLBindRequest() };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected ExternalSASLBindRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getExternalSASLBindRequests();
+    final ExternalSASLBindRequest[] ops = new ExternalSASLBindRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (ExternalSASLBindRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GSSAPISASLBindRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GSSAPISASLBindRequestTestCase.java
new file mode 100644
index 0000000..da0128e
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GSSAPISASLBindRequestTestCase.java
@@ -0,0 +1,70 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.ByteString;
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests GSSAPI SASL Bind requests.
+ */
+public abstract class GSSAPISASLBindRequestTestCase extends BindRequestTestCase
+{
+  @DataProvider(name = "GSSAPISASLBindRequests")
+  public Object[][] getGSSAPISASLBindRequests() throws Exception
+  {
+    final GSSAPISASLBindRequest[] requests = {
+        Requests.newGSSAPISASLBindRequest("id1", ByteString.empty()),
+        Requests
+            .newGSSAPISASLBindRequest("id2", ByteString.valueOf("password")) };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected GSSAPISASLBindRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getGSSAPISASLBindRequests();
+    final GSSAPISASLBindRequest[] ops = new GSSAPISASLBindRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (GSSAPISASLBindRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GenericBindRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GenericBindRequestTestCase.java
new file mode 100644
index 0000000..ca8b60e
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GenericBindRequestTestCase.java
@@ -0,0 +1,77 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.ByteString;
+import org.testng.annotations.DataProvider;
+
+import com.sun.opends.sdk.ldap.LDAPConstants;
+
+
+
+/**
+ * Tests Generic Bind requests.
+ */
+public class GenericBindRequestTestCase extends BindRequestTestCase
+{
+  @DataProvider(name = "GenericBindRequests")
+  public Object[][] getGenericBindRequests() throws Exception
+  {
+    final GenericBindRequest[] requests = {
+        Requests.newGenericBindRequest(LDAPConstants.TYPE_AUTHENTICATION_SASL,
+            ByteString.empty()),
+        Requests.newGenericBindRequest(
+            LDAPConstants.TYPE_AUTHENTICATION_SIMPLE, ByteString
+                .valueOf("password")),
+        Requests.newGenericBindRequest("username",
+            LDAPConstants.TYPE_AUTHENTICATION_SIMPLE, ByteString
+                .valueOf("password")) };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected GenericBindRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getGenericBindRequests();
+    final GenericBindRequest[] ops = new GenericBindRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (GenericBindRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyDNRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyDNRequestTestCase.java
new file mode 100644
index 0000000..e8e1e77
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyDNRequestTestCase.java
@@ -0,0 +1,69 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests the Modify DN requests.
+ */
+public class ModifyDNRequestTestCase extends RequestTestCase
+{
+  @DataProvider(name = "ModifyDNRequests")
+  public Object[][] getModifyDNRequests() throws Exception
+  {
+    final ModifyDNRequest[] requests = {
+        Requests.newModifyDNRequest("uid=user.100,ou=people,o=test",
+            "uid=100.user,ou=people,o=testl"),
+        Requests.newModifyDNRequest("cn=ModifyDNrequesttestcase", "cn=xyz"), };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected ModifyDNRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getModifyDNRequests();
+    final ModifyDNRequest[] ops = new ModifyDNRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (ModifyDNRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyRequestTestCase.java
new file mode 100644
index 0000000..57e9e7d
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyRequestTestCase.java
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.DN;
+import org.opends.sdk.ModificationType;
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests the modify request.
+ */
+public class ModifyRequestTestCase extends RequestTestCase
+{
+  @DataProvider(name = "ModifyRequests")
+  public Object[][] getModifyRequests() throws Exception
+  {
+    final ModifyRequest[] requests = {
+        Requests.newModifyRequest(DN.valueOf("uid=Modifyrequest1"))
+            .addModification(ModificationType.ADD, "userpassword", "password"),
+        Requests.newModifyRequest("cn=Modifyrequesttestcase").addModification(
+            ModificationType.ADD, "userpassword", "password"),
+        Requests.newModifyRequest("dn: ou=People,o=test", "changetype: modify",
+            "add: userpassword", "userpassword: password") };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected ModifyRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getModifyRequests();
+    final ModifyRequest[] ops = new ModifyRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (ModifyRequest) objs[i][0];
+    }
+    return ops;
+  }
+
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/PlainSASLBindRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/PlainSASLBindRequestTestCase.java
new file mode 100644
index 0000000..8f6a5d0
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/PlainSASLBindRequestTestCase.java
@@ -0,0 +1,69 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.opends.sdk.ByteString;
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests Plain SASL Bind requests.
+ */
+public class PlainSASLBindRequestTestCase extends BindRequestTestCase
+{
+  @DataProvider(name = "plainSASLBindRequests")
+  public Object[][] getPlainSASLBindRequests() throws Exception
+  {
+    final PlainSASLBindRequest[] requests = {
+        Requests.newPlainSASLBindRequest("id1", ByteString.empty()),
+        Requests.newPlainSASLBindRequest("id2", ByteString.valueOf("password")) };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected PlainSASLBindRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getPlainSASLBindRequests();
+    final PlainSASLBindRequest[] ops = new PlainSASLBindRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (PlainSASLBindRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestTestCase.java
new file mode 100644
index 0000000..71ef291
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestTestCase.java
@@ -0,0 +1,136 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import org.opends.sdk.Connection;
+import org.opends.sdk.DecodeException;
+import org.opends.sdk.DecodeOptions;
+import org.opends.sdk.TestCaseUtils;
+import org.opends.sdk.controls.Control;
+import org.opends.sdk.controls.ControlDecoder;
+import org.opends.sdk.controls.GenericControl;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+
+
+/**
+ * Tests the Request class.
+ */
+public abstract class RequestTestCase extends RequestsTestCase
+{
+  // Dummy decoder which does nothing.
+  private static class MyDecoder implements ControlDecoder<Control>
+  {
+    public Control decodeControl(final Control control,
+        final DecodeOptions options) throws DecodeException
+    {
+      // do nothing.
+      return control;
+    }
+
+
+
+    public String getOID()
+    {
+      return "1.2.3".intern();
+    }
+  }
+
+
+
+  // Connection used for sedning requests.
+  protected Connection con;
+
+
+
+  /**
+   * Request data to be validated.
+   *
+   * @return An array of requests.
+   * @throws Exception
+   */
+  @DataProvider(name = "testRequests")
+  public Object[][] getTestRequests() throws Exception
+  {
+    final Request[] requestArray = createTestRequests();
+    final Object[][] objectArray = new Object[requestArray.length][1];
+
+    for (int i = 0; i < requestArray.length; i++)
+    {
+      objectArray[i][0] = requestArray[i];
+    }
+    return objectArray;
+  }
+
+
+
+  /**
+   * Ensures that the LDAP Server is running.
+   *
+   * @throws Exception
+   *           If an unexpected problem occurs.
+   */
+  @BeforeClass()
+  public void startServer() throws Exception
+  {
+    TestCaseUtils.startServer();
+    con = TestCaseUtils.getInternalConnection();
+  }
+
+
+
+  @Test(dataProvider = "testRequests")
+  public void testControls(final Request request) throws Exception
+  {
+    // Add an arbitrary control and see if it is present.
+    Control control = GenericControl.newControl("1.2.3".intern());
+    request.addControl(control);
+    assertTrue(request.getControls().size() > 0);
+    final MyDecoder decoder = new MyDecoder();
+    control = request.getControl(decoder, new DecodeOptions());
+    assertNotNull(control);
+  }
+
+
+
+  /**
+   * Creates the test requests.
+   *
+   * @param <T>
+   * @return
+   * @throws Exception
+   */
+  protected abstract Request[] createTestRequests() throws Exception;
+}
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestsTestCase.java
similarity index 66%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestsTestCase.java
index 62b3ae3..81be811 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestsTestCase.java
@@ -22,21 +22,25 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package org.opends.sdk.requests;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.opends.sdk.OpenDSTestCase;
+import org.testng.annotations.Test;
 
 
 
 /**
- * Password call-back.
+ * An abstract class that all requests unit tests should extend. Requests
+ * represents the classes found directly under the package
+ * org.opends.sdk.requests.
  */
-public interface PasswordCallbackHandler
+
+@Test(groups = { "precommit", "requests", "sdk" }, sequential = true)
+public abstract class RequestsTestCase extends OpenDSTestCase
 {
-  public boolean handle(PasswordCallback callback);
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/SimpleBindRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/SimpleBindRequestTestCase.java
new file mode 100644
index 0000000..3086718
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/SimpleBindRequestTestCase.java
@@ -0,0 +1,68 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests Simple Bind requests.
+ */
+public class SimpleBindRequestTestCase extends BindRequestTestCase
+{
+  @DataProvider(name = "simpleBindRequests")
+  public Object[][] getSimpleBindRequests() throws Exception
+  {
+    final SimpleBindRequest[] requests = { Requests.newSimpleBindRequest(),// anonymous;
+        Requests.newSimpleBindRequest("username", "password") };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected SimpleBindRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getSimpleBindRequests();
+    final SimpleBindRequest[] ops = new SimpleBindRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (SimpleBindRequest) objs[i][0];
+    }
+    return ops;
+  }
+
+}
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/UnbindRequestTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/UnbindRequestTestCase.java
new file mode 100644
index 0000000..f4a0dec
--- /dev/null
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/UnbindRequestTestCase.java
@@ -0,0 +1,66 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2010 Sun Microsystems, Inc.
+ */
+
+package org.opends.sdk.requests;
+
+
+
+import org.testng.annotations.DataProvider;
+
+
+
+/**
+ * Tests the unbind requests.
+ */
+public class UnbindRequestTestCase extends RequestTestCase
+{
+  @DataProvider(name = "UnbindRequests")
+  public Object[][] getUnbindRequests() throws Exception
+  {
+    final UnbindRequest[] requests = { Requests.newUnbindRequest(), };
+    final Object[][] objArray = new Object[requests.length][1];
+    for (int i = 0; i < requests.length; i++)
+    {
+      objArray[i][0] = requests[i];
+    }
+    return objArray;
+  }
+
+
+
+  @Override
+  protected UnbindRequest[] createTestRequests() throws Exception
+  {
+    final Object[][] objs = getUnbindRequests();
+    final UnbindRequest[] ops = new UnbindRequest[objs.length];
+    for (int i = 0; i < objs.length; i++)
+    {
+      ops[i] = (UnbindRequest) objs[i][0];
+    }
+    return ops;
+  }
+}
diff --git a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/responses/ResponsesTestCase.java
similarity index 66%
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
copy to sdk/tests/unit-tests-testng/src/org/opends/sdk/responses/ResponsesTestCase.java
index 62b3ae3..7261a24 100644
--- a/sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/responses/ResponsesTestCase.java
@@ -22,21 +22,25 @@
  * CDDL HEADER END
  *
  *
- *      Copyright 2009 Sun Microsystems, Inc.
+ *      Copyright 2010 Sun Microsystems, Inc.
  */
 
-package org.opends.sdk.sasl;
+package org.opends.sdk.responses;
 
 
 
-import javax.security.auth.callback.PasswordCallback;
+import org.opends.sdk.OpenDSTestCase;
+import org.testng.annotations.Test;
 
 
 
 /**
- * Password call-back.
+ * An abstract class that all responses unit tests should extend. Responses
+ * represents the classes found directly under the package
+ * org.opends.sdk.responses.
  */
-public interface PasswordCallbackHandler
+
+@Test(groups = { "precommit", "responses", "sdk" }, sequential = true)
+public abstract class ResponsesTestCase extends OpenDSTestCase
 {
-  public boolean handle(PasswordCallback callback);
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AbstractSchemaElementTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AbstractSchemaElementTestCase.java
index 504d6dd..bafa766 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AbstractSchemaElementTestCase.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AbstractSchemaElementTestCase.java
@@ -43,30 +43,23 @@
 /**
  * Abstract schema element tests.
  */
-public abstract class AbstractSchemaElementTestCase extends
-    SchemaTestCase
+public abstract class AbstractSchemaElementTestCase extends SchemaTestCase
 {
-  protected static final Map<String, List<String>> EMPTY_PROPS =
-      Collections.emptyMap();
-  protected static final List<String> EMPTY_NAMES =
-      Collections.emptyList();
-
-
-
-  protected abstract SchemaElement getElement(String description,
-      Map<String, List<String>> extraProperties) throws SchemaException;
+  protected static final Map<String, List<String>> EMPTY_PROPS = Collections
+      .emptyMap();
+  protected static final List<String> EMPTY_NAMES = Collections.emptyList();
 
 
 
   @DataProvider(name = "equalsTestData")
-  public abstract Object[][] createEqualsTestData()
-      throws SchemaException, DecodeException;
+  public abstract Object[][] createEqualsTestData() throws SchemaException,
+      DecodeException;
 
 
 
   /**
    * Check that the equals operator works as expected.
-   * 
+   *
    * @param e1
    *          The first element
    * @param e2
@@ -77,8 +70,8 @@
    *           If the test failed unexpectedly.
    */
   @Test(dataProvider = "equalsTestData")
-  public final void testEquals(SchemaElement e1, SchemaElement e2,
-      boolean result) throws Exception
+  public final void testEquals(final SchemaElement e1, final SchemaElement e2,
+      final boolean result) throws Exception
   {
 
     Assert.assertEquals(e1.equals(e2), result);
@@ -88,8 +81,98 @@
 
 
   /**
+   * Check that the {@link SchemaElement#getDescription()} method returns a
+   * description.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public final void testGetDescription() throws Exception
+  {
+    final SchemaElement e = getElement("hello", EMPTY_PROPS);
+    Assert.assertEquals(e.getDescription(), "hello");
+  }
+
+
+
+  /**
+   * Check that the {@link SchemaElement#getDescription()} method returns
+   * <code>null</code> when there is no description.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public final void testGetDescriptionDefault() throws Exception
+  {
+    final SchemaElement e = getElement("", EMPTY_PROPS);
+    Assert.assertEquals(e.getDescription(), "");
+  }
+
+
+
+  /**
+   * Check that the {@link SchemaElement#getExtraProperty(String)} method
+   * returns values.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public final void testGetExtraProperty() throws Exception
+  {
+    final List<String> values = new ArrayList<String>();
+    values.add("one");
+    values.add("two");
+    final Map<String, List<String>> props = Collections.singletonMap("test",
+        values);
+    final SchemaElement e = getElement("", props);
+
+    int i = 0;
+    for (final String value : e.getExtraProperty("test"))
+    {
+      Assert.assertEquals(value, values.get(i));
+      i++;
+    }
+  }
+
+
+
+  /**
+   * Check that the {@link SchemaElement#getExtraProperty(String)} method
+   * returns <code>null</code> when there is no property.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public final void testGetExtraPropertyDefault() throws Exception
+  {
+    final SchemaElement e = getElement("", EMPTY_PROPS);
+    Assert.assertTrue(e.getExtraProperty("test").isEmpty());
+  }
+
+
+
+  /**
+   * Check that the {@link SchemaElement#getExtraPropertyNames()} method.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public final void testGetExtraPropertyNames() throws Exception
+  {
+    final SchemaElement e = getElement("", EMPTY_PROPS);
+    Assert.assertTrue(e.getExtraProperty("test").isEmpty());
+  }
+
+
+
+  /**
    * Check that the hasCode method operator works as expected.
-   * 
+   *
    * @param e1
    *          The first element
    * @param e2
@@ -100,8 +183,8 @@
    *           If the test failed unexpectedly.
    */
   @Test(dataProvider = "equalsTestData")
-  public final void testHashCode(SchemaElement e1, SchemaElement e2,
-      boolean result) throws Exception
+  public final void testHashCode(final SchemaElement e1,
+      final SchemaElement e2, final boolean result) throws Exception
   {
 
     Assert.assertEquals(e1.hashCode() == e2.hashCode(), result);
@@ -109,94 +192,6 @@
 
 
 
-  /**
-   * Check that the {@link SchemaElement#getDescription()} method
-   * returns <code>null</code> when there is no description.
-   * 
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test
-  public final void testGetDescriptionDefault() throws Exception
-  {
-    SchemaElement e = getElement("", EMPTY_PROPS);
-    Assert.assertEquals(e.getDescription(), "");
-  }
-
-
-
-  /**
-   * Check that the {@link SchemaElement#getDescription()} method
-   * returns a description.
-   * 
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test
-  public final void testGetDescription() throws Exception
-  {
-    SchemaElement e = getElement("hello", EMPTY_PROPS);
-    Assert.assertEquals(e.getDescription(), "hello");
-  }
-
-
-
-  /**
-   * Check that the {@link SchemaElement#getExtraProperty(String)}
-   * method returns <code>null</code> when there is no property.
-   * 
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test
-  public final void testGetExtraPropertyDefault() throws Exception
-  {
-    SchemaElement e = getElement("", EMPTY_PROPS);
-    Assert.assertNull(e.getExtraProperty("test"));
-  }
-
-
-
-  /**
-   * Check that the {@link SchemaElement#getExtraProperty(String)}
-   * method returns values.
-   * 
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test
-  public final void testGetExtraProperty() throws Exception
-  {
-    List<String> values = new ArrayList<String>();
-    values.add("one");
-    values.add("two");
-    Map<String, List<String>> props =
-        Collections.singletonMap("test", values);
-    SchemaElement e = getElement("", props);
-
-    Assert.assertNotNull(e.getExtraProperty("test"));
-    int i = 0;
-    for (String value : e.getExtraProperty("test"))
-    {
-      Assert.assertEquals(value, values.get(i));
-      i++;
-    }
-  }
-
-
-
-  /**
-   * Check that the {@link SchemaElement#getExtraPropertyNames()}
-   * method.
-   * 
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test
-  public final void testGetExtraPropertyNames() throws Exception
-  {
-    SchemaElement e = getElement("", EMPTY_PROPS);
-    Assert.assertNull(e.getExtraProperty("test"));
-    Assert.assertFalse(e.getExtraPropertyNames().iterator().hasNext());
-  }
+  protected abstract SchemaElement getElement(String description,
+      Map<String, List<String>> extraProperties) throws SchemaException;
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/ApproximateMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/ApproximateMatchingRuleTest.java
index ce6a792..a8ce15a 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/ApproximateMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/ApproximateMatchingRuleTest.java
@@ -31,12 +31,11 @@
 import static org.opends.sdk.schema.SchemaConstants.AMR_DOUBLE_METAPHONE_NAME;
 import static org.testng.Assert.assertEquals;
 
+import org.opends.sdk.ByteString;
 import org.opends.sdk.ConditionResult;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import org.opends.sdk.ByteString;
-
 
 
 /**
@@ -50,6 +49,26 @@
 
 
   /**
+   * Test the normalization and the approximate comparison.
+   */
+  @Test(dataProvider = "approximatematchingrules")
+  public void approximateMatchingRules(final MatchingRule rule,
+      final String value1, final String value2, final ConditionResult result)
+      throws Exception
+  {
+    // normalize the 2 provided values
+    final ByteString normalizedValue1 = rule.normalizeAttributeValue(ByteString
+        .valueOf(value1));
+
+    // check that the approximatelyMatch return the expected result.
+    final ConditionResult liveResult = rule.getAssertion(
+        ByteString.valueOf(value2)).matches(normalizedValue1);
+    assertEquals(result, liveResult);
+  }
+
+
+
+  /**
    * Build the data for the approximateMatchingRules test.
    */
   @DataProvider(name = "approximatematchingrules")
@@ -132,8 +151,7 @@
         { metaphone, "algorithme", "algorizm", ConditionResult.TRUE },
         { metaphone, "testing", "testng", ConditionResult.TRUE },
         { metaphone, "announce", "annonce", ConditionResult.TRUE },
-        { metaphone, "automaticly", "automatically",
-            ConditionResult.TRUE },
+        { metaphone, "automaticly", "automatically", ConditionResult.TRUE },
         { metaphone, "modifyd", "modified", ConditionResult.TRUE },
         { metaphone, "bouteille", "butaille", ConditionResult.TRUE },
         { metaphone, "xeon", "zeon", ConditionResult.TRUE },
@@ -142,24 +160,4 @@
         { metaphone, "thimble", "thimblle", ConditionResult.TRUE },
         { metaphone, "", "", ConditionResult.TRUE }, };
   }
-
-
-
-  /**
-   * Test the normalization and the approximate comparison.
-   */
-  @Test(dataProvider = "approximatematchingrules")
-  public void approximateMatchingRules(MatchingRule rule,
-      String value1, String value2, ConditionResult result)
-      throws Exception
-  {
-    // normalize the 2 provided values
-    ByteString normalizedValue1 = rule
-        .normalizeAttributeValue(ByteString.valueOf(value1));
-
-    // check that the approximatelyMatch return the expected result.
-    ConditionResult liveResult = rule.getAssertion(
-        ByteString.valueOf(value2)).matches(normalizedValue1);
-    assertEquals(result, liveResult);
-  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeSyntaxTest.java
index 785f8e0..05c87d2 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeSyntaxTest.java
@@ -43,17 +43,6 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
-  {
-    return Schema.getCoreSchema().getSyntax(SYNTAX_ATTRIBUTE_TYPE_OID);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
   @DataProvider(name = "acceptableValues")
   public Object[][] createAcceptableValues()
   {
@@ -98,4 +87,15 @@
                 + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
                 + " NO-USER-MODIFICATION USAGE userApplications", false }, };
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected Syntax getRule()
+  {
+    return Schema.getCoreSchema().getSyntax(SYNTAX_ATTRIBUTE_TYPE_OID);
+  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeTest.java
index a24fc50..110ee16 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeTest.java
@@ -45,43 +45,38 @@
  */
 public class AttributeTypeTest extends AbstractSchemaElementTestCase
 {
-  private Schema schema;
+  private final Schema schema;
 
 
 
   public AttributeTypeTest() throws Exception
   {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addAttributeType("1.2.1", EMPTY_NAMES, "", true, null,
-        null, null, null, null, "1.3.6.1.4.1.1466.115.121.1.27", true,
-        false, false, AttributeUsage.USER_APPLICATIONS, EMPTY_PROPS,
-        false);
-    builder
-        .addAttributeType(
-            "( 1.2.2 OBSOLETE SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE "
-                + " COLLECTIVE X-ORIGIN ( 'Sun Java System Identity Management' "
-                + "'user defined' ) X-SCHEMA-FILE '98sunEmp.ldif')",
-            false);
-    builder.addAttributeType("1.2.3", Collections
-        .singletonList("testType"), "", false, "1.2.2", null, null,
-        null, null, "1.3.6.1.4.1.1466.115.121.1.27", false, true,
-        false, AttributeUsage.USER_APPLICATIONS, EMPTY_PROPS, false);
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addAttributeType("1.2.1", EMPTY_NAMES, "", true, null, null, null,
+        null, null, "1.3.6.1.4.1.1466.115.121.1.27", true, false, false,
+        AttributeUsage.USER_APPLICATIONS, EMPTY_PROPS, false);
     builder.addAttributeType(
-        "( 1.2.4 NAME 'testType' SUP 1.2.3 SINGLE-VALUE COLLECTIVE )",
-        false);
-    List<String> names = new LinkedList<String>();
+        "( 1.2.2 OBSOLETE SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE "
+            + " COLLECTIVE X-ORIGIN ( 'Sun Java System Identity Management' "
+            + "'user defined' ) X-SCHEMA-FILE '98sunEmp.ldif')", false);
+    builder.addAttributeType("1.2.3", Collections.singletonList("testType"),
+        "", false, "1.2.2", null, null, null, null,
+        "1.3.6.1.4.1.1466.115.121.1.27", false, true, false,
+        AttributeUsage.USER_APPLICATIONS, EMPTY_PROPS, false);
+    builder.addAttributeType(
+        "( 1.2.4 NAME 'testType' SUP 1.2.3 SINGLE-VALUE COLLECTIVE )", false);
+    final List<String> names = new LinkedList<String>();
     names.add("testType");
     names.add("testnamealias");
     names.add("anothernamealias");
     builder.addAttributeType("1.2.5", names, "", false, null,
         EMR_CASE_IGNORE_LIST_OID, null, SMR_CASE_IGNORE_LIST_OID,
-        AMR_DOUBLE_METAPHONE_OID, SYNTAX_INTEGER_OID, false, false,
-        true, AttributeUsage.DSA_OPERATION, EMPTY_PROPS, false);
-    builder
-        .addAttributeType(
-            "( 1.2.6 NAME ( 'testType' 'testnamealias' 'anothernamealias1' ) "
-                + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SUP anothernamealias"
-                + " USAGE dSAOperation NO-USER-MODIFICATION )", false);
+        AMR_DOUBLE_METAPHONE_OID, SYNTAX_INTEGER_OID, false, false, true,
+        AttributeUsage.DSA_OPERATION, EMPTY_PROPS, false);
+    builder.addAttributeType(
+        "( 1.2.6 NAME ( 'testType' 'testnamealias' 'anothernamealias1' ) "
+            + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SUP anothernamealias"
+            + " USAGE dSAOperation NO-USER-MODIFICATION )", false);
     schema = builder.toSchema();
     if (!schema.getWarnings().isEmpty())
     {
@@ -91,67 +86,180 @@
 
 
 
-  protected SchemaElement getElement(String description,
-      Map<String, List<String>> extraProperties) throws SchemaException
-  {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addAttributeType("1.2.3", Collections
-        .singletonList("testType"), description, false, null, null,
-        null, null, null, "1.3.6.1.4.1.1466.115.121.1.27", false,
-        false, false, AttributeUsage.DSA_OPERATION, extraProperties,
-        false);
-    return builder.toSchema().getAttributeType("1.2.3");
-  }
-
-
-
   @DataProvider(name = "equalsTestData")
   public Object[][] createEqualsTestData() throws SchemaException,
       DecodeException
   {
     return new Object[][] {
-        { schema.getAttributeType("1.2.3"),
-            schema.getAttributeType("1.2.3"), true },
-        { schema.getAttributeType("1.2.4"),
-            schema.getAttributeType("1.2.3"), false } };
+        { schema.getAttributeType("1.2.3"), schema.getAttributeType("1.2.3"),
+            true },
+        { schema.getAttributeType("1.2.4"), schema.getAttributeType("1.2.3"),
+            false } };
   }
 
 
 
-  /**
-   * Check that the simple constructor throws an NPE when mandatory
-   * parameters are not specified.
-   *
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test(expectedExceptions = IllegalArgumentException.class)
-  public void testNoSupNorSyntax1() throws Exception
+  @Test
+  public void testADSyntax() throws Exception
   {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addAttributeType("1.2.1", EMPTY_NAMES, "", true, null,
-        null, null, null, null, null, false, false, false,
-        AttributeUsage.DSA_OPERATION, EMPTY_PROPS, false);
+    // AD uses single quotes around OIDs
+    final SchemaBuilder builder = new SchemaBuilder(schema);
     builder
-        .addAttributeType(
-            "( 1.2.2 OBSOLETE SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )",
+        .addAttributeType("(1.2.8.5 NAME 'testtype' DESC 'full type' "
+            + " SUP '1.2.5' " + " EQUALITY 'caseIgnoreMatch' "
+            + " SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' USAGE dSAOperation )",
             false);
+    Assert.assertTrue(builder.toSchema().getWarnings().isEmpty());
+  }
+
+
+
+  @Test(expectedExceptions = LocalizedIllegalArgumentException.class)
+  public void testADSyntaxQuoteMismatch() throws Exception
+  {
+    // AD uses single quotes around OIDs
+    final SchemaBuilder builder = new SchemaBuilder(schema);
+    builder
+        .addAttributeType("(1.2.8.5 NAME 'testtype' DESC 'full type' "
+            + " SUP '1.2.5 " + " EQUALITY 'caseIgnoreMatch' "
+            + " SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' USAGE dSAOperation )",
+            false);
+    Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
+  }
+
+
+
+  @Test
+  public void testCollectiveOperational() throws Exception
+  {
+    // Collective can't be operational
+    final SchemaBuilder builder = new SchemaBuilder(schema);
+    builder.addAttributeType(
+        "(1.2.8.5 NAME 'testtype' DESC 'full type' OBSOLETE "
+            + " EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch"
+            + " SUBSTR caseIgnoreSubstringsMatch"
+            + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
+            + " COLLECTIVE USAGE directoryOperation )", false);
+    Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
   }
 
 
 
   /**
-   * Check that the simple constructor throws an NPE when mandatory
-   * parameters are not specified.
+   * Check constructor sets the default matching rules correctly.
    *
    * @throws Exception
    *           If the test failed unexpectedly.
    */
-  @Test(expectedExceptions = IllegalArgumentException.class)
-  public void testNoSupNorSyntax2() throws Exception
+  @Test
+  public void testConstructorDefaultMatchingRules() throws Exception
   {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addAttributeType("( 1.2.2 OBSOLETE SINGLE-VALUE )", false);
+    final AttributeType type = schema.getAttributeType("1.2.1");
+
+    final Syntax syntax = schema.getSyntax("1.3.6.1.4.1.1466.115.121.1.27");
+    Assert.assertEquals(type.getApproximateMatchingRule(), syntax
+        .getApproximateMatchingRule());
+    Assert.assertEquals(type.getEqualityMatchingRule(), syntax
+        .getEqualityMatchingRule());
+    Assert.assertEquals(type.getOrderingMatchingRule(), syntax
+        .getOrderingMatchingRule());
+    Assert.assertEquals(type.getSubstringMatchingRule(), syntax
+        .getSubstringMatchingRule());
+  }
+
+
+
+  /**
+   * Check constructor sets the default usage correctly.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testConstructorDefaultUsage() throws Exception
+  {
+    final AttributeType d = schema.getAttributeType("1.2.2");
+
+    Assert.assertEquals(d.getUsage(), AttributeUsage.USER_APPLICATIONS);
+  }
+
+
+
+  /**
+   * Check constructor inherits the matching rules from the parent type when
+   * required.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dependsOnMethods = "testConstructorMatchingRules")
+  public void testConstructorInheritsMatchingRules() throws Exception
+  {
+    final AttributeType parent = schema.getAttributeType("1.2.5");
+
+    final AttributeType child = schema.getAttributeType("1.2.6");
+
+    Assert.assertEquals(parent.getApproximateMatchingRule(), child
+        .getApproximateMatchingRule());
+    Assert.assertEquals(parent.getEqualityMatchingRule(), child
+        .getEqualityMatchingRule());
+    // It should inherit ordering rule from parent's syntax since parent
+    // didn't specify an ordering matching rule.
+    Assert.assertEquals(parent.getSyntax().getOrderingMatchingRule(), child
+        .getOrderingMatchingRule());
+    Assert.assertEquals(parent.getSubstringMatchingRule(), child
+        .getSubstringMatchingRule());
+  }
+
+
+
+  /**
+   * Check constructor inherits the syntax from the parent type when required.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test(dependsOnMethods = "testConstructorSyntax")
+  public void testConstructorInheritsSyntax() throws Exception
+  {
+    AttributeType parent = schema.getAttributeType("1.2.3");
+
+    AttributeType child = schema.getAttributeType("1.2.4");
+
+    Assert.assertEquals(parent.getSyntax(), child.getSyntax());
+
+    parent = schema.getAttributeType("1.2.2");
+
+    child = schema.getAttributeType("1.2.3");
+    Assert.assertFalse(parent.getSyntax().equals(child.getSyntax()));
+
+    // Make sure paren't s syntax was not inherited in this case
+    child = schema.getAttributeType("1.2.6");
+    Assert
+        .assertEquals(child.getSyntax().getOID(), SYNTAX_DIRECTORY_STRING_OID);
+  }
+
+
+
+  /**
+   * Check constructor sets the matching rules correctly.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testConstructorMatchingRules() throws Exception
+  {
+    final AttributeType type = schema.getAttributeType("1.2.5");
+
+    Assert.assertEquals(type.getEqualityMatchingRule().getOID(),
+        EMR_CASE_IGNORE_LIST_OID);
+    Assert.assertEquals(type.getOrderingMatchingRule().getOID(), type
+        .getSyntax().getOrderingMatchingRule().getOID());
+    Assert.assertEquals(type.getSubstringMatchingRule().getOID(),
+        SMR_CASE_IGNORE_LIST_OID);
+    Assert.assertEquals(type.getApproximateMatchingRule().getOID(),
+        AMR_DOUBLE_METAPHONE_OID);
   }
 
 
@@ -180,6 +288,23 @@
 
 
   /**
+   * Check constructor sets the syntax correctly.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testConstructorSyntax() throws Exception
+  {
+    final AttributeType d = schema.getAttributeType("1.2.2");
+
+    Assert
+        .assertEquals(d.getSyntax().getOID(), "1.3.6.1.4.1.1466.115.121.1.15");
+  }
+
+
+
+  /**
    * Check that the type names are accessible.
    *
    * @throws Exception
@@ -204,6 +329,23 @@
 
 
   /**
+   * Check that the {@link AttributeType#getUsage()} method.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testGetAttributeUsage() throws Exception
+  {
+    AttributeType type = schema.getAttributeType("1.2.1");
+    Assert.assertEquals(type.getUsage(), AttributeUsage.USER_APPLICATIONS);
+    type = schema.getAttributeType("1.2.6");
+    Assert.assertEquals(type.getUsage(), AttributeUsage.DSA_OPERATION);
+  }
+
+
+
+  /**
    * Check that the {@link CommonSchemaElements#getNameOrOID()} method.
    *
    * @throws Exception
@@ -230,8 +372,7 @@
    *           If the test failed unexpectedly.
    */
   @Test
-  public final void testGetNameOrOIDReturnsPrimaryName()
-      throws Exception
+  public final void testGetNameOrOIDReturnsPrimaryName() throws Exception
   {
     AttributeType d = schema.getAttributeType("1.2.3");
     Assert.assertEquals(d.getNameOrOID(), "testType");
@@ -242,8 +383,7 @@
 
 
   /**
-   * Check that the {@link CommonSchemaElements#getNormalizedNames()}
-   * method.
+   * Check that the {@link CommonSchemaElements#getNormalizedNames()} method.
    *
    * @throws Exception
    *           If the test failed unexpectedly.
@@ -285,8 +425,24 @@
 
 
   /**
-   * Check that the {@link CommonSchemaElements#hasNameOrOID(String)}
-   * method.
+   * Check that the {@link AttributeType#getSuperiorType()} method.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public void testGetSuperiorType() throws Exception
+  {
+    AttributeType type = schema.getAttributeType("1.2.3");
+    Assert.assertEquals(type.getSuperiorType().getOID(), "1.2.2");
+    type = schema.getAttributeType("1.2.4");
+    Assert.assertEquals(type.getSuperiorType().getOID(), "1.2.3");
+  }
+
+
+
+  /**
+   * Check that the {@link CommonSchemaElements#hasNameOrOID(String)} method.
    *
    * @throws Exception
    *           If the test failed unexpectedly.
@@ -308,161 +464,34 @@
 
 
 
-  /**
-   * Check that the {@link CommonSchemaElements#isObsolete()} method.
-   *
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
   @Test
-  public final void testIsObsolete() throws Exception
+  public void testInheritFromNonCollective() throws Exception
   {
-    AttributeType d = schema.getAttributeType("1.2.3");
-    Assert.assertFalse(d.isObsolete());
-    d = schema.getAttributeType("1.2.4");
-    Assert.assertFalse(d.isObsolete());
-
-    d = schema.getAttributeType("1.2.1");
-    Assert.assertTrue(d.isObsolete());
-    d = schema.getAttributeType("1.2.2");
-    Assert.assertTrue(d.isObsolete());
+    // Collective can't inherit from non-collective
+    final SchemaBuilder builder = new SchemaBuilder(schema);
+    builder.addAttributeType("(1.2.8.5 NAME 'testtype' DESC 'full type' "
+        + " OBSOLETE SUP 1.2.5 "
+        + " EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch"
+        + " SUBSTR caseIgnoreSubstringsMatch"
+        + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
+        + " COLLECTIVE USAGE userApplications )", false);
+    Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
   }
 
 
 
-  /**
-   * Check constructor sets the default usage correctly.
-   *
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
   @Test
-  public void testConstructorDefaultUsage() throws Exception
+  public void testInheritFromUserAppUsage() throws Exception
   {
-    AttributeType d = schema.getAttributeType("1.2.2");
-
-    Assert.assertEquals(d.getUsage(), AttributeUsage.USER_APPLICATIONS);
-  }
-
-
-
-  /**
-   * Check constructor sets the syntax correctly.
-   *
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test
-  public void testConstructorSyntax() throws Exception
-  {
-    AttributeType d = schema.getAttributeType("1.2.2");
-
-    Assert.assertEquals(d.getSyntax().getOID(),
-        "1.3.6.1.4.1.1466.115.121.1.15");
-  }
-
-
-
-  /**
-   * Check constructor inherits the syntax from the parent type when
-   * required.
-   *
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test(dependsOnMethods = "testConstructorSyntax")
-  public void testConstructorInheritsSyntax() throws Exception
-  {
-    AttributeType parent = schema.getAttributeType("1.2.3");
-
-    AttributeType child = schema.getAttributeType("1.2.4");
-
-    Assert.assertEquals(parent.getSyntax(), child.getSyntax());
-
-    parent = schema.getAttributeType("1.2.2");
-
-    child = schema.getAttributeType("1.2.3");
-    Assert.assertFalse(parent.getSyntax().equals(child.getSyntax()));
-
-    // Make sure paren't s syntax was not inherited in this case
-    child = schema.getAttributeType("1.2.6");
-    Assert.assertEquals(child.getSyntax().getOID(),
-        SYNTAX_DIRECTORY_STRING_OID);
-  }
-
-
-
-  /**
-   * Check constructor sets the default matching rules correctly.
-   *
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test
-  public void testConstructorDefaultMatchingRules() throws Exception
-  {
-    AttributeType type = schema.getAttributeType("1.2.1");
-
-    Syntax syntax = schema.getSyntax("1.3.6.1.4.1.1466.115.121.1.27");
-    Assert.assertEquals(type.getApproximateMatchingRule(), syntax
-        .getApproximateMatchingRule());
-    Assert.assertEquals(type.getEqualityMatchingRule(), syntax
-        .getEqualityMatchingRule());
-    Assert.assertEquals(type.getOrderingMatchingRule(), syntax
-        .getOrderingMatchingRule());
-    Assert.assertEquals(type.getSubstringMatchingRule(), syntax
-        .getSubstringMatchingRule());
-  }
-
-
-
-  /**
-   * Check constructor sets the matching rules correctly.
-   *
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test
-  public void testConstructorMatchingRules() throws Exception
-  {
-    AttributeType type = schema.getAttributeType("1.2.5");
-
-    Assert.assertEquals(type.getEqualityMatchingRule().getOID(),
-        EMR_CASE_IGNORE_LIST_OID);
-    Assert.assertEquals(type.getOrderingMatchingRule().getOID(), type
-        .getSyntax().getOrderingMatchingRule().getOID());
-    Assert.assertEquals(type.getSubstringMatchingRule().getOID(),
-        SMR_CASE_IGNORE_LIST_OID);
-    Assert.assertEquals(type.getApproximateMatchingRule().getOID(),
-        AMR_DOUBLE_METAPHONE_OID);
-  }
-
-
-
-  /**
-   * Check constructor inherits the matching rules from the parent type
-   * when required.
-   *
-   * @throws Exception
-   *           If the test failed unexpectedly.
-   */
-  @Test(dependsOnMethods = "testConstructorMatchingRules")
-  public void testConstructorInheritsMatchingRules() throws Exception
-  {
-    AttributeType parent = schema.getAttributeType("1.2.5");
-
-    AttributeType child = schema.getAttributeType("1.2.6");
-
-    Assert.assertEquals(parent.getApproximateMatchingRule(), child
-        .getApproximateMatchingRule());
-    Assert.assertEquals(parent.getEqualityMatchingRule(), child
-        .getEqualityMatchingRule());
-    // It should inherit ordering rule from parent's syntax since parent
-    // didn't specify an ordering matching rule.
-    Assert.assertEquals(parent.getSyntax().getOrderingMatchingRule(),
-        child.getOrderingMatchingRule());
-    Assert.assertEquals(parent.getSubstringMatchingRule(), child
-        .getSubstringMatchingRule());
+    // directoryOperation can't inherit from userApplications
+    final SchemaBuilder builder = new SchemaBuilder(schema);
+    builder.addAttributeType("(1.2.8.5 NAME 'testtype' DESC 'full type' "
+        + " OBSOLETE SUP 1.2.1 "
+        + " EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch"
+        + " SUBSTR caseIgnoreSubstringsMatch"
+        + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
+        + " NO-USER-MODIFICATION USAGE directoryOperation )", false);
+    Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
   }
 
 
@@ -510,6 +539,28 @@
 
 
   /**
+   * Check that the {@link CommonSchemaElements#isObsolete()} method.
+   *
+   * @throws Exception
+   *           If the test failed unexpectedly.
+   */
+  @Test
+  public final void testIsObsolete() throws Exception
+  {
+    AttributeType d = schema.getAttributeType("1.2.3");
+    Assert.assertFalse(d.isObsolete());
+    d = schema.getAttributeType("1.2.4");
+    Assert.assertFalse(d.isObsolete());
+
+    d = schema.getAttributeType("1.2.1");
+    Assert.assertTrue(d.isObsolete());
+    d = schema.getAttributeType("1.2.2");
+    Assert.assertTrue(d.isObsolete());
+  }
+
+
+
+  /**
    * Check that the {@link AttributeType#isSingleValue()} method.
    *
    * @throws Exception
@@ -531,90 +582,38 @@
 
 
   /**
-   * Check that the {@link AttributeType#getUsage()} method.
+   * Check that the simple constructor throws an NPE when mandatory parameters
+   * are not specified.
    *
    * @throws Exception
    *           If the test failed unexpectedly.
    */
-  @Test
-  public void testGetAttributeUsage() throws Exception
+  @Test(expectedExceptions = IllegalArgumentException.class)
+  public void testNoSupNorSyntax1() throws Exception
   {
-    AttributeType type = schema.getAttributeType("1.2.1");
-    Assert.assertEquals(type.getUsage(),
-        AttributeUsage.USER_APPLICATIONS);
-    type = schema.getAttributeType("1.2.6");
-    Assert.assertEquals(type.getUsage(), AttributeUsage.DSA_OPERATION);
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addAttributeType("1.2.1", EMPTY_NAMES, "", true, null, null, null,
+        null, null, null, false, false, false, AttributeUsage.DSA_OPERATION,
+        EMPTY_PROPS, false);
+    builder.addAttributeType(
+        "( 1.2.2 OBSOLETE SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )",
+        false);
   }
 
 
 
   /**
-   * Check that the {@link AttributeType#getSuperiorType()} method.
+   * Check that the simple constructor throws an NPE when mandatory parameters
+   * are not specified.
    *
    * @throws Exception
    *           If the test failed unexpectedly.
    */
-  @Test
-  public void testGetSuperiorType() throws Exception
+  @Test(expectedExceptions = IllegalArgumentException.class)
+  public void testNoSupNorSyntax2() throws Exception
   {
-    AttributeType type = schema.getAttributeType("1.2.3");
-    Assert.assertEquals(type.getSuperiorType().getOID(), "1.2.2");
-    type = schema.getAttributeType("1.2.4");
-    Assert.assertEquals(type.getSuperiorType().getOID(), "1.2.3");
-  }
-
-
-
-  @Test
-  public void testInheritFromNonCollective() throws Exception
-  {
-    // Collective can't inherit from non-collective
-    SchemaBuilder builder = new SchemaBuilder(schema);
-    builder
-        .addAttributeType(
-            "(1.2.8.5 NAME 'testtype' DESC 'full type' "
-                + " OBSOLETE SUP 1.2.5 "
-                + " EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch"
-                + " SUBSTR caseIgnoreSubstringsMatch"
-                + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
-                + " COLLECTIVE USAGE userApplications )", false);
-    Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
-  }
-
-
-
-  @Test
-  public void testCollectiveOperational() throws Exception
-  {
-    // Collective can't be operational
-    SchemaBuilder builder = new SchemaBuilder(schema);
-    builder
-        .addAttributeType(
-            "(1.2.8.5 NAME 'testtype' DESC 'full type' OBSOLETE "
-                + " EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch"
-                + " SUBSTR caseIgnoreSubstringsMatch"
-                + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
-                + " COLLECTIVE USAGE directoryOperation )", false);
-    Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
-  }
-
-
-
-  @Test
-  public void testInheritFromUserAppUsage() throws Exception
-  {
-    // directoryOperation can't inherit from userApplications
-    SchemaBuilder builder = new SchemaBuilder(schema);
-    builder
-        .addAttributeType(
-            "(1.2.8.5 NAME 'testtype' DESC 'full type' "
-                + " OBSOLETE SUP 1.2.1 "
-                + " EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch"
-                + " SUBSTR caseIgnoreSubstringsMatch"
-                + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
-                + " NO-USER-MODIFICATION USAGE directoryOperation )",
-            false);
-    Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addAttributeType("( 1.2.2 OBSOLETE SINGLE-VALUE )", false);
   }
 
 
@@ -623,50 +622,27 @@
   public void testNoUserModNonOperational() throws Exception
   {
     // NO-USER-MODIFICATION can't have non-operational usage
-    SchemaBuilder builder = new SchemaBuilder(schema);
-    builder
-        .addAttributeType(
-            "(1.2.8.5 NAME 'testtype' DESC 'full type' OBSOLETE "
-                + " EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch"
-                + " SUBSTR caseIgnoreSubstringsMatch"
-                + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
-                + " NO-USER-MODIFICATION USAGE userApplications )",
-            false);
+    final SchemaBuilder builder = new SchemaBuilder(schema);
+    builder.addAttributeType(
+        "(1.2.8.5 NAME 'testtype' DESC 'full type' OBSOLETE "
+            + " EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch"
+            + " SUBSTR caseIgnoreSubstringsMatch"
+            + " SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE"
+            + " NO-USER-MODIFICATION USAGE userApplications )", false);
     Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
   }
 
 
 
-  @Test
-  public void testADSyntax() throws Exception
+  protected SchemaElement getElement(final String description,
+      final Map<String, List<String>> extraProperties) throws SchemaException
   {
-    // AD uses single quotes around OIDs
-    SchemaBuilder builder = new SchemaBuilder(schema);
-    builder
-        .addAttributeType(
-            "(1.2.8.5 NAME 'testtype' DESC 'full type' "
-                + " SUP '1.2.5' "
-                + " EQUALITY 'caseIgnoreMatch' "
-                + " SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' USAGE dSAOperation )",
-            false);
-    Assert.assertTrue(builder.toSchema().getWarnings().isEmpty());
-  }
-
-
-
-  @Test(expectedExceptions = LocalizedIllegalArgumentException.class)
-  public void testADSyntaxQuoteMismatch() throws Exception
-  {
-    // AD uses single quotes around OIDs
-    SchemaBuilder builder = new SchemaBuilder(schema);
-    builder
-        .addAttributeType(
-            "(1.2.8.5 NAME 'testtype' DESC 'full type' "
-                + " SUP '1.2.5 "
-                + " EQUALITY 'caseIgnoreMatch' "
-                + " SYNTAX '1.3.6.1.4.1.1466.115.121.1.15' USAGE dSAOperation )",
-            false);
-    Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addAttributeType("1.2.3", Collections.singletonList("testType"),
+        description, false, null, null, null, null, null,
+        "1.3.6.1.4.1.1466.115.121.1.27", false, false, false,
+        AttributeUsage.DSA_OPERATION, extraProperties, false);
+    return builder.toSchema().getAttributeType("1.2.3");
   }
 
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleTest.java
index 2afa9ec..0c6df99 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleTest.java
@@ -47,8 +47,8 @@
   @DataProvider(name = "matchingRuleInvalidAttributeValues")
   public Object[][] createMatchingRuleInvalidAttributeValues()
   {
-    return new Object[][] { { "\'a\'B" }, { "0" }, { "010101" },
-        { "\'10101" }, { "\'1010\'A" }, };
+    return new Object[][] { { "\'a\'B" }, { "0" }, { "010101" }, { "\'10101" },
+        { "\'1010\'A" }, };
   }
 
 
@@ -60,8 +60,7 @@
   @DataProvider(name = "matchingrules")
   public Object[][] createMatchingRuleTest()
   {
-    return new Object[][] {
-        { "\'0\'B", "\'0\'B", ConditionResult.TRUE },
+    return new Object[][] { { "\'0\'B", "\'0\'B", ConditionResult.TRUE },
         { "\'1\'B", "\'1\'B", ConditionResult.TRUE },
         { "\'0\'B", "\'1\'B", ConditionResult.FALSE }, };
   }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringSyntaxTest.java
index 1d02df6..9c3bcf3 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringSyntaxTest.java
@@ -43,9 +43,12 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
+  @DataProvider(name = "acceptableValues")
+  public Object[][] createAcceptableValues()
   {
-    return Schema.getCoreSchema().getSyntax(SYNTAX_BIT_STRING_OID);
+    return new Object[][] { { "'0101'B", true }, { "'1'B", true },
+        { "'0'B", true }, { "invalid", false }, { "1", false },
+        { "'010100000111111010101000'B", true }, };
   }
 
 
@@ -54,11 +57,8 @@
    * {@inheritDoc}
    */
   @Override
-  @DataProvider(name = "acceptableValues")
-  public Object[][] createAcceptableValues()
+  protected Syntax getRule()
   {
-    return new Object[][] { { "'0101'B", true }, { "'1'B", true },
-        { "'0'B", true }, { "invalid", false }, { "1", false },
-        { "'010100000111111010101000'B", true }, };
+    return Schema.getCoreSchema().getSyntax(SYNTAX_BIT_STRING_OID);
   }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleTest.java
index 202e3c0..0a5c047 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleTest.java
@@ -45,6 +45,18 @@
    * {@inheritDoc}
    */
   @Override
+  @DataProvider(name = "matchingRuleInvalidAttributeValues")
+  public Object[][] createMatchingRuleInvalidAttributeValues()
+  {
+    return new Object[][] { { "garbage" }, };
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
   @DataProvider(name = "matchingrules")
   public Object[][] createMatchingRuleTest()
   {
@@ -65,18 +77,6 @@
    * {@inheritDoc}
    */
   @Override
-  @DataProvider(name = "matchingRuleInvalidAttributeValues")
-  public Object[][] createMatchingRuleInvalidAttributeValues()
-  {
-    return new Object[][] { { "garbage" }, };
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
   protected MatchingRule getRule()
   {
     return Schema.getCoreSchema().getMatchingRule(EMR_BOOLEAN_OID);
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleTest.java
index 238b655..25872cb 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleTest.java
@@ -60,14 +60,12 @@
   @DataProvider(name = "matchingrules")
   public Object[][] createMatchingRuleTest()
   {
-    return new Object[][] {
-        { "12345678", "12345678", ConditionResult.TRUE },
+    return new Object[][] { { "12345678", "12345678", ConditionResult.TRUE },
         { "12345678\u2163", "12345678\u2163", ConditionResult.TRUE },
         { "ABC45678", "ABC45678", ConditionResult.TRUE },
         { "  ABC45678  ", "ABC45678", ConditionResult.TRUE },
         { "ABC   45678", "ABC 45678", ConditionResult.TRUE },
-        { "   ", " ", ConditionResult.TRUE },
-        { "", "", ConditionResult.TRUE },
+        { "   ", " ", ConditionResult.TRUE }, { "", "", ConditionResult.TRUE },
         { "ABC45678", "abc45678", ConditionResult.FALSE }, };
   }
 
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleTest.java
index e1115c5..d83123d 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleTest.java
@@ -38,8 +38,7 @@
 /**
  * Test the CaseExactIA5EqualityMatchingRule.
  */
-public class CaseExactIA5EqualityMatchingRuleTest extends
-    MatchingRuleTest
+public class CaseExactIA5EqualityMatchingRuleTest extends MatchingRuleTest
 {
 
   /**
@@ -61,12 +60,10 @@
   @DataProvider(name = "matchingrules")
   public Object[][] createMatchingRuleTest()
   {
-    return new Object[][] {
-        { "12345678", "12345678", ConditionResult.TRUE },
+    return new Object[][] { { "12345678", "12345678", ConditionResult.TRUE },
         { "ABC45678", "ABC45678", ConditionResult.TRUE },
         { "ABC45678", "abc45678", ConditionResult.FALSE },
-        { "\u0020foo\u0020bar\u0020\u0020", "foo bar",
-            ConditionResult.TRUE },
+        { "\u0020foo\u0020bar\u0020\u0020", "foo bar", ConditionResult.TRUE },
         { "test\u00AD\u200D", "test", ConditionResult.TRUE },
         { "foo\u000Bbar", "foo\u0020bar", ConditionResult.TRUE },
         { "foo\u070Fbar", "foobar", ConditionResult.TRUE },
@@ -82,8 +79,7 @@
   @Override
   protected MatchingRule getRule()
   {
-    return Schema.getCoreSchema().getMatchingRule(
-        EMR_CASE_EXACT_IA5_OID);
+    return Schema.getCoreSchema().getMatchingRule(EMR_CASE_EXACT_IA5_OID);
   }
 
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleTest.java
index d1deafc..72a5cb5 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleTest.java
@@ -42,41 +42,22 @@
     SubstringMatchingRuleTest
 {
 
-  /**
-   * {@inheritDoc}
-   */
   @Override
-  @DataProvider(name = "substringMiddleMatchData")
-  public Object[][] createSubstringMiddleMatchData()
+  @DataProvider(name = "substringInvalidAssertionValues")
+  public Object[][] createMatchingRuleInvalidAssertionValues()
   {
-    return new Object[][] {
-        { "this is a value", new String[] { "this" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "is" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "a" }, ConditionResult.TRUE },
-        { "this is a value", new String[] { "value" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { " " }, ConditionResult.TRUE },
-        { "this is a value",
-            new String[] { "this", "is", "a", "value" },
-            ConditionResult.TRUE },
-        // The matching rule requires ordered non overlapping substrings
-        // Issue #730 was not valid.
-        { "this is a value", new String[] { "value", "this" },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "this", "this is" },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "his is", "a val", },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "not", },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "THIS", },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "this", "not" },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "    " },
-            ConditionResult.TRUE }, };
+    return new Object[][] { { "12345678\uFFFD", new String[0], null },
+        { null, new String[] { "12345678\uFFFD" }, null },
+        { null, new String[0], "12345678\uFFFD" }, };
+  }
+
+
+
+  @Override
+  @DataProvider(name = "substringInvalidAttributeValues")
+  public Object[][] createMatchingRuleInvalidAttributeValues()
+  {
+    return new Object[][] { { "12345678\uFFFD" }, };
   }
 
 
@@ -85,10 +66,21 @@
    * {@inheritDoc}
    */
   @Override
-  protected MatchingRule getRule()
+  @DataProvider(name = "substringFinalMatchData")
+  public Object[][] createSubstringFinalMatchData()
   {
-    return Schema.getCoreSchema().getMatchingRule(
-        SMR_CASE_EXACT_IA5_OID);
+    return new Object[][] {
+        { "this is a value", "value", ConditionResult.TRUE },
+        { "this is a value", "alue", ConditionResult.TRUE },
+        { "this is a value", "ue", ConditionResult.TRUE },
+        { "this is a value", "e", ConditionResult.TRUE },
+        { "this is a value", "valu", ConditionResult.FALSE },
+        { "this is a value", "this", ConditionResult.FALSE },
+        { "this is a value", " ", ConditionResult.FALSE },
+        { "this is a value", "VALUE", ConditionResult.FALSE },
+        { "this is a VALUE", "value", ConditionResult.FALSE },
+        { "end with space    ", " ", ConditionResult.FALSE },
+        { "end with space    ", "space", ConditionResult.TRUE }, };
   }
 
 
@@ -118,38 +110,40 @@
    * {@inheritDoc}
    */
   @Override
-  @DataProvider(name = "substringFinalMatchData")
-  public Object[][] createSubstringFinalMatchData()
+  @DataProvider(name = "substringMiddleMatchData")
+  public Object[][] createSubstringMiddleMatchData()
   {
     return new Object[][] {
-        { "this is a value", "value", ConditionResult.TRUE },
-        { "this is a value", "alue", ConditionResult.TRUE },
-        { "this is a value", "ue", ConditionResult.TRUE },
-        { "this is a value", "e", ConditionResult.TRUE },
-        { "this is a value", "valu", ConditionResult.FALSE },
-        { "this is a value", "this", ConditionResult.FALSE },
-        { "this is a value", " ", ConditionResult.FALSE },
-        { "this is a value", "VALUE", ConditionResult.FALSE },
-        { "this is a VALUE", "value", ConditionResult.FALSE },
-        { "end with space    ", " ", ConditionResult.FALSE },
-        { "end with space    ", "space", ConditionResult.TRUE }, };
+        { "this is a value", new String[] { "this" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "is" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "a" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "value" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { " " }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "this", "is", "a", "value" },
+            ConditionResult.TRUE },
+        // The matching rule requires ordered non overlapping substrings
+        // Issue #730 was not valid.
+        { "this is a value", new String[] { "value", "this" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "this", "this is" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "his is", "a val", },
+            ConditionResult.TRUE },
+        { "this is a value", new String[] { "not", }, ConditionResult.FALSE },
+        { "this is a value", new String[] { "THIS", }, ConditionResult.FALSE },
+        { "this is a value", new String[] { "this", "not" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "    " }, ConditionResult.TRUE }, };
   }
 
 
 
-  @DataProvider(name = "substringInvalidAttributeValues")
-  public Object[][] createMatchingRuleInvalidAttributeValues()
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected MatchingRule getRule()
   {
-    return new Object[][] { { "12345678\uFFFD" }, };
-  }
-
-
-
-  @DataProvider(name = "substringInvalidAssertionValues")
-  public Object[][] createMatchingRuleInvalidAssertionValues()
-  {
-    return new Object[][] { { "12345678\uFFFD", new String[0], null },
-        { null, new String[] { "12345678\uFFFD" }, null },
-        { null, new String[0], "12345678\uFFFD" }, };
+    return Schema.getCoreSchema().getMatchingRule(SMR_CASE_EXACT_IA5_OID);
   }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleTest.java
index 3cf2507..e119462 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleTest.java
@@ -37,8 +37,7 @@
 /**
  * Test the CaseExactOrderingMatchingRule.
  */
-public class CaseExactOrderingMatchingRuleTest extends
-    OrderingMatchingRuleTest
+public class CaseExactOrderingMatchingRuleTest extends OrderingMatchingRuleTest
 {
 
   /**
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleTest.java
index decbbcc..70bf2f7 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleTest.java
@@ -42,42 +42,20 @@
     SubstringMatchingRuleTest
 {
 
-  /**
-   * {@inheritDoc}
-   */
   @Override
-  @DataProvider(name = "substringMiddleMatchData")
-  public Object[][] createSubstringMiddleMatchData()
+  @DataProvider(name = "substringInvalidAssertionValues")
+  public Object[][] createMatchingRuleInvalidAssertionValues()
   {
-    return new Object[][] {
-        { "this is a value", new String[] { "this" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "is" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "a" }, ConditionResult.TRUE },
-        { "this is a value", new String[] { "value" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { " " }, ConditionResult.TRUE },
-        { "this is a value",
-            new String[] { "this", "is", "a", "value" },
-            ConditionResult.TRUE },
-        // The matching rule requires ordered non overlapping
-        // substrings.
-        // Issue #730 was not valid.
-        { "this is a value", new String[] { "value", "this" },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "this", "this is" },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "his is", "a val", },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "not", },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "THIS", },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "this", "not" },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "    " },
-            ConditionResult.TRUE }, };
+    return new Object[][] {};
+  }
+
+
+
+  @Override
+  @DataProvider(name = "substringInvalidAttributeValues")
+  public Object[][] createMatchingRuleInvalidAttributeValues()
+  {
+    return new Object[][] {};
   }
 
 
@@ -86,9 +64,21 @@
    * {@inheritDoc}
    */
   @Override
-  protected MatchingRule getRule()
+  @DataProvider(name = "substringFinalMatchData")
+  public Object[][] createSubstringFinalMatchData()
   {
-    return Schema.getCoreSchema().getMatchingRule(SMR_CASE_EXACT_OID);
+    return new Object[][] {
+        { "this is a value", "value", ConditionResult.TRUE },
+        { "this is a value", "alue", ConditionResult.TRUE },
+        { "this is a value", "ue", ConditionResult.TRUE },
+        { "this is a value", "e", ConditionResult.TRUE },
+        { "this is a value", "valu", ConditionResult.FALSE },
+        { "this is a value", "this", ConditionResult.FALSE },
+        { "this is a value", " ", ConditionResult.FALSE },
+        { "this is a value", "VALUE", ConditionResult.FALSE },
+        { "this is a VALUE", "value", ConditionResult.FALSE },
+        { "end with space    ", " ", ConditionResult.FALSE },
+        { "end with space    ", "space", ConditionResult.TRUE }, };
   }
 
 
@@ -118,37 +108,42 @@
    * {@inheritDoc}
    */
   @Override
-  @DataProvider(name = "substringFinalMatchData")
-  public Object[][] createSubstringFinalMatchData()
+  @DataProvider(name = "substringMiddleMatchData")
+  public Object[][] createSubstringMiddleMatchData()
   {
     return new Object[][] {
-        { "this is a value", "value", ConditionResult.TRUE },
-        { "this is a value", "alue", ConditionResult.TRUE },
-        { "this is a value", "ue", ConditionResult.TRUE },
-        { "this is a value", "e", ConditionResult.TRUE },
-        { "this is a value", "valu", ConditionResult.FALSE },
-        { "this is a value", "this", ConditionResult.FALSE },
-        { "this is a value", " ", ConditionResult.FALSE },
-        { "this is a value", "VALUE", ConditionResult.FALSE },
-        { "this is a VALUE", "value", ConditionResult.FALSE },
-        { "end with space    ", " ", ConditionResult.FALSE },
-        { "end with space    ", "space", ConditionResult.TRUE }, };
+        { "this is a value", new String[] { "this" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "is" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "a" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "value" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { " " }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "this", "is", "a", "value" },
+            ConditionResult.TRUE },
+        // The matching rule requires ordered non overlapping
+        // substrings.
+        // Issue #730 was not valid.
+        { "this is a value", new String[] { "value", "this" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "this", "this is" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "his is", "a val", },
+            ConditionResult.TRUE },
+        { "this is a value", new String[] { "not", }, ConditionResult.FALSE },
+        { "this is a value", new String[] { "THIS", }, ConditionResult.FALSE },
+        { "this is a value", new String[] { "this", "not" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "    " }, ConditionResult.TRUE }, };
   }
 
 
 
-  @DataProvider(name = "substringInvalidAttributeValues")
-  public Object[][] createMatchingRuleInvalidAttributeValues()
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected MatchingRule getRule()
   {
-    return new Object[][] {};
-  }
-
-
-
-  @DataProvider(name = "substringInvalidAssertionValues")
-  public Object[][] createMatchingRuleInvalidAssertionValues()
-  {
-    return new Object[][] {};
+    return Schema.getCoreSchema().getMatchingRule(SMR_CASE_EXACT_OID);
   }
 
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleTest.java
index 1fddb88..322b711 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleTest.java
@@ -38,8 +38,7 @@
 /**
  * Test the CaseIgnoreEqualityMatchingRule.
  */
-public class CaseIgnoreEqualityMatchingRuleTest extends
-    MatchingRuleTest
+public class CaseIgnoreEqualityMatchingRuleTest extends MatchingRuleTest
 {
   /**
    * {@inheritDoc}
@@ -67,8 +66,7 @@
         { "    ", " ", ConditionResult.TRUE },
         { "Z", "z", ConditionResult.TRUE },
         { "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890",
-            "abcdefghijklmnopqrstuvwxyz1234567890",
-            ConditionResult.TRUE },
+            "abcdefghijklmnopqrstuvwxyz1234567890", ConditionResult.TRUE },
         { "foo\u0020bar\u0020\u0020", "foo bar", ConditionResult.TRUE },
         { "test\u00AD\u200D", "test", ConditionResult.TRUE },
         { "foo\u070Fbar", "foobar", ConditionResult.TRUE },
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleTest.java
index 5d99968..d5f298f 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleTest.java
@@ -38,8 +38,7 @@
 /**
  * Test the CaseExactIA5EqualityMatchingRule.
  */
-public class CaseIgnoreIA5EqualityMatchingRuleTest extends
-    MatchingRuleTest
+public class CaseIgnoreIA5EqualityMatchingRuleTest extends MatchingRuleTest
 {
 
   /**
@@ -61,8 +60,7 @@
   @DataProvider(name = "matchingrules")
   public Object[][] createMatchingRuleTest()
   {
-    return new Object[][] {
-        { "12345678", "12345678", ConditionResult.TRUE },
+    return new Object[][] { { "12345678", "12345678", ConditionResult.TRUE },
         { "ABC45678", "ABC45678", ConditionResult.TRUE },
         { "ABC45678", "abc45678", ConditionResult.TRUE }, };
   }
@@ -75,8 +73,7 @@
   @Override
   protected MatchingRule getRule()
   {
-    return Schema.getCoreSchema().getMatchingRule(
-        EMR_CASE_IGNORE_IA5_OID);
+    return Schema.getCoreSchema().getMatchingRule(EMR_CASE_IGNORE_IA5_OID);
   }
 
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java
index 33a8b6e..5757c14 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java
@@ -42,87 +42,20 @@
     SubstringMatchingRuleTest
 {
 
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  @DataProvider(name = "substringMiddleMatchData")
-  public Object[][] createSubstringMiddleMatchData()
+  @DataProvider(name = "substringInvalidAssertionValues")
+  public Object[][] createMatchingRuleInvalidAssertionValues()
   {
-    return new Object[][] {
-        { "this is a value", new String[] { "this" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "is" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "a" }, ConditionResult.TRUE },
-        { "this is a value", new String[] { "value" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "THIS" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "IS" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "A" }, ConditionResult.TRUE },
-        { "this is a value", new String[] { "VALUE" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { " " }, ConditionResult.TRUE },
-        { "this is a value",
-            new String[] { "this", "is", "a", "value" },
-            ConditionResult.TRUE },
-        // The matching rule requires ordered non overlapping
-        // substrings.
-        // Issue #730 was not valid.
-        { "this is a value", new String[] { "value", "this" },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "this", "this is" },
-            ConditionResult.FALSE },
-        { "this is a value",
-            new String[] { "this", "IS", "a", "VALue" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "his IS", "A val", },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "not", },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "this", "not" },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "    " },
-            ConditionResult.TRUE }, };
+    return new Object[][] { { "12345678\uFFFD", new String[0], null },
+        { null, new String[] { "12345678\uFFFD" }, null },
+        { null, new String[0], "12345678\uFFFD" }, };
   }
 
 
 
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected MatchingRule getRule()
+  @DataProvider(name = "substringInvalidAttributeValues")
+  public Object[][] createMatchingRuleInvalidAttributeValues()
   {
-    return Schema.getCoreSchema().getMatchingRule(
-        SMR_CASE_IGNORE_IA5_OID);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  @DataProvider(name = "substringInitialMatchData")
-  public Object[][] createSubstringInitialMatchData()
-  {
-    return new Object[][] {
-        { "this is a value", "this", ConditionResult.TRUE },
-        { "this is a value", "th", ConditionResult.TRUE },
-        { "this is a value", "t", ConditionResult.TRUE },
-        { "this is a value", "is", ConditionResult.FALSE },
-        { "this is a value", "a", ConditionResult.FALSE },
-        { "this is a value", "TH", ConditionResult.TRUE },
-        { "this is a value", "T", ConditionResult.TRUE },
-        { "this is a value", "IS", ConditionResult.FALSE },
-        { "this is a value", "A", ConditionResult.FALSE },
-        { "this is a value", "VALUE", ConditionResult.FALSE },
-        { "this is a value", " ", ConditionResult.FALSE },
-        { "this is a value", "NOT", ConditionResult.FALSE },
-        { "this is a value", "THIS", ConditionResult.TRUE }, };
+    return new Object[][] { { "12345678\uFFFD" }, };
   }
 
 
@@ -156,19 +89,75 @@
 
 
 
-  @DataProvider(name = "substringInvalidAttributeValues")
-  public Object[][] createMatchingRuleInvalidAttributeValues()
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  @DataProvider(name = "substringInitialMatchData")
+  public Object[][] createSubstringInitialMatchData()
   {
-    return new Object[][] { { "12345678\uFFFD" }, };
+    return new Object[][] {
+        { "this is a value", "this", ConditionResult.TRUE },
+        { "this is a value", "th", ConditionResult.TRUE },
+        { "this is a value", "t", ConditionResult.TRUE },
+        { "this is a value", "is", ConditionResult.FALSE },
+        { "this is a value", "a", ConditionResult.FALSE },
+        { "this is a value", "TH", ConditionResult.TRUE },
+        { "this is a value", "T", ConditionResult.TRUE },
+        { "this is a value", "IS", ConditionResult.FALSE },
+        { "this is a value", "A", ConditionResult.FALSE },
+        { "this is a value", "VALUE", ConditionResult.FALSE },
+        { "this is a value", " ", ConditionResult.FALSE },
+        { "this is a value", "NOT", ConditionResult.FALSE },
+        { "this is a value", "THIS", ConditionResult.TRUE }, };
   }
 
 
 
-  @DataProvider(name = "substringInvalidAssertionValues")
-  public Object[][] createMatchingRuleInvalidAssertionValues()
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  @DataProvider(name = "substringMiddleMatchData")
+  public Object[][] createSubstringMiddleMatchData()
   {
-    return new Object[][] { { "12345678\uFFFD", new String[0], null },
-        { null, new String[] { "12345678\uFFFD" }, null },
-        { null, new String[0], "12345678\uFFFD" }, };
+    return new Object[][] {
+        { "this is a value", new String[] { "this" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "is" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "a" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "value" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "THIS" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "IS" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "A" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "VALUE" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { " " }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "this", "is", "a", "value" },
+            ConditionResult.TRUE },
+        // The matching rule requires ordered non overlapping
+        // substrings.
+        // Issue #730 was not valid.
+        { "this is a value", new String[] { "value", "this" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "this", "this is" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "this", "IS", "a", "VALue" },
+            ConditionResult.TRUE },
+        { "this is a value", new String[] { "his IS", "A val", },
+            ConditionResult.TRUE },
+        { "this is a value", new String[] { "not", }, ConditionResult.FALSE },
+        { "this is a value", new String[] { "this", "not" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "    " }, ConditionResult.TRUE }, };
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected MatchingRule getRule()
+  {
+    return Schema.getCoreSchema().getMatchingRule(SMR_CASE_IGNORE_IA5_OID);
   }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleTest.java
index 3efdef70..e9ef68e 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleTest.java
@@ -62,8 +62,7 @@
   {
     return new Object[][] { { "12345678", "02345678", 1 },
         { "abcdef", "bcdefa", -1 }, { "abcdef", "abcdef", 0 },
-        { "abcdef", "ABCDEF", 0 },
-        { "abcdef", "aCcdef", -1 },
+        { "abcdef", "ABCDEF", 0 }, { "abcdef", "aCcdef", -1 },
         { "aCcdef", "abcdef", 1 },
         { "foo\u0020bar\u0020\u0020", "foo bar", 0 },
         { "test\u00AD\u200D", "test", 0 },
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleTest.java
index 7826ece..257a1b8 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleTest.java
@@ -42,86 +42,18 @@
     SubstringMatchingRuleTest
 {
 
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  @DataProvider(name = "substringMiddleMatchData")
-  public Object[][] createSubstringMiddleMatchData()
+  @DataProvider(name = "substringInvalidAssertionValues")
+  public Object[][] createMatchingRuleInvalidAssertionValues()
   {
-    return new Object[][] {
-        { "this is a value", new String[] { "this" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "is" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "a" }, ConditionResult.TRUE },
-        { "this is a value", new String[] { "value" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "THIS" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "IS" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "A" }, ConditionResult.TRUE },
-        { "this is a value", new String[] { "VALUE" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { " " }, ConditionResult.TRUE },
-        { "this is a value",
-            new String[] { "this", "is", "a", "value" },
-            ConditionResult.TRUE },
-        // The matching rule requires ordered non overlapping
-        // substrings.
-        // Issue #730 was not valid.
-        { "this is a value", new String[] { "value", "this" },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "this", "this is" },
-            ConditionResult.FALSE },
-        { "this is a value",
-            new String[] { "this", "IS", "a", "VALue" },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "his IS", "A val", },
-            ConditionResult.TRUE },
-        { "this is a value", new String[] { "not", },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "this", "not" },
-            ConditionResult.FALSE },
-        { "this is a value", new String[] { "    " },
-            ConditionResult.TRUE }, };
+    return new Object[][] {};
   }
 
 
 
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected MatchingRule getRule()
+  @DataProvider(name = "substringInvalidAttributeValues")
+  public Object[][] createMatchingRuleInvalidAttributeValues()
   {
-    return Schema.getCoreSchema().getMatchingRule(SMR_CASE_IGNORE_OID);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  @DataProvider(name = "substringInitialMatchData")
-  public Object[][] createSubstringInitialMatchData()
-  {
-    return new Object[][] {
-        { "this is a value", "this", ConditionResult.TRUE },
-        { "this is a value", "th", ConditionResult.TRUE },
-        { "this is a value", "t", ConditionResult.TRUE },
-        { "this is a value", "is", ConditionResult.FALSE },
-        { "this is a value", "a", ConditionResult.FALSE },
-        { "this is a value", "TH", ConditionResult.TRUE },
-        { "this is a value", "T", ConditionResult.TRUE },
-        { "this is a value", "IS", ConditionResult.FALSE },
-        { "this is a value", "A", ConditionResult.FALSE },
-        { "this is a value", "VALUE", ConditionResult.FALSE },
-        { "this is a value", " ", ConditionResult.FALSE },
-        { "this is a value", "NOT", ConditionResult.FALSE },
-        { "this is a value", "THIS", ConditionResult.TRUE }, };
+    return new Object[][] {};
   }
 
 
@@ -155,17 +87,75 @@
 
 
 
-  @DataProvider(name = "substringInvalidAttributeValues")
-  public Object[][] createMatchingRuleInvalidAttributeValues()
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  @DataProvider(name = "substringInitialMatchData")
+  public Object[][] createSubstringInitialMatchData()
   {
-    return new Object[][] {};
+    return new Object[][] {
+        { "this is a value", "this", ConditionResult.TRUE },
+        { "this is a value", "th", ConditionResult.TRUE },
+        { "this is a value", "t", ConditionResult.TRUE },
+        { "this is a value", "is", ConditionResult.FALSE },
+        { "this is a value", "a", ConditionResult.FALSE },
+        { "this is a value", "TH", ConditionResult.TRUE },
+        { "this is a value", "T", ConditionResult.TRUE },
+        { "this is a value", "IS", ConditionResult.FALSE },
+        { "this is a value", "A", ConditionResult.FALSE },
+        { "this is a value", "VALUE", ConditionResult.FALSE },
+        { "this is a value", " ", ConditionResult.FALSE },
+        { "this is a value", "NOT", ConditionResult.FALSE },
+        { "this is a value", "THIS", ConditionResult.TRUE }, };
   }
 
 
 
-  @DataProvider(name = "substringInvalidAssertionValues")
-  public Object[][] createMatchingRuleInvalidAssertionValues()
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  @DataProvider(name = "substringMiddleMatchData")
+  public Object[][] createSubstringMiddleMatchData()
   {
-    return new Object[][] {};
+    return new Object[][] {
+        { "this is a value", new String[] { "this" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "is" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "a" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "value" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "THIS" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "IS" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "A" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "VALUE" }, ConditionResult.TRUE },
+        { "this is a value", new String[] { " " }, ConditionResult.TRUE },
+        { "this is a value", new String[] { "this", "is", "a", "value" },
+            ConditionResult.TRUE },
+        // The matching rule requires ordered non overlapping
+        // substrings.
+        // Issue #730 was not valid.
+        { "this is a value", new String[] { "value", "this" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "this", "this is" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "this", "IS", "a", "VALue" },
+            ConditionResult.TRUE },
+        { "this is a value", new String[] { "his IS", "A val", },
+            ConditionResult.TRUE },
+        { "this is a value", new String[] { "not", }, ConditionResult.FALSE },
+        { "this is a value", new String[] { "this", "not" },
+            ConditionResult.FALSE },
+        { "this is a value", new String[] { "    " }, ConditionResult.TRUE }, };
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected MatchingRule getRule()
+  {
+    return Schema.getCoreSchema().getMatchingRule(SMR_CASE_IGNORE_OID);
   }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/DITContentRuleSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/DITContentRuleSyntaxTest.java
index 12638a3..72fe3e3 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/DITContentRuleSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/DITContentRuleSyntaxTest.java
@@ -39,18 +39,6 @@
  */
 public class DITContentRuleSyntaxTest extends SyntaxTestCase
 {
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected Syntax getRule()
-  {
-    return Schema.getCoreSchema()
-        .getSyntax(SYNTAX_DIT_CONTENT_RULE_OID);
-  }
-
-
-
   @Override
   @DataProvider(name = "acceptableValues")
   public Object[][] createAcceptableValues()
@@ -61,34 +49,44 @@
                 + "( x121Address $ telexNumber ) )", true },
         {
             "( 2.5.6.4 NAME 'full rule' DESC 'rule with all possible fields' "
-                + " OBSOLETE" + " AUX ( posixAccount )"
-                + " MUST ( cn $ sn )" + " MAY ( dc )"
-                + " NOT ( x121Address $ telexNumber ) )", true },
+                + " OBSOLETE" + " AUX ( posixAccount )" + " MUST ( cn $ sn )"
+                + " MAY ( dc )" + " NOT ( x121Address $ telexNumber ) )", true },
         {
             "( 2.5.6.4 NAME 'full rule' DESC 'ommit parenthesis' "
-                + " OBSOLETE" + " AUX posixAccount " + " MUST cn "
-                + " MAY dc " + " NOT x121Address )", true },
+                + " OBSOLETE" + " AUX posixAccount " + " MUST cn " + " MAY dc "
+                + " NOT x121Address )", true },
         {
-            "( 2.5.6.4 NAME 'full rule' DESC 'use numeric OIDs' "
-                + " OBSOLETE" + " AUX 1.3.6.1.1.1.2.0" + " MUST cn "
-                + " MAY dc " + " NOT x121Address )", true },
+            "( 2.5.6.4 NAME 'full rule' DESC 'use numeric OIDs' " + " OBSOLETE"
+                + " AUX 1.3.6.1.1.1.2.0" + " MUST cn " + " MAY dc "
+                + " NOT x121Address )", true },
         {
-            "( 2.5.6.4 NAME 'full rule' DESC 'illegal OIDs' "
-                + " OBSOLETE" + " AUX 2.5.6.." + " MUST cn "
-                + " MAY dc " + " NOT x121Address )", false },
+            "( 2.5.6.4 NAME 'full rule' DESC 'illegal OIDs' " + " OBSOLETE"
+                + " AUX 2.5.6.." + " MUST cn " + " MAY dc "
+                + " NOT x121Address )", false },
         {
-            "( 2.5.6.4 NAME 'full rule' DESC 'illegal OIDs' "
-                + " OBSOLETE" + " AUX 2.5.6.x" + " MUST cn "
-                + " MAY dc " + " NOT x121Address )", false },
+            "( 2.5.6.4 NAME 'full rule' DESC 'illegal OIDs' " + " OBSOLETE"
+                + " AUX 2.5.6.x" + " MUST cn " + " MAY dc "
+                + " NOT x121Address )", false },
         {
             "( 2.5.6.4 NAME 'full rule' DESC 'missing closing parenthesis' "
-                + " OBSOLETE" + " AUX posixAccount" + " MUST cn "
-                + " MAY dc " + " NOT x121Address", false },
+                + " OBSOLETE" + " AUX posixAccount" + " MUST cn " + " MAY dc "
+                + " NOT x121Address", false },
         {
             "( 2.5.6.4 NAME 'full rule' DESC 'extra parameterss' "
-                + " MUST cn "
-                + " X-name ( 'this is an extra parameter' ) )", true },
+                + " MUST cn " + " X-name ( 'this is an extra parameter' ) )",
+            true },
 
     };
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected Syntax getRule()
+  {
+    return Schema.getCoreSchema().getSyntax(SYNTAX_DIT_CONTENT_RULE_OID);
+  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/EnumSyntaxTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/EnumSyntaxTestCase.java
index d20c402..7999b6d 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/EnumSyntaxTestCase.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/EnumSyntaxTestCase.java
@@ -30,14 +30,13 @@
 
 import static org.opends.sdk.schema.SchemaConstants.OMR_OID_GENERIC_ENUM;
 
+import org.opends.sdk.ByteString;
 import org.opends.sdk.ConditionResult;
 import org.opends.sdk.DecodeException;
 import org.testng.Assert;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import org.opends.sdk.ByteString;
-
 
 
 /**
@@ -49,13 +48,72 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule() throws SchemaException, DecodeException
+  @DataProvider(name = "acceptableValues")
+  public Object[][] createAcceptableValues()
   {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addEnumerationSyntax("3.3.3", "Day Of The Week", false, "monday",
-        "tuesday", "wednesday", "thursday", "friday", "saturday",
-        "sunday");
-    return builder.toSchema().getSyntax("3.3.3");
+    return new Object[][] { { "arbit-day", false }, { "wednesday", true }, };
+  }
+
+
+
+  @Test
+  public void testDecode() throws SchemaException, DecodeException
+  {
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addSyntax("( 3.3.3  DESC 'Day Of The Week' "
+        + " X-ENUM  ( 'monday' 'tuesday'   'wednesday'  'thursday'  'friday' "
+        + " 'saturday' 'sunday') )", true);
+    final Schema schema = builder.toSchema();
+    final Syntax syntax = schema.getSyntax("3.3.3");
+    final MatchingRule rule = syntax.getOrderingMatchingRule();
+    Assert.assertEquals(rule.getGreaterOrEqualAssertion(
+        ByteString.valueOf("monday")).matches(
+        rule.normalizeAttributeValue(ByteString.valueOf("thursday"))),
+        ConditionResult.TRUE);
+    Assert.assertEquals(rule.getLessOrEqualAssertion(
+        ByteString.valueOf("monday")).matches(
+        rule.normalizeAttributeValue(ByteString.valueOf("thursday"))),
+        ConditionResult.FALSE);
+    Assert.assertEquals(rule.getGreaterOrEqualAssertion(
+        ByteString.valueOf("tuesday")).matches(
+        rule.normalizeAttributeValue(ByteString.valueOf("monday"))),
+        ConditionResult.FALSE);
+    Assert.assertEquals(rule.getLessOrEqualAssertion(
+        ByteString.valueOf("tuesday")).matches(
+        rule.normalizeAttributeValue(ByteString.valueOf("monday"))),
+        ConditionResult.TRUE);
+    Assert.assertEquals(rule.getGreaterOrEqualAssertion(
+        ByteString.valueOf("tuesday")).matches(
+        rule.normalizeAttributeValue(ByteString.valueOf("tuesday"))),
+        ConditionResult.TRUE);
+    Assert.assertEquals(rule.getLessOrEqualAssertion(
+        ByteString.valueOf("tuesday")).matches(
+        rule.normalizeAttributeValue(ByteString.valueOf("tuesday"))),
+        ConditionResult.TRUE);
+    Assert.assertEquals(rule.getAssertion(ByteString.valueOf("tuesday"))
+        .matches(rule.normalizeAttributeValue(ByteString.valueOf("monday"))),
+        ConditionResult.TRUE);
+    Assert.assertEquals(rule.getAssertion(ByteString.valueOf("monday"))
+        .matches(rule.normalizeAttributeValue(ByteString.valueOf("thursday"))),
+        ConditionResult.FALSE);
+    Assert.assertEquals(rule.getAssertion(ByteString.valueOf("tuesday"))
+        .matches(rule.normalizeAttributeValue(ByteString.valueOf("tuesday"))),
+        ConditionResult.FALSE);
+    Assert.assertNotNull(schema
+        .getMatchingRule(OMR_OID_GENERIC_ENUM + ".3.3.3"));
+  }
+
+
+
+  @Test
+  public void testDuplicateEnum() throws SchemaException, DecodeException
+  {
+    // This should be handled silently.
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addSyntax("( 3.3.3  DESC 'Day Of The Week' "
+        + " X-ENUM  ( 'monday' 'tuesday'   'wednesday'  'thursday'  'friday' "
+        + " 'saturday' 'monday') )", true);
+    builder.toSchema();
   }
 
 
@@ -64,83 +122,11 @@
    * {@inheritDoc}
    */
   @Override
-  @DataProvider(name = "acceptableValues")
-  public Object[][] createAcceptableValues()
+  protected Syntax getRule() throws SchemaException, DecodeException
   {
-    return new Object[][] { { "arbit-day", false },
-        { "wednesday", true }, };
-  }
-
-
-
-  @Test
-  public void testDuplicateEnum() throws SchemaException,
-      DecodeException
-  {
-    // This should be handled silently.
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder
-        .addSyntax(
-            "( 3.3.3  DESC 'Day Of The Week' "
-                + " X-ENUM  ( 'monday' 'tuesday'   'wednesday'  'thursday'  'friday' "
-                + " 'saturday' 'monday') )", true);
-    builder.toSchema();
-  }
-
-
-
-  @Test
-  public void testDecode() throws SchemaException, DecodeException
-  {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder
-        .addSyntax(
-            "( 3.3.3  DESC 'Day Of The Week' "
-                + " X-ENUM  ( 'monday' 'tuesday'   'wednesday'  'thursday'  'friday' "
-                + " 'saturday' 'sunday') )", true);
-    Schema schema = builder.toSchema();
-    Syntax syntax = schema.getSyntax("3.3.3");
-    MatchingRule rule = syntax.getOrderingMatchingRule();
-    Assert.assertEquals(rule.getGreaterOrEqualAssertion(
-        ByteString.valueOf("monday")).matches(
-        rule.normalizeAttributeValue(ByteString.valueOf("thursday"))),
-        ConditionResult.TRUE);
-    Assert.assertEquals(rule.getLessOrEqualAssertion(
-        ByteString.valueOf("monday")).matches(
-        rule.normalizeAttributeValue(ByteString.valueOf("thursday"))),
-        ConditionResult.FALSE);
-    Assert.assertEquals(rule.getGreaterOrEqualAssertion(
-        ByteString.valueOf("tuesday")).matches(
-        rule.normalizeAttributeValue(ByteString.valueOf("monday"))),
-        ConditionResult.FALSE);
-    Assert.assertEquals(rule.getLessOrEqualAssertion(
-        ByteString.valueOf("tuesday")).matches(
-        rule.normalizeAttributeValue(ByteString.valueOf("monday"))),
-        ConditionResult.TRUE);
-    Assert.assertEquals(rule.getGreaterOrEqualAssertion(
-        ByteString.valueOf("tuesday")).matches(
-        rule.normalizeAttributeValue(ByteString.valueOf("tuesday"))),
-        ConditionResult.TRUE);
-    Assert.assertEquals(rule.getLessOrEqualAssertion(
-        ByteString.valueOf("tuesday")).matches(
-        rule.normalizeAttributeValue(ByteString.valueOf("tuesday"))),
-        ConditionResult.TRUE);
-    Assert
-        .assertEquals(rule.getAssertion(ByteString.valueOf("tuesday"))
-            .matches(
-                rule.normalizeAttributeValue(ByteString
-                    .valueOf("monday"))), ConditionResult.TRUE);
-    Assert.assertEquals(
-        rule.getAssertion(ByteString.valueOf("monday"))
-            .matches(
-                rule.normalizeAttributeValue(ByteString
-                    .valueOf("thursday"))), ConditionResult.FALSE);
-    Assert.assertEquals(
-        rule.getAssertion(ByteString.valueOf("tuesday"))
-            .matches(
-                rule.normalizeAttributeValue(ByteString
-                    .valueOf("tuesday"))), ConditionResult.FALSE);
-    Assert.assertNotNull(schema.getMatchingRule(OMR_OID_GENERIC_ENUM
-        + ".3.3.3"));
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addEnumerationSyntax("3.3.3", "Day Of The Week", false, "monday",
+        "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday");
+    return builder.toSchema().getSyntax("3.3.3");
   }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GeneralizedTimeSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GeneralizedTimeSyntaxTest.java
index db991df..b11b2cd 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GeneralizedTimeSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GeneralizedTimeSyntaxTest.java
@@ -28,7 +28,7 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_GENERALIZED_TIME_OID;
 
 import org.testng.annotations.DataProvider;
 
@@ -39,18 +39,6 @@
  */
 public class GeneralizedTimeSyntaxTest extends SyntaxTestCase
 {
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected Syntax getRule()
-  {
-    return Schema.getCoreSchema()
-        .getSyntax(SYNTAX_GENERALIZED_TIME_OID);
-  }
-
-
-
   @Override
   @DataProvider(name = "acceptableValues")
   public Object[][] createAcceptableValues()
@@ -59,10 +47,8 @@
         { "20060906135030+01", true }, { "200609061350Z", true },
         { "20060906135030Z", true }, { "20061116135030Z", true },
         { "20061126135030Z", true }, { "20061231235959Z", true },
-        { "20060906135030+0101", true },
-        { "20060906135030+2359", true },
-        { "20060906135030+3359", false },
-        { "20060906135030+2389", false },
+        { "20060906135030+0101", true }, { "20060906135030+2359", true },
+        { "20060906135030+3359", false }, { "20060906135030+2389", false },
         { "20060906135030+2361", false }, { "20060906135030+", false },
         { "20060906135030+0", false }, { "20060906135030+010", false },
         { "20061200235959Z", false }, { "2006121a235959Z", false },
@@ -74,4 +60,15 @@
         { "2006", false }, };
   }
 
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected Syntax getRule()
+  {
+    return Schema.getCoreSchema().getSyntax(SYNTAX_GENERALIZED_TIME_OID);
+  }
+
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GuideSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GuideSyntaxTest.java
index bb2f4ba..066a26e 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GuideSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GuideSyntaxTest.java
@@ -43,9 +43,17 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
+  @DataProvider(name = "acceptableValues")
+  public Object[][] createAcceptableValues()
   {
-    return Schema.getCoreSchema().getSyntax(SYNTAX_GUIDE_OID);
+    return new Object[][] { { "sn$EQ|!(sn$EQ)", true }, { "!(sn$EQ)", true },
+        { "person#sn$EQ", true }, { "(sn$EQ)", true }, { "sn$EQ", true },
+        { "sn$SUBSTR", true }, { "sn$GE", true }, { "sn$LE", true },
+        { "sn$ME", false }, { "?true", true }, { "?false", true },
+        { "true|sn$GE", false }, { "sn$APPROX", true },
+        { "sn$EQ|(sn$EQ)", true }, { "sn$EQ|(sn$EQ", false },
+        { "sn$EQ|(sn$EQ)|sn$EQ", true }, { "sn$EQ|(cn$APPROX&?false)", true },
+        { "sn$EQ|(cn$APPROX&|?false)", false }, };
   }
 
 
@@ -54,17 +62,8 @@
    * {@inheritDoc}
    */
   @Override
-  @DataProvider(name = "acceptableValues")
-  public Object[][] createAcceptableValues()
+  protected Syntax getRule()
   {
-    return new Object[][] { { "sn$EQ|!(sn$EQ)", true },
-        { "!(sn$EQ)", true }, { "person#sn$EQ", true },
-        { "(sn$EQ)", true }, { "sn$EQ", true }, { "sn$SUBSTR", true },
-        { "sn$GE", true }, { "sn$LE", true }, { "sn$ME", false },
-        { "?true", true }, { "?false", true }, { "true|sn$GE", false },
-        { "sn$APPROX", true }, { "sn$EQ|(sn$EQ)", true },
-        { "sn$EQ|(sn$EQ", false }, { "sn$EQ|(sn$EQ)|sn$EQ", true },
-        { "sn$EQ|(cn$APPROX&?false)", true },
-        { "sn$EQ|(cn$APPROX&|?false)", false }, };
+    return Schema.getCoreSchema().getSyntax(SYNTAX_GUIDE_OID);
   }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/IA5StringSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/IA5StringSyntaxTest.java
index d350d49..44154d8 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/IA5StringSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/IA5StringSyntaxTest.java
@@ -43,9 +43,10 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
+  @DataProvider(name = "acceptableValues")
+  public Object[][] createAcceptableValues()
   {
-    return Schema.getCoreSchema().getSyntax(SYNTAX_IA5_STRING_OID);
+    return new Object[][] { { "12345678", true }, { "12345678\u2163", false }, };
   }
 
 
@@ -54,11 +55,9 @@
    * {@inheritDoc}
    */
   @Override
-  @DataProvider(name = "acceptableValues")
-  public Object[][] createAcceptableValues()
+  protected Syntax getRule()
   {
-    return new Object[][] { { "12345678", true },
-        { "12345678\u2163", false }, };
+    return Schema.getCoreSchema().getSyntax(SYNTAX_IA5_STRING_OID);
   }
 
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/LDAPSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/LDAPSyntaxTest.java
index 6a338e0..b78b12f 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/LDAPSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/LDAPSyntaxTest.java
@@ -43,17 +43,6 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
-  {
-    return Schema.getCoreSchema().getSyntax(SYNTAX_LDAP_SYNTAX_OID);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
   @DataProvider(name = "acceptableValues")
   public Object[][] createAcceptableValues()
   {
@@ -61,20 +50,12 @@
         {
             "( 2.5.4.3 DESC 'full syntax description' "
                 + "X-9EN ('this' 'is' 'a' 'test'))", false },
-        {
-            "( 2.5.4.3 DESC 'full syntax description' "
-                + "(X-name 'this", false },
-        {
-            "( 2.5.4.3 DESC 'full syntax description' "
-                + "(X-name 'this'", false },
-        {
-            "( 2.5.4.3 DESC 'full syntax description' "
-                + "Y-name 'this')", false },
-        {
-            "( 2.5.4.3 DESC 'full syntax description' "
-                + "X-name 'this' 'is')", false },
-        { "( 2.5.4.3 DESC 'full syntax description' " + "X-name )",
+        { "( 2.5.4.3 DESC 'full syntax description' " + "(X-name 'this", false },
+        { "( 2.5.4.3 DESC 'full syntax description' " + "(X-name 'this'", false },
+        { "( 2.5.4.3 DESC 'full syntax description' " + "Y-name 'this')", false },
+        { "( 2.5.4.3 DESC 'full syntax description' " + "X-name 'this' 'is')",
             false },
+        { "( 2.5.4.3 DESC 'full syntax description' " + "X-name )", false },
         {
             "( 2.5.4.3 DESC 'full syntax description' "
                 + "X- ('this' 'is' 'a' 'test'))", false },
@@ -105,12 +86,9 @@
         {
             "( 2.5.4.3 DESC 'full syntax description' "
                 + "X-a-_eN_- ('this' 'is' 'a' 'test'))", true },
-        {
-            "( 2.5.4.3 DESC 'full syntax description' "
-                + "X-name ('this'))", true },
-        {
-            "( 2.5.4.3 DESC 'full syntax description' "
-                + "X-name 'this')", true },
+        { "( 2.5.4.3 DESC 'full syntax description' " + "X-name ('this'))",
+            true },
+        { "( 2.5.4.3 DESC 'full syntax description' " + "X-name 'this')", true },
         {
             "( 2.5.4.3 DESC 'full syntax description' "
                 + "X-name 'this' X-name-a 'test')", true },
@@ -122,4 +100,15 @@
         { "2.5.4.3 DESC 'syntax description' )", false },
         { "(2.5.4.3 DESC 'syntax description' ", false }, };
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected Syntax getRule()
+  {
+    return Schema.getCoreSchema().getSyntax(SYNTAX_LDAP_SYNTAX_OID);
+  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleSyntaxTest.java
index df96f25..bed7f0d 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleSyntaxTest.java
@@ -43,17 +43,6 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
-  {
-    return Schema.getCoreSchema().getSyntax(SYNTAX_MATCHING_RULE_OID);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
   @DataProvider(name = "acceptableValues")
   public Object[][] createAcceptableValues()
   {
@@ -70,4 +59,15 @@
                 + " X-name ( 'this is an extension' ) ", false }, };
   }
 
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected Syntax getRule()
+  {
+    return Schema.getCoreSchema().getSyntax(SYNTAX_MATCHING_RULE_OID);
+  }
+
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleTest.java
index 775a2f3..4255e6a 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleTest.java
@@ -31,13 +31,12 @@
 import static org.testng.Assert.assertEquals;
 
 import org.opends.sdk.Assertion;
+import org.opends.sdk.ByteString;
 import org.opends.sdk.ConditionResult;
 import org.opends.sdk.DecodeException;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import org.opends.sdk.ByteString;
-
 
 
 /**
@@ -46,28 +45,8 @@
 public abstract class MatchingRuleTest extends SchemaTestCase
 {
   /**
-   * Generate data for the Matching Rule test.
-   * 
-   * @return the data for the equality matching rule test.
-   */
-  @DataProvider(name = "matchingrules")
-  public abstract Object[][] createMatchingRuleTest();
-
-
-
-  /**
-   * Generate invalid attribute values for the Matching Rule test.
-   * 
-   * @return the data for the EqualityMatchingRulesInvalidValuestest.
-   */
-  @DataProvider(name = "matchingRuleInvalidAttributeValues")
-  public abstract Object[][] createMatchingRuleInvalidAttributeValues();
-
-
-
-  /**
    * Generate invalid assertion values for the Matching Rule test.
-   * 
+   *
    * @return the data for the EqualityMatchingRulesInvalidValuestest.
    */
   @DataProvider(name = "matchingRuleInvalidAssertionValues")
@@ -79,11 +58,22 @@
 
 
   /**
-   * Get an instance of the matching rule.
-   * 
-   * @return An instance of the matching rule to test.
+   * Generate invalid attribute values for the Matching Rule test.
+   *
+   * @return the data for the EqualityMatchingRulesInvalidValuestest.
    */
-  protected abstract MatchingRule getRule();
+  @DataProvider(name = "matchingRuleInvalidAttributeValues")
+  public abstract Object[][] createMatchingRuleInvalidAttributeValues();
+
+
+
+  /**
+   * Generate data for the Matching Rule test.
+   *
+   * @return the data for the equality matching rule test.
+   */
+  @DataProvider(name = "matchingrules")
+  public abstract Object[][] createMatchingRuleTest();
 
 
 
@@ -91,17 +81,17 @@
    * Test the normalization and the comparison of valid values.
    */
   @Test(dataProvider = "matchingrules")
-  public void matchingRules(String value1, String value2,
-      ConditionResult result) throws Exception
+  public void matchingRules(final String value1, final String value2,
+      final ConditionResult result) throws Exception
   {
-    MatchingRule rule = getRule();
+    final MatchingRule rule = getRule();
 
     // normalize the 2 provided values and check that they are equals
-    ByteString normalizedValue1 =
-        rule.normalizeAttributeValue(ByteString.valueOf(value1));
-    Assertion assertion = rule.getAssertion(ByteString.valueOf(value2));
+    final ByteString normalizedValue1 = rule.normalizeAttributeValue(ByteString
+        .valueOf(value1));
+    final Assertion assertion = rule.getAssertion(ByteString.valueOf(value2));
 
-    ConditionResult liveResult = assertion.matches(normalizedValue1);
+    final ConditionResult liveResult = assertion.matches(normalizedValue1);
     assertEquals(result, liveResult);
   }
 
@@ -110,14 +100,14 @@
   /**
    * Test that invalid values are rejected.
    */
-  @Test(expectedExceptions = DecodeException.class, dataProvider = "matchingRuleInvalidAttributeValues")
-  public void matchingRulesInvalidAttributeValues(String value)
+  @Test(expectedExceptions = DecodeException.class, dataProvider = "matchingRuleInvalidAssertionValues")
+  public void matchingRulesInvalidAssertionValues(final String value)
       throws Exception
   {
     // Get the instance of the rule to be tested.
-    MatchingRule rule = getRule();
+    final MatchingRule rule = getRule();
 
-    rule.normalizeAttributeValue(ByteString.valueOf(value));
+    rule.getAssertion(ByteString.valueOf(value));
   }
 
 
@@ -125,13 +115,22 @@
   /**
    * Test that invalid values are rejected.
    */
-  @Test(expectedExceptions = DecodeException.class, dataProvider = "matchingRuleInvalidAssertionValues")
-  public void matchingRulesInvalidAssertionValues(String value)
+  @Test(expectedExceptions = DecodeException.class, dataProvider = "matchingRuleInvalidAttributeValues")
+  public void matchingRulesInvalidAttributeValues(final String value)
       throws Exception
   {
     // Get the instance of the rule to be tested.
-    MatchingRule rule = getRule();
+    final MatchingRule rule = getRule();
 
-    rule.getAssertion(ByteString.valueOf(value));
+    rule.normalizeAttributeValue(ByteString.valueOf(value));
   }
+
+
+
+  /**
+   * Get an instance of the matching rule.
+   *
+   * @return An instance of the matching rule to test.
+   */
+  protected abstract MatchingRule getRule();
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleUseSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleUseSyntaxTest.java
index 54b51e1..28038ed 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleUseSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleUseSyntaxTest.java
@@ -43,10 +43,19 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
+  @DataProvider(name = "acceptableValues")
+  public Object[][] createAcceptableValues()
   {
-    return Schema.getCoreSchema().getSyntax(
-        SYNTAX_MATCHING_RULE_USE_OID);
+    return new Object[][] {
+        {
+            "( 2.5.13.10 NAME 'full matching rule' "
+                + " DESC 'description of matching rule' OBSOLETE "
+                + " APPLIES 2.5.4.3 " + " X-name 'this is an extension' )",
+            true },
+        {
+            "( 2.5.13.10 NAME 'missing closing parenthesis' "
+                + " DESC 'description of matching rule' " + " SYNTAX 2.5.4.3 "
+                + " X-name ( 'this is an extension' ) ", false }, };
   }
 
 
@@ -55,19 +64,8 @@
    * {@inheritDoc}
    */
   @Override
-  @DataProvider(name = "acceptableValues")
-  public Object[][] createAcceptableValues()
+  protected Syntax getRule()
   {
-    return new Object[][] {
-        {
-            "( 2.5.13.10 NAME 'full matching rule' "
-                + " DESC 'description of matching rule' OBSOLETE "
-                + " APPLIES 2.5.4.3 "
-                + " X-name 'this is an extension' )", true },
-        {
-            "( 2.5.13.10 NAME 'missing closing parenthesis' "
-                + " DESC 'description of matching rule' "
-                + " SYNTAX 2.5.4.3 "
-                + " X-name ( 'this is an extension' ) ", false }, };
+    return Schema.getCoreSchema().getSyntax(SYNTAX_MATCHING_RULE_USE_OID);
   }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OrderingMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OrderingMatchingRuleTest.java
index 53444ff..cd8eba9 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OrderingMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OrderingMatchingRuleTest.java
@@ -29,14 +29,13 @@
 
 
 import org.opends.sdk.Assertion;
+import org.opends.sdk.ByteString;
 import org.opends.sdk.ConditionResult;
 import org.opends.sdk.DecodeException;
 import org.testng.Assert;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import org.opends.sdk.ByteString;
-
 
 
 /**
@@ -45,8 +44,18 @@
 public abstract class OrderingMatchingRuleTest extends SchemaTestCase
 {
   /**
+   * Create data for the OrderingMatchingRulesInvalidValues test.
+   *
+   * @return The data for the OrderingMatchingRulesInvalidValues test.
+   */
+  @DataProvider(name = "OrderingMatchingRuleInvalidValues")
+  public abstract Object[][] createOrderingMatchingRuleInvalidValues();
+
+
+
+  /**
    * Create data for the OrderingMatchingRules test.
-   * 
+   *
    * @return The data for the OrderingMatchingRules test.
    */
   @DataProvider(name = "Orderingmatchingrules")
@@ -58,39 +67,39 @@
    * Test the comparison of valid values.
    */
   @Test(dataProvider = "Orderingmatchingrules")
-  public void OrderingMatchingRules(String value1, String value2,
-      int result) throws Exception
+  public void orderingMatchingRules(final String value1, final String value2,
+      final int result) throws Exception
   {
     // Make sure that the specified class can be instantiated as a task.
-    MatchingRule ruleInstance = getRule();
+    final MatchingRule ruleInstance = getRule();
 
-    ByteString normalizedValue1 =
-        ruleInstance
-            .normalizeAttributeValue(ByteString.valueOf(value1));
-    ByteString normalizedValue2 =
-        ruleInstance
-            .normalizeAttributeValue(ByteString.valueOf(value2));
+    final ByteString normalizedValue1 = ruleInstance
+        .normalizeAttributeValue(ByteString.valueOf(value1));
+    final ByteString normalizedValue2 = ruleInstance
+        .normalizeAttributeValue(ByteString.valueOf(value2));
 
     // Test the comparator
-    int comp =
-        ruleInstance.comparator().compare(normalizedValue1,
-            normalizedValue2);
+    final int comp = ruleInstance.comparator().compare(normalizedValue1,
+        normalizedValue2);
     if (comp == 0)
+    {
       Assert.assertEquals(comp, result);
+    }
     else if (comp > 0)
+    {
       Assert.assertTrue(result > 0);
+    }
     else if (comp < 0)
+    {
       Assert.assertTrue(result < 0);
+    }
 
-    Assertion a =
-        ruleInstance.getGreaterOrEqualAssertion(ByteString
-            .valueOf(value2));
+    Assertion a = ruleInstance.getGreaterOrEqualAssertion(ByteString
+        .valueOf(value2));
     Assert.assertEquals(a.matches(normalizedValue1),
         result >= 0 ? ConditionResult.TRUE : ConditionResult.FALSE);
 
-    a =
-        ruleInstance
-            .getLessOrEqualAssertion(ByteString.valueOf(value2));
+    a = ruleInstance.getLessOrEqualAssertion(ByteString.valueOf(value2));
     Assert.assertEquals(a.matches(normalizedValue1),
         result <= 0 ? ConditionResult.TRUE : ConditionResult.FALSE);
 
@@ -102,35 +111,25 @@
 
 
   /**
-   * Get the Ordering matching Rules that is to be tested.
-   * 
-   * @return The Ordering matching Rules that is to be tested.
-   */
-  protected abstract MatchingRule getRule();
-
-
-
-  /**
-   * Create data for the OrderingMatchingRulesInvalidValues test.
-   * 
-   * @return The data for the OrderingMatchingRulesInvalidValues test.
-   */
-  @DataProvider(name = "OrderingMatchingRuleInvalidValues")
-  public abstract Object[][] createOrderingMatchingRuleInvalidValues();
-
-
-
-  /**
    * Test that invalid values are rejected.
    */
   @Test(expectedExceptions = DecodeException.class, dataProvider = "OrderingMatchingRuleInvalidValues")
-  public void OrderingMatchingRulesInvalidValues(String value)
+  public void orderingMatchingRulesInvalidValues(final String value)
       throws Exception
   {
     // Make sure that the specified class can be instantiated as a task.
-    MatchingRule ruleInstance = getRule();
+    final MatchingRule ruleInstance = getRule();
 
     // normalize the 2 provided values
     ruleInstance.normalizeAttributeValue(ByteString.valueOf(value));
   }
+
+
+
+  /**
+   * Get the Ordering matching Rules that is to be tested.
+   *
+   * @return The Ordering matching Rules that is to be tested.
+   */
+  protected abstract MatchingRule getRule();
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OtherMailboxSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OtherMailboxSyntaxTest.java
index 94f9cca..243536f 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OtherMailboxSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OtherMailboxSyntaxTest.java
@@ -43,9 +43,11 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
+  @DataProvider(name = "acceptableValues")
+  public Object[][] createAcceptableValues()
   {
-    return Schema.getCoreSchema().getSyntax(SYNTAX_OTHER_MAILBOX_OID);
+    return new Object[][] { { "MyMail$Mymailbox", true },
+        { "MyMailMymailbox", false }, };
   }
 
 
@@ -54,10 +56,8 @@
    * {@inheritDoc}
    */
   @Override
-  @DataProvider(name = "acceptableValues")
-  public Object[][] createAcceptableValues()
+  protected Syntax getRule()
   {
-    return new Object[][] { { "MyMail$Mymailbox", true },
-        { "MyMailMymailbox", false }, };
+    return Schema.getCoreSchema().getSyntax(SYNTAX_OTHER_MAILBOX_OID);
   }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/RegexSyntaxTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/RegexSyntaxTestCase.java
index 3297e97..8b9cb15 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/RegexSyntaxTestCase.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/RegexSyntaxTestCase.java
@@ -45,39 +45,10 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
-  {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addPatternSyntax("1.1.1",
-        "Host and Port in the format of HOST:PORT", Pattern
-            .compile("^[a-z-A-Z]+:[0-9.]+\\d$"), false);
-    return builder.toSchema().getSyntax("1.1.1");
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
   @DataProvider(name = "acceptableValues")
   public Object[][] createAcceptableValues()
   {
-    return new Object[][] { { "invalid regex", false },
-        { "host:0.0.0", true }, };
-  }
-
-
-
-  @Test
-  public void testInvalidPattern()
-  {
-    // This should fail due to invalid pattern.
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addSyntax(
-        "( 1.1.1 DESC 'Host and Port in the format of HOST:PORT' "
-            + " X-PATTERN '^[a-z-A-Z+:[0-@.]+\\d$' )", true);
-    Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
+    return new Object[][] { { "invalid regex", false }, { "host:0.0.0", true }, };
   }
 
 
@@ -86,11 +57,39 @@
   public void testDecode()
   {
     // This should fail due to invalid pattern.
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
     builder.addSyntax(
         "( 1.1.1 DESC 'Host and Port in the format of HOST:PORT' "
             + " X-PATTERN '^[a-z-A-Z]+:[0-9.]+\\d$' )", true);
     builder.toSchema();
   }
 
+
+
+  @Test
+  public void testInvalidPattern()
+  {
+    // This should fail due to invalid pattern.
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addSyntax(
+        "( 1.1.1 DESC 'Host and Port in the format of HOST:PORT' "
+            + " X-PATTERN '^[a-z-A-Z+:[0-@.]+\\d$' )", true);
+    Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
+  }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected Syntax getRule()
+  {
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addPatternSyntax("1.1.1",
+        "Host and Port in the format of HOST:PORT", Pattern
+            .compile("^[a-z-A-Z]+:[0-9.]+\\d$"), false);
+    return builder.toSchema().getSyntax("1.1.1");
+  }
+
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SchemaUtilsTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SchemaUtilsTest.java
index fe2c1e7..318c098 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SchemaUtilsTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SchemaUtilsTest.java
@@ -43,17 +43,26 @@
 public class SchemaUtilsTest extends SchemaTestCase
 {
 
+  @DataProvider(name = "invalidOIDs")
+  public Object[][] createInvalidOIDs()
+  {
+    return new Object[][] { { "" }, { ".0" }, { "0." }, { "100." }, { ".999" },
+        { "1one" }, { "one+two+three" },
+        // AD puts quotes around OIDs - test mismatched quotes.
+        { "'0" }, { "'10" }, { "999'" }, { "0.0'" }, };
+  }
+
+
+
   @DataProvider(name = "validOIDs")
   public Object[][] createValidOIDs()
   {
     return new Object[][] {
         // Compliant NOIDs
-        { "0.0" }, { "1.0" }, { "2.0" }, { "3.0" }, { "4.0" },
-        { "5.0" }, { "6.0" }, { "7.0" }, { "8.0" }, { "9.0" },
-        { "0.1" }, { "0.2" }, { "0.3" }, { "0.4" }, { "0.5" },
-        { "0.6" }, { "0.7" }, { "0.8" }, { "0.9" }, { "10.0" },
-        { "100.0" },
-        { "999.0" },
+        { "0.0" }, { "1.0" }, { "2.0" }, { "3.0" }, { "4.0" }, { "5.0" },
+        { "6.0" }, { "7.0" }, { "8.0" }, { "9.0" }, { "0.1" }, { "0.2" },
+        { "0.3" }, { "0.4" }, { "0.5" }, { "0.6" }, { "0.7" }, { "0.8" },
+        { "0.9" }, { "10.0" }, { "100.0" }, { "999.0" },
         { "0.100" },
         { "0.999" },
         { "100.100" },
@@ -69,31 +78,29 @@
         // AD puts quotes around OIDs - not compliant but we need to
         // handle them.
         { "'0.0'" }, { "'10.0'" }, { "'999.0'" },
-        { "'111.22.333.44.55555.66.777.88.999'" }, { "'a'" },
-        { "'a2'" }, { "'a-'" }, { "'one'" }, { "'one1'" },
+        { "'111.22.333.44.55555.66.777.88.999'" }, { "'a'" }, { "'a2'" },
+        { "'a-'" }, { "'one'" }, { "'one1'" },
         { "'one-two'" },
         { "'one1-two2-three3'" },
         // Not strictly legal, but we'll be lenient with what we accept.
-        { "0" }, { "1" }, { "2" }, { "3" }, { "4" }, { "5" }, { "6" },
-        { "7" }, { "8" }, { "9" }, { "00" }, { "01" }, { "01.0" },
-        { "0.01" }, { "one.two.three" }, };
+        { "0" }, { "1" }, { "2" }, { "3" }, { "4" }, { "5" }, { "6" }, { "7" },
+        { "8" }, { "9" }, { "00" }, { "01" }, { "01.0" }, { "0.01" },
+        { "one.two.three" }, };
   }
 
 
 
-  @DataProvider(name = "invalidOIDs")
-  public Object[][] createInvalidOIDs()
+  @Test(dataProvider = "invalidOIDs", expectedExceptions = DecodeException.class)
+  public void testReadOIDInvalid(final String oid) throws DecodeException
   {
-    return new Object[][] { { "" }, { ".0" }, { "0." }, { "100." },
-        { ".999" }, { "1one" }, { "one+two+three" },
-        // AD puts quotes around OIDs - test mismatched quotes.
-        { "'0" }, { "'10" }, { "999'" }, { "0.0'" }, };
+    final SubstringReader reader = new SubstringReader(oid);
+    SchemaUtils.readOID(reader);
   }
 
 
 
   @Test(dataProvider = "validOIDs")
-  public void testReadOIDValid(String oid) throws DecodeException
+  public void testReadOIDValid(final String oid) throws DecodeException
   {
     String expected = oid;
     if (oid.startsWith("'"))
@@ -101,16 +108,7 @@
       expected = oid.substring(1, oid.length() - 1);
     }
 
-    SubstringReader reader = new SubstringReader(oid);
+    final SubstringReader reader = new SubstringReader(oid);
     Assert.assertEquals(SchemaUtils.readOID(reader), expected);
   }
-
-
-
-  @Test(dataProvider = "invalidOIDs", expectedExceptions = DecodeException.class)
-  public void testReadOIDInvalid(String oid) throws DecodeException
-  {
-    SubstringReader reader = new SubstringReader(oid);
-    SchemaUtils.readOID(reader);
-  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstitutionSyntaxTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstitutionSyntaxTestCase.java
index 1af8608..d6c3238 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstitutionSyntaxTestCase.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstitutionSyntaxTestCase.java
@@ -28,7 +28,7 @@
 
 
 
-import static org.opends.sdk.schema.SchemaConstants.*;
+import static org.opends.sdk.schema.SchemaConstants.SYNTAX_IA5_STRING_OID;
 
 import org.testng.Assert;
 import org.testng.annotations.DataProvider;
@@ -45,26 +45,10 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
-  {
-    // Use IA5String syntax as our substitute.
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addSubstitutionSyntax("9.9.9", "Unimplemented Syntax",
-        SYNTAX_IA5_STRING_OID, false);
-    return builder.toSchema().getSyntax("9.9.9");
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
   @DataProvider(name = "acceptableValues")
   public Object[][] createAcceptableValues()
   {
-    return new Object[][] { { "12345678", true },
-        { "12345678\u2163", false }, };
+    return new Object[][] { { "12345678", true }, { "12345678\u2163", false }, };
   }
 
 
@@ -72,7 +56,7 @@
   @Test
   public void testSelfSubstitute1()
   {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
     builder.addSyntax("( 1.3.6.1.4.1.1466.115.121.1.15 "
         + " DESC 'Replacing DirectorySyntax'  "
         + " X-SUBST '1.3.6.1.4.1.1466.115.121.1.15' )", true);
@@ -84,22 +68,60 @@
   @Test
   public void testSelfSubstitute2()
   {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
     builder.addSubstitutionSyntax("1.3.6.1.4.1.1466.115.121.1.15",
-        "Replacing DirectorySyntax", "1.3.6.1.4.1.1466.115.121.1.15",
-        true);
+        "Replacing DirectorySyntax", "1.3.6.1.4.1.1466.115.121.1.15", true);
     Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
   }
 
 
 
+  @Test(expectedExceptions = ConflictingSchemaElementException.class)
+  public void testSubstituteCore1() throws ConflictingSchemaElementException
+  {
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addSyntax("( 1.3.6.1.4.1.1466.115.121.1.26 "
+        + " DESC 'Replacing DirectorySyntax'  " + " X-SUBST '9.9.9' )", false);
+  }
+
+
+
+  @Test
+  public void testSubstituteCore1Override()
+  {
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addSyntax("( 1.3.6.1.4.1.1466.115.121.1.26 "
+        + " DESC 'Replacing DirectorySyntax'  " + " X-SUBST '9.9.9' )", true);
+  }
+
+
+
+  @Test(expectedExceptions = ConflictingSchemaElementException.class)
+  public void testSubstituteCore2() throws ConflictingSchemaElementException
+  {
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addSubstitutionSyntax("1.3.6.1.4.1.1466.115.121.1.26",
+        "Replacing DirectorySyntax", "9.9.9", false);
+  }
+
+
+
+  @Test
+  public void testSubstituteCore2Override()
+  {
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addSubstitutionSyntax("1.3.6.1.4.1.1466.115.121.1.26",
+        "Replacing DirectorySyntax", "9.9.9", true);
+  }
+
+
+
   @Test
   public void testUndefinedSubstitute1()
   {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
     builder.addSyntax("( 1.3.6.1.4.1.1466.115.121.1.15 "
-        + " DESC 'Replacing DirectorySyntax'  " + " X-SUBST '1.1.1' )",
-        true);
+        + " DESC 'Replacing DirectorySyntax'  " + " X-SUBST '1.1.1' )", true);
     Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
   }
 
@@ -108,7 +130,7 @@
   @Test
   public void testUndefinedSubstitute2()
   {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
     builder.addSubstitutionSyntax("1.3.6.1.4.1.1466.115.121.1.15",
         "Replacing DirectorySyntax", "1.1.1", true);
     Assert.assertFalse(builder.toSchema().getWarnings().isEmpty());
@@ -116,45 +138,16 @@
 
 
 
-  @Test(expectedExceptions = ConflictingSchemaElementException.class)
-  public void testSubstituteCore1()
-      throws ConflictingSchemaElementException
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected Syntax getRule()
   {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addSyntax("( 1.3.6.1.4.1.1466.115.121.1.26 "
-        + " DESC 'Replacing DirectorySyntax'  " + " X-SUBST '9.9.9' )",
-        false);
-  }
-
-
-
-  @Test(expectedExceptions = ConflictingSchemaElementException.class)
-  public void testSubstituteCore2()
-      throws ConflictingSchemaElementException
-  {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addSubstitutionSyntax("1.3.6.1.4.1.1466.115.121.1.26",
-        "Replacing DirectorySyntax", "9.9.9", false);
-  }
-
-
-
-  @Test
-  public void testSubstituteCore1Override()
-  {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addSyntax("( 1.3.6.1.4.1.1466.115.121.1.26 "
-        + " DESC 'Replacing DirectorySyntax'  " + " X-SUBST '9.9.9' )",
-        true);
-  }
-
-
-
-  @Test
-  public void testSubstituteCore2Override()
-  {
-    SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
-    builder.addSubstitutionSyntax("1.3.6.1.4.1.1466.115.121.1.26",
-        "Replacing DirectorySyntax", "9.9.9", true);
+    // Use IA5String syntax as our substitute.
+    final SchemaBuilder builder = new SchemaBuilder(Schema.getCoreSchema());
+    builder.addSubstitutionSyntax("9.9.9", "Unimplemented Syntax",
+        SYNTAX_IA5_STRING_OID, false);
+    return builder.toSchema().getSyntax("9.9.9");
   }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstringMatchingRuleTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstringMatchingRuleTest.java
index 4c2ee85..f0ab7e2 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstringMatchingRuleTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstringMatchingRuleTest.java
@@ -33,66 +33,24 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import org.opends.sdk.ByteSequence;
+import org.opends.sdk.ByteString;
 import org.opends.sdk.ConditionResult;
 import org.opends.sdk.DecodeException;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import org.opends.sdk.ByteSequence;
-import org.opends.sdk.ByteString;
-
 
 
 /**
- * Abstract class for building test for the substring matching rules.
- * This class is intended to be extended by one class for each substring
- * matching rules.
+ * Abstract class for building test for the substring matching rules. This class
+ * is intended to be extended by one class for each substring matching rules.
  */
 public abstract class SubstringMatchingRuleTest extends SchemaTestCase
 {
   /**
-   * Generate data for the test of the middle string match.
-   * 
-   * @return the data for the test of the middle string match.
-   */
-  @DataProvider(name = "substringMiddleMatchData")
-  public abstract Object[][] createSubstringMiddleMatchData();
-
-
-
-  /**
-   * Generate data for the test of the initial string match.
-   * 
-   * @return the data for the test of the initial string match.
-   */
-  @DataProvider(name = "substringInitialMatchData")
-  public abstract Object[][] createSubstringInitialMatchData();
-
-
-
-  /**
-   * Generate data for the test of the final string match.
-   * 
-   * @return the data for the test of the final string match.
-   */
-  @DataProvider(name = "substringInitialMatchData")
-  public abstract Object[][] createSubstringFinalMatchData();
-
-
-
-  /**
-   * Generate invalid attribute values for the Matching Rule test.
-   * 
-   * @return the data for the EqualityMatchingRulesInvalidValuestest.
-   */
-  @DataProvider(name = "substringInvalidAttributeValues")
-  public abstract Object[][] createMatchingRuleInvalidAttributeValues();
-
-
-
-  /**
    * Generate invalid assertion values for the Matching Rule test.
-   * 
+   *
    * @return the data for the EqualityMatchingRulesInvalidValuestest.
    */
   @DataProvider(name = "substringInvalidAssertionValues")
@@ -101,46 +59,66 @@
 
 
   /**
-   * Get an instance of the matching rule.
-   * 
-   * @return An instance of the matching rule to test.
+   * Generate invalid attribute values for the Matching Rule test.
+   *
+   * @return the data for the EqualityMatchingRulesInvalidValuestest.
    */
-  protected abstract MatchingRule getRule();
+  @DataProvider(name = "substringInvalidAttributeValues")
+  public abstract Object[][] createMatchingRuleInvalidAttributeValues();
 
 
 
   /**
-   * Test the normalization and the middle substring match.
+   * Generate data for the test of the final string match.
+   *
+   * @return the data for the test of the final string match.
    */
-  @Test(dataProvider = "substringMiddleMatchData")
-  public void middleMatchingRules(String value, String[] middleSubs,
-      ConditionResult result) throws Exception
+  @DataProvider(name = "substringInitialMatchData")
+  public abstract Object[][] createSubstringFinalMatchData();
+
+
+
+  /**
+   * Generate data for the test of the initial string match.
+   *
+   * @return the data for the test of the initial string match.
+   */
+  @DataProvider(name = "substringInitialMatchData")
+  public abstract Object[][] createSubstringInitialMatchData();
+
+
+
+  /**
+   * Generate data for the test of the middle string match.
+   *
+   * @return the data for the test of the middle string match.
+   */
+  @DataProvider(name = "substringMiddleMatchData")
+  public abstract Object[][] createSubstringMiddleMatchData();
+
+
+
+  /**
+   * Test the normalization and the final substring match.
+   */
+  @Test(dataProvider = "substringFinalMatchData")
+  public void finalMatchingRules(final String value, final String finalValue,
+      final ConditionResult result) throws Exception
   {
-    MatchingRule rule = getRule();
+    final MatchingRule rule = getRule();
 
     // normalize the 2 provided values and check that they are equals
-    ByteString normalizedValue =
-        rule.normalizeAttributeValue(ByteString.valueOf(value));
+    final ByteString normalizedValue = rule.normalizeAttributeValue(ByteString
+        .valueOf(value));
 
-    StringBuilder printableMiddleSubs = new StringBuilder();
-    List<ByteSequence> middleList =
-        new ArrayList<ByteSequence>(middleSubs.length);
-    printableMiddleSubs.append("*");
-    for (String middleSub : middleSubs)
-    {
-      printableMiddleSubs.append(middleSub);
-      printableMiddleSubs.append("*");
-      middleList.add(ByteString.valueOf(middleSub));
-    }
-
-    if (rule.getAssertion(null, middleList, null).matches(
+    if (rule.getAssertion(null, null, ByteString.valueOf(finalValue)).matches(
         normalizedValue) != result
-        || rule.getAssertion(ByteString.valueOf(printableMiddleSubs))
-            .matches(normalizedValue) != result)
+        || rule.getAssertion(ByteString.valueOf("*" + finalValue)).matches(
+            normalizedValue) != result)
     {
-      fail("middle substring matching rule " + rule
-          + " does not give expected result (" + result
-          + ") for values : " + value + " and " + printableMiddleSubs);
+      fail("final substring matching rule " + rule
+          + " does not give expected result (" + result + ") for values : "
+          + value + " and " + finalValue);
     }
   }
 
@@ -150,88 +128,46 @@
    * Test the normalization and the initial substring match.
    */
   @Test(dataProvider = "substringInitialMatchData")
-  public void initialMatchingRules(String value, String initial,
-      ConditionResult result) throws Exception
+  public void initialMatchingRules(final String value, final String initial,
+      final ConditionResult result) throws Exception
   {
-    MatchingRule rule = getRule();
+    final MatchingRule rule = getRule();
 
     // normalize the 2 provided values and check that they are equals
-    ByteString normalizedValue =
-        rule.normalizeAttributeValue(ByteString.valueOf(value));
+    final ByteString normalizedValue = rule.normalizeAttributeValue(ByteString
+        .valueOf(value));
 
-    if (rule.getAssertion(ByteString.valueOf(initial), null, null)
-        .matches(normalizedValue) != result
-        || rule.getAssertion(ByteString.valueOf(initial + "*"))
-            .matches(normalizedValue) != result)
+    if (rule.getAssertion(ByteString.valueOf(initial), null, null).matches(
+        normalizedValue) != result
+        || rule.getAssertion(ByteString.valueOf(initial + "*")).matches(
+            normalizedValue) != result)
     {
       fail("initial substring matching rule " + rule
-          + " does not give expected result (" + result
-          + ") for values : " + value + " and " + initial);
+          + " does not give expected result (" + result + ") for values : "
+          + value + " and " + initial);
     }
   }
 
 
 
   /**
-   * Test the normalization and the final substring match.
-   */
-  @Test(dataProvider = "substringFinalMatchData")
-  public void finalMatchingRules(String value, String finalValue,
-      ConditionResult result) throws Exception
-  {
-    MatchingRule rule = getRule();
-
-    // normalize the 2 provided values and check that they are equals
-    ByteString normalizedValue =
-        rule.normalizeAttributeValue(ByteString.valueOf(value));
-
-    if (rule.getAssertion(null, null, ByteString.valueOf(finalValue))
-        .matches(normalizedValue) != result
-        || rule.getAssertion(ByteString.valueOf("*" + finalValue))
-            .matches(normalizedValue) != result)
-    {
-      fail("final substring matching rule " + rule
-          + " does not give expected result (" + result
-          + ") for values : " + value + " and " + finalValue);
-    }
-  }
-
-
-
-  /**
-   * Test that invalid values are rejected.
-   */
-  @Test(expectedExceptions = DecodeException.class, dataProvider = "substringInvalidAttributeValues")
-  public void substringInvalidAttributeValues(String value)
-      throws Exception
-  {
-    // Get the instance of the rule to be tested.
-    MatchingRule rule = getRule();
-
-    rule.normalizeAttributeValue(ByteString.valueOf(value));
-  }
-
-
-
-  /**
    * Test that invalid values are rejected.
    */
   @Test(expectedExceptions = DecodeException.class, dataProvider = "substringInvalidAssertionValues")
-  public void matchingRulesInvalidAssertionValues(String subInitial,
-      String[] anys, String subFinal) throws Exception
+  public void matchingRulesInvalidAssertionValues(final String subInitial,
+      final String[] anys, final String subFinal) throws Exception
   {
     // Get the instance of the rule to be tested.
-    MatchingRule rule = getRule();
+    final MatchingRule rule = getRule();
 
-    List<ByteSequence> anyList =
-        new ArrayList<ByteSequence>(anys.length);
-    for (String middleSub : anys)
+    final List<ByteSequence> anyList = new ArrayList<ByteSequence>(anys.length);
+    for (final String middleSub : anys)
     {
       anyList.add(ByteString.valueOf(middleSub));
     }
     rule.getAssertion(subInitial == null ? null : ByteString
-        .valueOf(subInitial), anyList, subFinal == null ? null
-        : ByteString.valueOf(subFinal));
+        .valueOf(subInitial), anyList, subFinal == null ? null : ByteString
+        .valueOf(subFinal));
   }
 
 
@@ -241,19 +177,19 @@
    */
   @Test(expectedExceptions = DecodeException.class, dataProvider = "substringInvalidAssertionValues")
   public void matchingRulesInvalidAssertionValuesString(
-      String subInitial, String[] anys, String subFinal)
+      final String subInitial, final String[] anys, final String subFinal)
       throws Exception
   {
     // Get the instance of the rule to be tested.
-    MatchingRule rule = getRule();
+    final MatchingRule rule = getRule();
 
-    StringBuilder assertionString = new StringBuilder();
+    final StringBuilder assertionString = new StringBuilder();
     if (subInitial != null)
     {
       assertionString.append(subInitial);
     }
     assertionString.append("*");
-    for (String middleSub : anys)
+    for (final String middleSub : anys)
     {
       assertionString.append(middleSub);
       assertionString.append("*");
@@ -264,4 +200,64 @@
     }
     rule.getAssertion(ByteString.valueOf(assertionString.toString()));
   }
+
+
+
+  /**
+   * Test the normalization and the middle substring match.
+   */
+  @Test(dataProvider = "substringMiddleMatchData")
+  public void middleMatchingRules(final String value,
+      final String[] middleSubs, final ConditionResult result) throws Exception
+  {
+    final MatchingRule rule = getRule();
+
+    // normalize the 2 provided values and check that they are equals
+    final ByteString normalizedValue = rule.normalizeAttributeValue(ByteString
+        .valueOf(value));
+
+    final StringBuilder printableMiddleSubs = new StringBuilder();
+    final List<ByteSequence> middleList = new ArrayList<ByteSequence>(
+        middleSubs.length);
+    printableMiddleSubs.append("*");
+    for (final String middleSub : middleSubs)
+    {
+      printableMiddleSubs.append(middleSub);
+      printableMiddleSubs.append("*");
+      middleList.add(ByteString.valueOf(middleSub));
+    }
+
+    if (rule.getAssertion(null, middleList, null).matches(normalizedValue) != result
+        || rule.getAssertion(ByteString.valueOf(printableMiddleSubs)).matches(
+            normalizedValue) != result)
+    {
+      fail("middle substring matching rule " + rule
+          + " does not give expected result (" + result + ") for values : "
+          + value + " and " + printableMiddleSubs);
+    }
+  }
+
+
+
+  /**
+   * Test that invalid values are rejected.
+   */
+  @Test(expectedExceptions = DecodeException.class, dataProvider = "substringInvalidAttributeValues")
+  public void substringInvalidAttributeValues(final String value)
+      throws Exception
+  {
+    // Get the instance of the rule to be tested.
+    final MatchingRule rule = getRule();
+
+    rule.normalizeAttributeValue(ByteString.valueOf(value));
+  }
+
+
+
+  /**
+   * Get an instance of the matching rule.
+   *
+   * @return An instance of the matching rule to test.
+   */
+  protected abstract MatchingRule getRule();
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SyntaxTestCase.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SyntaxTestCase.java
index 78198f0..a71120c 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SyntaxTestCase.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SyntaxTestCase.java
@@ -30,13 +30,12 @@
 
 import static org.testng.Assert.fail;
 
-import org.opends.sdk.LocalizableMessageBuilder;
+import org.opends.sdk.ByteString;
 import org.opends.sdk.DecodeException;
+import org.opends.sdk.LocalizableMessageBuilder;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
 
-import org.opends.sdk.ByteString;
-
 
 
 /**
@@ -45,10 +44,10 @@
 public abstract class SyntaxTestCase extends SchemaTestCase
 {
   /**
-   * Create data for the testAcceptableValues test. This should be a
-   * table of tables with 2 elements. The first one should be the value
-   * to test, the second the expected result of the test.
-   * 
+   * Create data for the testAcceptableValues test. This should be a table of
+   * tables with 2 elements. The first one should be the value to test, the
+   * second the expected result of the test.
+   *
    * @return a table containing data for the testAcceptableValues Test.
    */
   @DataProvider(name = "acceptableValues")
@@ -57,33 +56,25 @@
 
 
   /**
-   * Get an instance of the attribute syntax that muste be tested.
-   * 
-   * @return An instance of the attribute syntax that muste be tested.
-   */
-  protected abstract Syntax getRule() throws SchemaException,
-      DecodeException;
-
-
-
-  /**
    * Test the normalization and the approximate comparison.
    */
   @Test(dataProvider = "acceptableValues")
-  public void testAcceptableValues(String value, Boolean result)
+  public void testAcceptableValues(final String value, final Boolean result)
       throws Exception
   {
     // Make sure that the specified class can be instantiated as a task.
-    Syntax syntax = getRule();
+    final Syntax syntax = getRule();
 
-    LocalizableMessageBuilder reason = new LocalizableMessageBuilder();
+    final LocalizableMessageBuilder reason = new LocalizableMessageBuilder();
     // test the valueIsAcceptable method
-    Boolean liveResult =
-        syntax.valueIsAcceptable(ByteString.valueOf(value), reason);
+    final Boolean liveResult = syntax.valueIsAcceptable(ByteString
+        .valueOf(value), reason);
 
-    if (liveResult != result)
+    if (!liveResult.equals(result))
+    {
       fail(syntax + ".valueIsAcceptable gave bad result for " + value
           + "reason : " + reason);
+    }
 
     // call the getters
     syntax.getApproximateMatchingRule();
@@ -96,4 +87,13 @@
     syntax.isHumanReadable();
     syntax.toString();
   }
+
+
+
+  /**
+   * Get an instance of the attribute syntax that muste be tested.
+   *
+   * @return An instance of the attribute syntax that muste be tested.
+   */
+  protected abstract Syntax getRule() throws SchemaException, DecodeException;
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/TelexSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/TelexSyntaxTest.java
index 7c26fec..d86d3ba 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/TelexSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/TelexSyntaxTest.java
@@ -43,9 +43,12 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
+  @DataProvider(name = "acceptableValues")
+  public Object[][] createAcceptableValues()
   {
-    return Schema.getCoreSchema().getSyntax(SYNTAX_TELEX_OID);
+    return new Object[][] { { "123$france$456", true },
+        { "abcdefghijk$lmnopqr$stuvwxyz", true },
+        { "12345$67890$()+,-./:? ", true }, };
   }
 
 
@@ -54,12 +57,9 @@
    * {@inheritDoc}
    */
   @Override
-  @DataProvider(name = "acceptableValues")
-  public Object[][] createAcceptableValues()
+  protected Syntax getRule()
   {
-    return new Object[][] { { "123$france$456", true },
-        { "abcdefghijk$lmnopqr$stuvwxyz", true },
-        { "12345$67890$()+,-./:? ", true }, };
+    return Schema.getCoreSchema().getSyntax(SYNTAX_TELEX_OID);
   }
 
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UTCTimeSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UTCTimeSyntaxTest.java
index 10dc155..d816be6 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UTCTimeSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UTCTimeSyntaxTest.java
@@ -43,17 +43,6 @@
  */
 public class UTCTimeSyntaxTest extends SyntaxTestCase
 {
-  /**
-   * {@inheritDoc}
-   */
-  @Override
-  protected Syntax getRule()
-  {
-    return Schema.getCoreSchema().getSyntax(SYNTAX_UTC_TIME_OID);
-  }
-
-
-
   @Override
   @DataProvider(name = "acceptableValues")
   public Object[][] createAcceptableValues()
@@ -93,20 +82,31 @@
   /**
    * Tests the {@code createUTCTimeValue} and {@code decodeUTCTimeValue}
    * methods.
-   * 
+   *
    * @throws Exception
    *           If an unexpected problem occurs.
    */
   @Test()
   public void testCreateAndDecodeUTCTimeValue() throws Exception
   {
-    Date d = new Date();
-    String timeValue = UTCTimeSyntaxImpl.createUTCTimeValue(d);
-    Date decodedDate = UTCTimeSyntaxImpl.decodeUTCTimeValue(timeValue);
+    final Date d = new Date();
+    final String timeValue = UTCTimeSyntaxImpl.createUTCTimeValue(d);
+    final Date decodedDate = UTCTimeSyntaxImpl.decodeUTCTimeValue(timeValue);
 
     // UTCTime does not have support for sub-second values, so we need
     // to make
     // sure that the decoded value is within 1000 milliseconds.
     assertTrue(Math.abs(d.getTime() - decodedDate.getTime()) < 1000);
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected Syntax getRule()
+  {
+    return Schema.getCoreSchema().getSyntax(SYNTAX_UTC_TIME_OID);
+  }
 }
diff --git a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UUIDSyntaxTest.java b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UUIDSyntaxTest.java
index ee173f8..d2d228f 100644
--- a/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UUIDSyntaxTest.java
+++ b/sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UUIDSyntaxTest.java
@@ -43,22 +43,10 @@
    * {@inheritDoc}
    */
   @Override
-  protected Syntax getRule()
-  {
-    return Schema.getCoreSchema().getSyntax(SYNTAX_UUID_OID);
-  }
-
-
-
-  /**
-   * {@inheritDoc}
-   */
-  @Override
   @DataProvider(name = "acceptableValues")
   public Object[][] createAcceptableValues()
   {
-    return new Object[][] {
-        { "12345678-9ABC-DEF0-1234-1234567890ab", true },
+    return new Object[][] { { "12345678-9ABC-DEF0-1234-1234567890ab", true },
         { "12345678-9abc-def0-1234-1234567890ab", true },
         { "12345678-9abc-def0-1234-1234567890ab", true },
         { "12345678-9abc-def0-1234-1234567890ab", true },
@@ -71,4 +59,15 @@
         { "12345678/9abc/def0/1234/1234567890ab", false },
         { "12345678-9abc-def0-1234-1234567890a", false }, };
   }
+
+
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  protected Syntax getRule()
+  {
+    return Schema.getCoreSchema().getSyntax(SYNTAX_UUID_OID);
+  }
 }

--
Gitblit v1.10.0