mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

matthew_swift
28.47.2010 f2160f4bd1c8ac67e5a86a6710d431e8932877f9
Synchronize SDK on java.net with internal repository.
18 files copied
66 files deleted
154 files added
11 files renamed
369 files modified
117164 ■■■■■ changed files
sdk/build.xml 36 ●●●●● patch | view | raw | blame | history
sdk/examples/org/opends/sdk/examples/DummyServer.java 260 ●●●●● patch | view | raw | blame | history
sdk/examples/org/opends/sdk/examples/package-info.java 9 ●●●●● patch | view | raw | blame | history
sdk/ext/checkstyle/check-src.xml 58 ●●●●● patch | view | raw | blame | history
sdk/ext/checkstyle/check-tests.xml 16 ●●●●● patch | view | raw | blame | history
sdk/ext/checkstyle/checkstyle-all-4.1.jar patch | view | raw | blame | history
sdk/ext/checkstyle/checkstyle-all-5.1.jar patch | view | raw | blame | history
sdk/ext/checkstyle/opends-checkstyle.xml 97 ●●●●● patch | view | raw | blame | history
sdk/ext/checkstyle/opends-doctarget-checkstyle.xml 35 ●●●●● patch | view | raw | blame | history
sdk/ext/checkstyle/opends-functest-checkstyle.xml 17 ●●●●● patch | view | raw | blame | history
sdk/ext/checkstyle/opends-unittest-checkstyle.xml 17 ●●●●● patch | view | raw | blame | history
sdk/ext/checkstyle/src-header.txt patch | view | raw | blame | history
sdk/lib/grizzly.jar patch | view | raw | blame | history
sdk/resource/bin/_client-script.bat 10 ●●●● patch | view | raw | blame | history
sdk/resource/bin/_script-util.bat 4 ●●●● patch | view | raw | blame | history
sdk/resource/bin/_script-util.sh 55 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControl.java 191 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControl.java 570 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/controls/RealAttributesOnlyRequestControl.java 192 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/controls/VirtualAttributesOnlyRequestControl.java 192 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/controls/package-info.java 9 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedRequest.java 248 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedResult.java 184 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/extensions/GetSymmetricKeyExtendedRequest.java 334 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedRequest.java 1139 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedResult.java 171 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperation.java 26 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationContainer.java 29 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationType.java 323 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/extensions/package-info.java 7 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/ASN1BufferReader.java 272 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/ASN1BufferWriter.java 261 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPFutureResultImpl.java 119 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPMessageHandler.java 240 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPTransport.java 245 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/GlobalTransportFactory.java 183 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPListenerOptions.java 116 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPOptions.java 116 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/InternalConnection.java 335 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPBindFutureResultImpl.java 68 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPClientFilter.java 587 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPCompareFutureResultImpl.java 43 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPConnection.java 1522 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPConnectionFactoryImpl.java 405 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPConstants.java 75 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPExtendedFutureResultImpl.java 53 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPFutureResultImpl.java 48 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPListenerImpl.java 139 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPMessageHandler.java 140 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPReader.java 1817 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPSearchFutureResultImpl.java 79 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPServerFilter.java 953 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPUtils.java 234 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/LDAPWriter.java 677 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/SASLDecoderTransformer.java 109 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/SASLEncoderTransformer.java 109 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/SASLFilter.java 317 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/SASLStreamReader.java 118 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/SASLStreamWriter.java 88 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/TimeoutChecker.java 157 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/UnexpectedRequestException.java 5 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/UnexpectedResponseException.java 6 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/UnsupportedMessageException.java 10 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/ldap/package-info.java 9 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/messages/messages.properties 142 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/ApplicationKeyManager.java 138 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/Argument.java 1038 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/ArgumentException.java 25 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/ArgumentGroup.java 148 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/ArgumentParser.java 2539 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/ArgumentParserConnectionFactory.java 746 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/AuthenticatedConnectionFactory.java 662 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/BooleanArgument.java 92 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/CLIException.java 33 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/ConsoleApplication.java 267 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/DataSource.java 485 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/DistrustAllTrustManager.java 66 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/FileBasedArgument.java 246 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/HostnameMismatchCertificateException.java 93 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/IntegerArgument.java 793 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/LDAPCompare.java 524 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/LDAPModify.java 833 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/LDAPPasswordModify.java 414 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/LDAPSearch.java 822 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/ModRate.java 502 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/MultiChoiceArgument.java 305 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/MultiColumnPrinter.java 300 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/PerformanceRunner.java 1214 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/PromptingTrustManager.java 248 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/SearchRate.java 583 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/SelectableCertificateKeyManager.java 314 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/StringArgument.java 107 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/ToolConstants.java 56 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/TrustAllTrustManager.java 72 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/TrustStoreTrustManager.java 284 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/Utils.java 970 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/tools/package-info.java 3 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/ASCIICharProp.java 123 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/AbstractFutureResult.java 213 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Base64.java 161 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/ByteSequenceOutputStream.java 105 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Collections2.java 91 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/CompletedFutureResult.java 109 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Function.java 14 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Functions.java 192 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/FutureResultTransformer.java 99 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Iterables.java 292 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Iterators.java 258 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/LocalizableMessageDescriptor.java 417 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Platform.java 1211 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Predicate.java 18 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/RecursiveFutureResult.java 69 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/SSLUtils.java 39 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/SizeLimitInputStream.java 137 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/StaticUtils.java 1164 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/StringPrepProfile.java 779 ●●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/SubstringReader.java 139 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/Validator.java 114 ●●●● patch | view | raw | blame | history
sdk/src/com/sun/opends/sdk/util/package-info.java 7 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AVA.java 954 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AbstractAsynchronousConnection.java 255 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AbstractAttribute.java 132 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AbstractConnection.java 179 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AbstractConnectionFactory.java 62 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AbstractEntry.java 206 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AbstractFilterVisitor.java 94 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AbstractMapEntry.java 204 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Assertion.java 14 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AssertionFailureException.java 19 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AsynchronousConnection.java 670 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Attribute.java 301 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AttributeDescription.java 347 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AttributeFactory.java 54 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java 412 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AuthenticationException.java 60 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/AuthorizationException.java 62 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ByteSequence.java 185 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ByteSequenceReader.java 224 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ByteString.java 228 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ByteStringBuilder.java 346 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/CancelledResultException.java 16 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ConditionResult.java 157 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Connection.java 928 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ConnectionEventListener.java 92 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ConnectionException.java 6 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ConnectionFactory.java 63 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ConnectionPool.java 703 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ConnectionSecurityLayer.java 83 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Connections.java 137 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ConstraintViolationException.java 80 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/DN.java 321 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/DecodeException.java 90 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/DecodeOptions.java 241 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/DereferenceAliasesPolicy.java 105 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Entry.java 532 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/EntryFactory.java 53 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/EntryNotFoundException.java 26 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ErrorResultException.java 111 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ErrorResultIOException.java 11 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/FailoverLoadBalancingAlgorithm.java 135 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Filter.java 1101 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/FilterVisitor.java 25 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/FutureResult.java 77 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java 570 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/IntermediateResponseHandler.java 69 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/InternalConnectionFactory.java 88 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/KeyManagers.java 402 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LDAPClientContext.java 118 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LDAPConnectionFactory.java 152 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LDAPListener.java 281 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LDAPListenerOptions.java 183 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LDAPOptions.java 227 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LDAPUrl.java 978 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LinkedAttribute.java 393 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LinkedHashMapEntry.java 156 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LoadBalancingAlgorithm.java 14 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LoadBalancingConnectionFactory.java 18 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LocalizableException.java 8 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LocalizableMessage.java 270 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LocalizableMessageBuilder.java 188 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/LocalizedIllegalArgumentException.java 46 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Matcher.java 189 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Modification.java 53 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ModificationType.java 110 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/MultipleEntriesFoundException.java 17 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/RDN.java 701 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ReferralException.java 19 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ResultCode.java 567 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ResultHandler.java 24 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/RootDSE.java 386 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/SSLContextBuilder.java 255 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/SchemaResolver.java 63 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/SearchResultHandler.java 37 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/SearchScope.java 96 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ServerConnection.java 277 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ServerConnectionFactory.java 59 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/SortKey.java 704 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/SortedEntry.java 294 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/SynchronousConnection.java 397 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/TimeoutResultException.java 7 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/TreeMapEntry.java 157 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/TrustManagers.java 553 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/Types.java 337 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/asn1/ASN1.java 94 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/asn1/ASN1ByteSequenceReader.java 108 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/asn1/ASN1Constants.java 74 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/asn1/ASN1InputStreamReader.java 185 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/asn1/ASN1OutputStreamWriter.java 116 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/asn1/ASN1Reader.java 139 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/asn1/ASN1Writer.java 92 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/asn1/AbstractASN1Reader.java 11 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/asn1/AbstractASN1Writer.java 19 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/asn1/package-info.java 3 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/AccountUsabilityControl.java 688 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/AssertionControl.java 197 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/AssertionRequestControl.java 242 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/AuthorizationIdentityControl.java 295 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/AuthorizationIdentityRequestControl.java 199 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/AuthorizationIdentityResponseControl.java 226 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/Control.java 126 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/ControlDecoder.java 39 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/EntryChangeNotificationControl.java 390 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/EntryChangeNotificationResponseControl.java 396 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/GenericControl.java 229 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/GetEffectiveRightsRequestControl.java 440 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/ManageDsaITRequestControl.java 194 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/MatchedValuesControl.java 350 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/MatchedValuesRequestControl.java 463 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PagedResultsControl.java 256 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PasswordExpiredControl.java 138 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PasswordExpiredResponseControl.java 194 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PasswordExpiringControl.java 175 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PasswordExpiringResponseControl.java 229 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PasswordPolicyControl.java 412 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PasswordPolicyErrorType.java 192 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PasswordPolicyRequestControl.java 195 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PasswordPolicyResponseControl.java 418 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PasswordPolicyWarningType.java 149 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PermissiveModifyRequestControl.java 189 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PersistentSearchChangeType.java 177 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PersistentSearchControl.java 328 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PersistentSearchRequestControl.java 414 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PostReadControl.java 445 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PostReadRequestControl.java 354 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PostReadResponseControl.java 259 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PreReadControl.java 445 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PreReadRequestControl.java 354 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/PreReadResponseControl.java 260 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/ProxiedAuthV1Control.java 211 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/ProxiedAuthV1RequestControl.java 294 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/ProxiedAuthV2Control.java 215 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/ProxiedAuthV2RequestControl.java 283 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/ServerSideSortControl.java 550 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/ServerSideSortRequestControl.java 393 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/ServerSideSortResponseControl.java 376 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/SimplePagedResultsControl.java 344 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/SortKey.java 145 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/SortResult.java 113 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/SubentriesRequestControl.java 195 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/SubtreeDeleteControl.java 113 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/SubtreeDeleteRequestControl.java 192 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/VLVControl.java 652 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/VLVResult.java 113 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/VLVTarget.java 192 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/VirtualListViewRequestControl.java 525 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/VirtualListViewResponseControl.java 338 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/controls/package-info.java 3 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/CancelRequest.java 167 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/ExtendedOperation.java 34 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/GetConnectionIDRequest.java 141 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/GetConnectionIDResult.java 122 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/GetSymmetricKeyRequest.java 227 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/PasswordModifyRequest.java 274 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/PasswordModifyResult.java 119 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/PasswordPolicyStateExtendedOperation.java 1070 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/StartTLSRequest.java 120 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/WhoAmIRequest.java 110 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/WhoAmIResult.java 113 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/extensions/package-info.java 31 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldap/LDAPConnectionFactory.java 128 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldap/LDAPConnectionOptions.java 211 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldap/LDAPDecoder.java 1921 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldap/LDAPEncoder.java 725 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldap/ResolvedSchema.java 65 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/AbstractLDIFReader.java 146 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/AbstractLDIFStream.java 12 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/AbstractLDIFWriter.java 72 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/ChangeRecord.java 13 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/ChangeRecordReader.java 26 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/ChangeRecordVisitor.java 21 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/ChangeRecordVisitorWriter.java 46 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/ChangeRecordWriter.java 76 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/ConnectionChangeRecordWriter.java 114 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/ConnectionEntryWriter.java 51 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/EntryReader.java 25 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/EntryWriter.java 32 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/LDIFChangeRecordReader.java 221 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/LDIFChangeRecordWriter.java 145 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/LDIFEntryReader.java 148 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java 129 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AbandonRequest.java 85 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AbandonRequestImpl.java 11 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AbstractBindRequest.java 15 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AbstractExtendedRequest.java 43 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AbstractRequestImpl.java 74 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AbstractSASLBindRequest.java 27 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AbstractUnmodifiableRequestImpl.java 62 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AddRequest.java 166 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AddRequestImpl.java 193 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequest.java 151 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequestImpl.java 129 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/BindClient.java 99 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/BindClientImpl.java 151 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/BindRequest.java 109 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequest.java 197 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestImpl.java 272 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/CancelExtendedRequest.java 143 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/CancelExtendedRequestImpl.java 230 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/CompareRequest.java 151 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/CompareRequestImpl.java 35 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/DeleteRequest.java 116 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/DeleteRequestImpl.java 17 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequest.java 256 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequestImpl.java 404 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/ExtendedRequest.java 115 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/ExtendedRequestDecoder.java 67 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/ExternalSASLBindRequest.java 160 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/ExternalSASLBindRequestImpl.java 199 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequest.java 330 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequestImpl.java 573 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/GenericBindRequest.java 179 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/GenericBindRequestImpl.java 90 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/GenericExtendedRequest.java 139 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/GenericExtendedRequestImpl.java 171 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/ModifyDNRequest.java 240 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/ModifyDNRequestImpl.java 39 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/ModifyRequest.java 250 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/ModifyRequestImpl.java 91 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequest.java 274 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequestImpl.java 437 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/PlainSASLBindRequest.java 222 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/PlainSASLBindRequestImpl.java 254 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/Request.java 85 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/Requests.java 600 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/SASLBindClientImpl.java 275 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/SASLBindRequest.java 108 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/SearchRequest.java 384 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/SearchRequestImpl.java 116 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/SimpleBindRequest.java 217 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/SimpleBindRequestImpl.java 65 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/StartTLSExtendedRequest.java 141 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/StartTLSExtendedRequestImpl.java 203 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/UnbindRequest.java 75 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/UnbindRequestImpl.java 7 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequest.java 133 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequestImpl.java 194 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/requests/package-info.java 3 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/AbstractExtendedResult.java 33 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/AbstractIntermediateResponse.java 23 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/AbstractResponseImpl.java 74 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/AbstractResultImpl.java 39 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResponseImpl.java 62 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResultImpl.java 37 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/BindResult.java 133 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/BindResultImpl.java 13 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/CompareResult.java 94 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/CompareResultImpl.java 7 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/ExtendedResult.java 118 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/ExtendedResultDecoder.java 89 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/GenericExtendedResult.java 120 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/GenericExtendedResultImpl.java 44 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/GenericIntermediateResponse.java 72 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/GenericIntermediateResponseImpl.java 59 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/IntermediateResponse.java 72 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResult.java 235 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResultImpl.java 189 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/Response.java 81 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/Responses.java 129 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/Result.java 152 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/ResultImpl.java 6 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/SearchResultEntry.java 150 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/SearchResultEntryImpl.java 183 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/SearchResultReference.java 88 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/SearchResultReferenceImpl.java 47 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/WhoAmIExtendedResult.java 220 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/WhoAmIExtendedResultImpl.java 152 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/responses/package-info.java 3 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/AbstractSASLContext.java 248 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/AnonymousSASLBindRequest.java 162 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/CRAMMD5SASLBindRequest.java 276 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/DigestMD5SASLBindRequest.java 437 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/ExternalSASLBindRequest.java 191 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/GSSAPISASLBindRequest.java 303 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/GenericSASLBindRequest.java 176 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/NameCallbackHandler.java 42 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/PlainSASLBindRequest.java 321 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/SASLBindRequest.java 66 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/SASLContext.java 77 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/sasl/TextInputCallbackHandler.java 42 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AbstractMatchingRuleImpl.java 39 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AbstractOrderingMatchingRuleImpl.java 25 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AbstractSubstringMatchingRuleImpl.java 327 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AbstractSyntaxImpl.java 4 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AttributeType.java 233 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AttributeTypeSyntaxImpl.java 40 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AttributeUsage.java 26 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AuthPasswordExactEqualityMatchingRuleImpl.java 17 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/AuthPasswordSyntaxImpl.java 64 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/BinarySyntaxImpl.java 25 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleImpl.java 32 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/BitStringSyntaxImpl.java 44 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleImpl.java 17 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/BooleanSyntaxImpl.java 40 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleImpl.java 15 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleImpl.java 20 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleImpl.java 28 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleImpl.java 12 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleImpl.java 16 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleImpl.java 15 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java 20 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java 24 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseIgnoreListEqualityMatchingRuleImpl.java 12 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseIgnoreListSubstringMatchingRuleImpl.java 13 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleImpl.java 12 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleImpl.java 15 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CertificateListSyntaxImpl.java 26 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CertificatePairSyntaxImpl.java 26 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CertificateSyntaxImpl.java 26 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/ConflictingSchemaElementException.java 16 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CoreSchema.java 3585 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CoreSchemaImpl.java 643 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/CountryStringSyntaxImpl.java 35 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/DITContentRule.java 198 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/DITContentRuleSyntaxImpl.java 29 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/DITStructureRule.java 72 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/DITStructureRuleSyntaxImpl.java 34 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/DeliveryMethodSyntaxImpl.java 37 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java 41 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/DirectoryStringSyntaxImpl.java 26 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/DistinguishedNameEqualityMatchingRuleImpl.java 36 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/DistinguishedNameSyntaxImpl.java 17 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java 105 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/EnhancedGuideSyntaxImpl.java 46 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/EnumOrderingMatchingRule.java 21 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/EnumSyntaxImpl.java 42 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/EqualLengthApproximateMatchingRuleImpl.java 14 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/FacsimileNumberSyntaxImpl.java 57 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/FaxSyntaxImpl.java 26 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/GeneralizedTimeEqualityMatchingRuleImpl.java 8 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/GeneralizedTimeOrderingMatchingRuleImpl.java 8 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/GeneralizedTimeSyntaxImpl.java 343 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/GenerateCoreSchema.java 280 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/GuideSyntaxImpl.java 118 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/IA5StringSyntaxImpl.java 30 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/IntegerEqualityMatchingRuleImpl.java 17 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java 40 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/IntegerOrderingMatchingRuleImpl.java 14 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/IntegerSyntaxImpl.java 44 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/JPEGSyntaxImpl.java 26 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/KeywordEqualityMatchingRuleImpl.java 27 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/LDAPSyntaxDescriptionSyntaxImpl.java 54 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/MatchingRule.java 204 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/MatchingRuleImpl.java 69 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/MatchingRuleSyntaxImpl.java 41 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/MatchingRuleUse.java 95 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/MatchingRuleUseSyntaxImpl.java 44 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/NameAndOptionalUIDSyntaxImpl.java 33 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/NameForm.java 146 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/NameFormSyntaxImpl.java 53 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/NumericStringEqualityMatchingRuleImpl.java 14 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/NumericStringOrderingMatchingRuleImpl.java 12 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/NumericStringSubstringMatchingRuleImpl.java 12 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/NumericStringSyntaxImpl.java 37 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/OIDSyntaxImpl.java 23 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/ObjectClass.java 296 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/ObjectClassSyntaxImpl.java 33 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/ObjectClassType.java 9 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/ObjectIdentifierEqualityMatchingRuleImpl.java 40 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java 44 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/OctetStringEqualityMatchingRuleImpl.java 10 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/OctetStringOrderingMatchingRuleImpl.java 10 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/OctetStringSubstringMatchingRuleImpl.java 10 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/OctetStringSyntaxImpl.java 26 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/OtherMailboxSyntaxImpl.java 39 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/PostalAddressSyntaxImpl.java 29 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/PresentationAddressEqualityMatchingRuleImpl.java 16 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/PresentationAddressSyntaxImpl.java 22 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/PrintableStringSyntaxImpl.java 46 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/ProtocolInformationEqualityMatchingRuleImpl.java 16 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/ProtocolInformationSyntaxImpl.java 21 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/RegexSyntaxImpl.java 22 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/Schema.java 1117 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SchemaBuilder.java 1081 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SchemaCompatOptions.java 66 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SchemaConstants.java 330 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SchemaElement.java 57 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SchemaException.java 15 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SchemaUtils.java 341 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SubstringAssertionSyntaxImpl.java 34 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SupportedAlgorithmSyntaxImpl.java 27 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/Syntax.java 196 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/SyntaxImpl.java 63 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/TelephoneNumberEqualityMatchingRuleImpl.java 13 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/TelephoneNumberSubstringMatchingRuleImpl.java 13 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/TelephoneNumberSyntaxImpl.java 69 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/TeletexTerminalIdentifierSyntaxImpl.java 59 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/TelexNumberSyntaxImpl.java 53 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/UTCTimeSyntaxImpl.java 256 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/UUIDEqualityMatchingRuleImpl.java 32 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/UUIDOrderingMatchingRuleImpl.java 29 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/UUIDSyntaxImpl.java 25 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/UniqueMemberEqualityMatchingRuleImpl.java 12 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/UnknownSchemaElementException.java 12 ●●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/UserPasswordExactEqualityMatchingRuleImpl.java 17 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/UserPasswordSyntaxImpl.java 55 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/WordEqualityMatchingRuleImpl.java 27 ●●●● patch | view | raw | blame | history
sdk/src/org/opends/sdk/schema/package-info.java 3 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControlTestCase.java 74 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControlTestCase.java 95 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferReaderTestCase.java 62 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferWriterTestCase.java 86 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/GlobalTransportFactoryTestCase.java 68 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/LDAPTestCase.java 15 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/messages/MessagesTestCase.java 19 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/tools/ToolsTestCase.java 15 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/ASCIICharPropTestCase.java 183 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/Base64TestCase.java 238 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTestCase.java 195 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StringPrepProfileTestCase.java 119 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/UtilTestCase.java 14 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTestCase.java 477 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/AuthenticatedConnectionFactoryTestCase.java 62 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteSequenceTestCase.java 247 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringBuilderTestCase.java 296 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringTestCase.java 167 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/ConnectionFactoryTestCase.java 171 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/DNTestCase.java 997 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/EntryTestCase.java 119 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/FilterTestCase.java 219 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/HeartBeatConnectionFactoryTestCase.java 71 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/InternalConnectionFactoryTestCase.java 57 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPConnectionFactoryTestCase.java 56 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPServer.java 590 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPUrlTestCase.java 232 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTestCase.java 21 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/OpenDSTestCase.java 113 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/RDNTestCase.java 481 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/SdkTestCase.java 15 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/SortedEntryTest.java 88 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/SuiteRunner.java 8 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/SynchronousConnectionTestCase.java 164 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/TestCaseUtils.java 141 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/TestListener.java 459 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/TypesTestCase.java 156 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ByteSequenceReaderTestCase.java 18 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1InputStreamReaderTestCase.java 18 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1OutputStreamWriterTestCase.java 69 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ReaderTestCase.java 922 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1WriterTestCase.java 742 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/controls/ControlsTestCase.java 60 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryReaderTestCase.java 88 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFTestCase.java 16 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AbandonRequestTestCase.java 67 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AddRequestTestCase.java 71 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AnonymousSASLBindRequestTestCase.java 68 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/BindRequestTestCase.java 71 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestTestCase.java 69 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CompareRequestTestCase.java 71 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DeleteRequestTestCase.java 70 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DigestMD5SASLBindRequestTestCase.java 71 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExtendedRequestTestCase.java 20 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExternalSASLBindRequestTestCase.java 67 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GSSAPISASLBindRequestTestCase.java 70 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GenericBindRequestTestCase.java 77 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyDNRequestTestCase.java 69 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyRequestTestCase.java 75 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/PlainSASLBindRequestTestCase.java 69 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestTestCase.java 136 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestsTestCase.java 16 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/SimpleBindRequestTestCase.java 68 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/UnbindRequestTestCase.java 66 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/responses/ResponsesTestCase.java 16 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AbstractSchemaElementTestCase.java 209 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/ApproximateMatchingRuleTest.java 46 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeSyntaxTest.java 22 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeTest.java 608 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleTest.java 7 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringSyntaxTest.java 14 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleTest.java 24 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleTest.java 6 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleTest.java 12 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleTest.java 118 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleTest.java 3 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleTest.java 115 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleTest.java 6 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleTest.java 9 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java 155 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleTest.java 3 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleTest.java 150 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/DITContentRuleSyntaxTest.java 58 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/EnumSyntaxTestCase.java 156 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GeneralizedTimeSyntaxTest.java 31 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GuideSyntaxTest.java 25 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/IA5StringSyntaxTest.java 11 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/LDAPSyntaxTest.java 49 ●●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleSyntaxTest.java 22 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleTest.java 79 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleUseSyntaxTest.java 30 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OrderingMatchingRuleTest.java 83 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OtherMailboxSyntaxTest.java 12 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/RegexSyntaxTestCase.java 61 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SchemaUtilsTest.java 54 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstitutionSyntaxTestCase.java 123 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstringMatchingRuleTest.java 246 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SyntaxTestCase.java 44 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/TelexSyntaxTest.java 14 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UTCTimeSyntaxTest.java 28 ●●●● patch | view | raw | blame | history
sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UUIDSyntaxTest.java 25 ●●●● patch | view | raw | blame | history
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,6 +36,7 @@
    <!-- General server-wide properties -->
    <property name="src.dir" location="src" />
    <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" />
@@ -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">
        <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,6 +905,13 @@
        <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>
@@ -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}" />
sdk/examples/org/opends/sdk/examples/DummyServer.java
New file
@@ -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);
  }
}
sdk/examples/org/opends/sdk/examples/package-info.java
old mode 100755 new mode 100644 copy from sdk/src/org/opends/sdk/sasl/package-info.java copy to sdk/examples/org/opends/sdk/examples/package-info.java
File was copied from sdk/src/org/opends/sdk/sasl/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;
sdk/ext/checkstyle/check-src.xml
New file
@@ -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>
sdk/ext/checkstyle/check-tests.xml
New file
@@ -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>
sdk/ext/checkstyle/checkstyle-all-4.1.jar
Binary files differ
sdk/ext/checkstyle/checkstyle-all-5.1.jar
Binary files differ
sdk/ext/checkstyle/opends-checkstyle.xml
File was deleted
sdk/ext/checkstyle/opends-doctarget-checkstyle.xml
File was deleted
sdk/ext/checkstyle/opends-functest-checkstyle.xml
File was deleted
sdk/ext/checkstyle/opends-unittest-checkstyle.xml
File was deleted
sdk/ext/checkstyle/src-header.txt
sdk/lib/grizzly.jar
Binary files differ
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
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%
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
sdk/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControl.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControl.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/controls/RealAttributesOnlyRequestControl.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/controls/VirtualAttributesOnlyRequestControl.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/controls/package-info.java
old mode 100755 new mode 100644 copy from sdk/src/org/opends/sdk/sasl/package-info.java copy to sdk/src/com/sun/opends/sdk/controls/package-info.java
File was copied from sdk/src/org/opends/sdk/sasl/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;
sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedRequest.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/extensions/GetConnectionIDExtendedResult.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/extensions/GetSymmetricKeyExtendedRequest.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedRequest.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateExtendedResult.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperation.java
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java copy to sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperation.java
File was copied from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.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();
}
sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationContainer.java
copy from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.java copy to sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationContainer.java
File was copied from sdk/src/org/opends/sdk/sasl/PasswordCallbackHandler.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();
}
sdk/src/com/sun/opends/sdk/extensions/PasswordPolicyStateOperationType.java
New file
@@ -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;
  }
}
sdk/src/com/sun/opends/sdk/extensions/package-info.java
old mode 100755 new mode 100644 copy from sdk/src/org/opends/sdk/sasl/package-info.java copy to sdk/src/com/sun/opends/sdk/extensions/package-info.java
File was copied from sdk/src/org/opends/sdk/sasl/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;
sdk/src/com/sun/opends/sdk/ldap/ASN1BufferReader.java
File was renamed from sdk/src/com/sun/opends/sdk/ldap/ASN1StreamReader.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(
        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)
    return !((state == ELEMENT_READ_STATE_NEED_TYPE) && !needTypeState(true))
        && !((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();
        && !((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;
  }
sdk/src/com/sun/opends/sdk/ldap/ASN1BufferWriter.java
File was renamed from sdk/src/com/sun/opends/sdk/ldap/ASN1StreamWriter.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)
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();
  }
}
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);
  }
}
sdk/src/com/sun/opends/sdk/ldap/AbstractLDAPTransport.java
File was deleted
sdk/src/com/sun/opends/sdk/ldap/GlobalTransportFactory.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPListenerOptions.java
New file
@@ -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;
  }
}
sdk/src/com/sun/opends/sdk/ldap/GrizzlyLDAPOptions.java
New file
@@ -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;
  }
}
sdk/src/com/sun/opends/sdk/ldap/InternalConnection.java
New file
@@ -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;
  }
}
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;
  }
}
sdk/src/com/sun/opends/sdk/ldap/LDAPClientFilter.java
New file
@@ -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);
  }
}
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);
  }
}
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
{
  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()
final class LDAPConnection extends AbstractAsynchronousConnection implements
    AsynchronousConnection
    {
      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,51 +110,66 @@
  /**
   * {@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)
      {
        synchronized (writeLock)
      // 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)
          {
            return;
        return new CompletedFutureResult<Void>(ErrorResultException
            .wrap(connectionInvalidReason), messageID);
          }
          if (pendingBindOrStartTLS > 0)
      if (bindOrStartTLSInProgress)
          {
            // This is not allowed. We will just ignore this
            // abandon request.
        final Result errorResult = Responses.newResult(
            ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
            "Bind or Start TLS operation in progress");
        return new CompletedFutureResult<Void>(ErrorResultException
            .wrap(errorResult), messageID);
          }
    }
          try
          {
            LDAPEncoder.encodeAbandonRequest(asn1Writer, messageID,
                request);
            asn1Writer.flush();
          }
          catch (IOException e)
      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
      try
          {
            // 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);
          }
        }
        ldapWriter.abandonRequest(asn1Writer, messageID, request);
        connection.write(asn1Writer.getBuffer(), null);
        return new CompletedFutureResult<Void>((Void) null, messageID);
      }
      finally
      {
        connFactory.releaseASN1Writer(asn1Writer);
        asn1Writer.recycle();
      }
    }
    catch (final IOException e)
    {
      // 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);
    }
  }
@@ -747,54 +177,55 @@
  /**
   * {@inheritDoc}
   */
  public FutureResult<Result> add(AddRequest request,
      ResultHandler<Result> handler)
  public FutureResult<Result> add(final AddRequest 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);
    try
    {
      synchronized (writeLock)
    synchronized (stateLock)
      {
        if (connectionInvalidReason != null)
        {
          future.adaptErrorResult(connectionInvalidReason);
          return future;
        }
        if (pendingBindOrStartTLS > 0)
      if (bindOrStartTLSInProgress)
        {
          future.setResultOrError(Responses.newResult(
              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
        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();
      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
      try
      {
        ldapWriter.addRequest(asn1Writer, messageID, request);
        connection.write(asn1Writer.getBuffer(), null);
        }
        catch (IOException e)
      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?
          Result errorResult = Responses.newResult(
      final Result errorResult = Responses.newResult(
              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
          connectionErrorOccurred(errorResult);
          future.adaptErrorResult(errorResult);
        }
      }
    }
    finally
    {
      connFactory.releaseASN1Writer(asn1Writer);
    }
    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,25 +247,44 @@
  /**
   * {@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
    {
      synchronized (writeLock)
      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 (pendingBindOrStartTLS > 0)
      if (bindOrStartTLSInProgress)
        {
          future.setResultOrError(Responses.newBindResult(
              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
@@ -851,65 +300,36 @@
        }
        pendingRequests.put(messageID, future);
        pendingBindOrStartTLS = messageID;
      bindOrStartTLSInProgress = true;
    }
        try
        {
          if (request instanceof SASLBindRequest<?>)
          {
      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
            try
            {
              SASLBindRequest<?> saslBind = (SASLBindRequest<?>) request;
              SASLContext saslContext = saslBind
                  .getClientContext(serverAddress.getHostName());
              future.setSASLContext(saslContext);
              LDAPEncoder.encodeBindRequest(asn1Writer, messageID, 3,
                  saslBind, saslContext.getSASLCredentials());
        // 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);
            }
            catch (SaslException e)
      finally
            {
              // 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;
        asn1Writer.recycle();
            }
          }
          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)
    catch (final 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(
      final Result errorResult = Responses.newResult(
              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
          connectionErrorOccurred(errorResult);
          future.adaptErrorResult(errorResult);
        }
      }
    }
    finally
    {
      connFactory.releaseASN1Writer(asn1Writer);
    }
    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,25 +355,22 @@
  /**
   * {@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);
    try
    {
      synchronized (writeLock)
    synchronized (stateLock)
      {
        if (connectionInvalidReason != null)
        {
          future.adaptErrorResult(connectionInvalidReason);
          return future;
        }
        if (pendingBindOrStartTLS > 0)
      if (bindOrStartTLSInProgress)
        {
          future.setResultOrError(Responses.newCompareResult(
              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
@@ -962,29 +378,32 @@
          return future;
        }
        pendingRequests.put(messageID, future);
    }
        try
        {
          LDAPEncoder.encodeCompareRequest(asn1Writer, messageID,
              request);
          asn1Writer.flush();
      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
      try
      {
        ldapWriter.compareRequest(asn1Writer, messageID, request);
        connection.write(asn1Writer.getBuffer(), null);
        }
        catch (IOException e)
      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?
          Result errorResult = Responses.newResult(
      final Result errorResult = Responses.newResult(
              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
          connectionErrorOccurred(errorResult);
          future.adaptErrorResult(errorResult);
        }
      }
    }
    finally
    {
      connFactory.releaseASN1Writer(asn1Writer);
    }
    return future;
  }
@@ -994,55 +413,55 @@
  /**
   * {@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);
    try
    {
      synchronized (writeLock)
    synchronized (stateLock)
      {
        if (connectionInvalidReason != null)
        {
          future.adaptErrorResult(connectionInvalidReason);
          return future;
        }
        if (pendingBindOrStartTLS > 0)
      if (bindOrStartTLSInProgress)
        {
          future.setResultOrError(Responses.newResult(
              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
        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();
      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
      try
      {
        ldapWriter.deleteRequest(asn1Writer, messageID, request);
        connection.write(asn1Writer.getBuffer(), null);
        }
        catch (IOException e)
      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?
          Result errorResult = Responses.newResult(
      final Result errorResult = Responses.newResult(
              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
          connectionErrorOccurred(errorResult);
          future.adaptErrorResult(errorResult);
        }
      }
    }
    finally
    {
      connFactory.releaseASN1Writer(asn1Writer);
    }
    return future;
  }
@@ -1052,74 +471,73 @@
  /**
   * {@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);
    try
    {
      synchronized (writeLock)
    synchronized (stateLock)
      {
        if (connectionInvalidReason != null)
        {
          future.adaptErrorResult(connectionInvalidReason);
          return future;
        }
        if (pendingBindOrStartTLS > 0)
      if (bindOrStartTLSInProgress)
        {
          future.setResultOrError(request.getExtendedOperation()
              .decodeResponse(ResultCode.OPERATIONS_ERROR, "",
        future.setResultOrError(request.getResultDecoder()
            .adaptExtendedErrorResult(ResultCode.OPERATIONS_ERROR, "",
                  "Bind or Start TLS operation in progress"));
          return future;
        }
        if (request.getRequestName().equals(
            StartTLSRequest.OID_START_TLS_REQUEST))
      if (request.getOID().equals(StartTLSExtendedRequest.OID))
        {
          if (!pendingRequests.isEmpty())
          {
            future.setResultOrError(request.getExtendedOperation()
                .decodeResponse(ResultCode.OPERATIONS_ERROR, "",
          future.setResultOrError(request.getResultDecoder()
              .adaptExtendedErrorResult(ResultCode.OPERATIONS_ERROR, "",
                    "There are pending operations on this connection"));
            return future;
          }
          if (isTLSEnabled())
          {
            future.setResultOrError(request.getExtendedOperation()
                .decodeResponse(ResultCode.OPERATIONS_ERROR, "",
          future.setResultOrError(request.getResultDecoder()
              .adaptExtendedErrorResult(ResultCode.OPERATIONS_ERROR, "",
                    "This connection is already TLS enabled"));
          }
          pendingBindOrStartTLS = messageID;
        bindOrStartTLSInProgress = true;
        }
        pendingRequests.put(messageID, future);
    }
        try
        {
          LDAPEncoder.encodeExtendedRequest(asn1Writer, messageID,
              request);
          asn1Writer.flush();
      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
      try
      {
        ldapWriter.extendedRequest(asn1Writer, messageID, request);
        connection.write(asn1Writer.getBuffer(), null);
        }
        catch (IOException e)
      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?
          Result errorResult = Responses.newResult(
      final Result errorResult = Responses.newResult(
              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
          connectionErrorOccurred(errorResult);
          future.adaptErrorResult(errorResult);
        }
      }
    }
    finally
    {
      connFactory.releaseASN1Writer(asn1Writer);
    }
    return future;
  }
@@ -1129,55 +547,75 @@
  /**
   * {@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;
  }
    try
  /**
   * {@inheritDoc}
   */
  public boolean isValid()
    {
      synchronized (writeLock)
    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 (pendingBindOrStartTLS > 0)
      if (bindOrStartTLSInProgress)
        {
          future.setResultOrError(Responses.newResult(
              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
        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();
      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
      try
      {
        ldapWriter.modifyRequest(asn1Writer, messageID, request);
        connection.write(asn1Writer.getBuffer(), null);
        }
        catch (IOException e)
      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?
          Result errorResult = Responses.newResult(
      final Result errorResult = Responses.newResult(
              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
          connectionErrorOccurred(errorResult);
          future.adaptErrorResult(errorResult);
        }
      }
    }
    finally
    {
      connFactory.releaseASN1Writer(asn1Writer);
    }
    return future;
  }
@@ -1187,55 +625,55 @@
  /**
   * {@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);
    try
    {
      synchronized (writeLock)
    synchronized (stateLock)
      {
        if (connectionInvalidReason != null)
        {
          future.adaptErrorResult(connectionInvalidReason);
          return future;
        }
        if (pendingBindOrStartTLS > 0)
      if (bindOrStartTLSInProgress)
        {
          future.setResultOrError(Responses.newResult(
              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
        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();
      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
      try
      {
        ldapWriter.modifyDNRequest(asn1Writer, messageID, request);
        connection.write(asn1Writer.getBuffer(), null);
        }
        catch (IOException e)
      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?
          Result errorResult = Responses.newResult(
      final Result errorResult = Responses.newResult(
              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
          connectionErrorOccurred(errorResult);
          future.adaptErrorResult(errorResult);
        }
      }
    }
    finally
    {
      connFactory.releaseASN1Writer(asn1Writer);
    }
    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,96 +695,115 @@
  /**
   * {@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);
    try
    {
      synchronized (writeLock)
    synchronized (stateLock)
      {
        if (connectionInvalidReason != null)
        {
          future.adaptErrorResult(connectionInvalidReason);
          return future;
        }
        if (pendingBindOrStartTLS > 0)
      if (bindOrStartTLSInProgress)
        {
          future.setResultOrError(Responses.newResult(
              ResultCode.OPERATIONS_ERROR).setDiagnosticMessage(
        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();
      final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
      try
      {
        ldapWriter.searchRequest(asn1Writer, messageID, request);
        connection.write(asn1Writer.getBuffer(), null);
        }
        catch (IOException e)
      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?
          Result errorResult = Responses.newResult(
      final Result errorResult = Responses.newResult(
              ResultCode.CLIENT_SIDE_ENCODING_ERROR).setCause(e);
          connectionErrorOccurred(errorResult);
          future.adaptErrorResult(errorResult);
        }
      }
    }
    finally
    {
      connFactory.releaseASN1Writer(asn1Writer);
    }
    return future;
  }
  /**
   * 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,29 +833,30 @@
    }
    // 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();
        }
        catch (IOException e)
          final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
          try
        {
          // Underlying channel probably blown up. Just ignore.
            ldapWriter.abandonRequest(asn1Writer, messageID, abandon);
            connection.write(asn1Writer.getBuffer(), null);
        }
        finally
        {
          connFactory.releaseASN1Writer(asn1Writer);
            asn1Writer.recycle();
          }
        }
        catch (final IOException e)
        {
          // Underlying channel probably blown up. Just ignore.
        }
      }
@@ -1407,45 +865,34 @@
    pendingRequests.clear();
    // Now try cleanly closing the connection if possible.
    // Only send unbind if specified.
    if (unbindRequest != null)
    {
    try
    {
      ASN1StreamWriter asn1Writer = connFactory
          .getASN1Writer(streamWriter);
      if (unbindRequest == null)
      {
        unbindRequest = Requests.newUnbindRequest();
      }
        final ASN1BufferWriter asn1Writer = ASN1BufferWriter.getWriter();
      try
      {
        LDAPEncoder.encodeUnbindRequest(asn1Writer, nextMsgID
            .getAndIncrement(), unbindRequest);
        asn1Writer.flush();
          ldapWriter.unbindRequest(asn1Writer, nextMsgID.getAndIncrement(),
              unbindRequest);
          connection.write(asn1Writer.getBuffer(), null);
      }
      finally
      {
        connFactory.releaseASN1Writer(asn1Writer);
          asn1Writer.recycle();
      }
    }
    catch (IOException e)
      catch (final 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,16 +900,15 @@
    // 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));
@@ -1472,186 +918,102 @@
  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()
    if (isClosed)
  {
    StreamWriter writer = connection.getStreamWriter();
    FilterChain currentFilterChain = (FilterChain) connection
        .getProcessor();
    for (Filter filter : currentFilterChain)
    {
      if (filter instanceof StreamTransformerFilter)
      {
        writer = ((StreamTransformerFilter) filter)
            .getStreamWriter(writer);
      }
    }
    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)
    {
      if (result.getResultCode() == ResultCode.SUCCESS)
      {
        StartTLSRequest request = (StartTLSRequest) future.getRequest();
        try
        {
          startTLS(request.getSSLContext());
        }
        catch (ErrorResultException e)
        {
          future.adaptErrorResult(e.getResult());
      // Don't notify after connection is closed.
          return;
        }
      }
      pendingBindOrStartTLS = -1;
    }
    future.setResultOrError(decodedResponse);
  }
  private void handleIncorrectResponse(
      AbstractLDAPFutureResultImpl<?> pendingRequest)
    for (final ConnectionEventListener listener : listeners)
  {
    // 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);
  }
}
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
{
  private final class LDAPTransport extends AbstractLDAPTransport
public final class LDAPConnectionFactoryImpl extends AbstractConnectionFactory
    implements ConnectionFactory
  {
    @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);
            }
            catch (ErrorResultException errorResult)
              connection.startTLS(options.getSSLContext(),
                  new EmptyCompletionHandler<SSLEngine>()
            {
              try
                    @Override
                    public void completed(final SSLEngine result)
              {
                connection.close();
                connection = null;
              }
              catch (Exception ignored)
              {
              }
              throw errorResult;
            }
                      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 (final IOException ioe)
            {
              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());
    TCPNIOTransport tmpTransport = null;
    if (options instanceof GrizzlyLDAPOptions)
    {
      tmpTransport = ((GrizzlyLDAPOptions) options).getTCPNIOTransport();
  }
  private LDAPConnectionFactoryImpl(String host, int port,
      LDAPConnectionOptions options, TCPNIOTransport transport)
    if (tmpTransport == null)
  {
    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)
    {
      this.sslEngineConfigurator = null;
      this.sslFilter = null;
      tmpTransport = GlobalTransportFactory.getInstance().createTCPTransport();
    }
    else
    {
      this.sslEngineConfigurator = new SSLEngineConfigurator(
          this.options.getSSLContext(), true, false, false);
      this.sslFilter = new SSLFilter(sslEngineConfigurator,
          sslHandshaker);
    }
    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);
  }
}
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.
  }
}
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);
  }
}
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;
  }
}
sdk/src/com/sun/opends/sdk/ldap/LDAPListenerImpl.java
New file
@@ -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;
  }
}
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;
}
sdk/src/com/sun/opends/sdk/ldap/LDAPReader.java
New file
@@ -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);
  }
}
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);
      }
    }
  }
  /**
   * {@inheritDoc}
   */
  Result newErrorResult(ResultCode resultCode,
      String diagnosticMessage, Throwable cause)
        if (!searchResultHandler.handleReference(reference))
  {
    return Responses.newResult(resultCode).setDiagnosticMessage(
        diagnosticMessage).setCause(cause);
          searchResultHandler = null;
        }
      }
    }
    return true;
  }
  @Override
  public String toString()
  {
    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);
  }
}
sdk/src/com/sun/opends/sdk/ldap/LDAPServerFilter.java
New file
@@ -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);
    }
  }
}
sdk/src/com/sun/opends/sdk/ldap/LDAPUtils.java
File was renamed from sdk/src/org/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));
        }
        if (reader.hasNextElement()
            && (reader.peekType() == TYPE_SUBFINAL))
          while (reader.hasNextElement() && (reader.peekType() == TYPE_SUBANY));
        }
        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);
  }
sdk/src/com/sun/opends/sdk/ldap/LDAPWriter.java
New file
@@ -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();
  }
}
sdk/src/com/sun/opends/sdk/ldap/SASLDecoderTransformer.java
New file
@@ -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());
    }
  }
}
sdk/src/com/sun/opends/sdk/ldap/SASLEncoderTransformer.java
New file
@@ -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());
    }
  }
}
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));
  }
}
sdk/src/com/sun/opends/sdk/ldap/SASLStreamReader.java
File was deleted
sdk/src/com/sun/opends/sdk/ldap/SASLStreamWriter.java
File was deleted
sdk/src/com/sun/opends/sdk/ldap/TimeoutChecker.java
New file
@@ -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();
    }
  }
}
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());
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());
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,11 +47,11 @@
  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,
    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;
sdk/src/com/sun/opends/sdk/ldap/package-info.java
old mode 100755 new mode 100644 copy from sdk/src/org/opends/sdk/sasl/package-info.java copy to sdk/src/com/sun/opends/sdk/ldap/package-info.java
File was copied from sdk/src/org/opends/sdk/sasl/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;
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
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)
    {
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
   * @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;
  }
  /**
   * 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 boolean getBooleanValue() throws ArgumentException
  public void setRequired(final boolean isRequired)
  {
    if (values.isEmpty())
    {
      LocalizableMessage message = ERR_ARG_NO_BOOLEAN_VALUE.get(name);
      throw new ArgumentException(message);
    this.isRequired = 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"))
  /**
   * 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)
    {
      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);
    this.valuePlaceholder = valuePlaceholder;
    }
    if (iterator.hasNext())
  /**
   * 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)
    {
      LocalizableMessage message = ERR_ARG_BOOLEAN_MULTIPLE_VALUES.get(name);
      throw new ArgumentException(message);
    }
    else
    {
      return booleanValue;
    }
    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();
  }
}
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;
@@ -61,7 +51,7 @@
   * @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;
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,7 +54,7 @@
  private List<Argument> args = null;
  // Governs groups position within usage statement
  private Integer priority;
  private final Integer priority;
@@ -66,11 +65,11 @@
   *          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,6 +91,41 @@
  /**
   * Adds an argument to this group.
   *
   * @param arg
   *          to add
   * @return boolean where true indicates the add was successful
   */
  boolean addArgument(final Argument arg)
  {
    boolean success = false;
    if (arg != null)
    {
      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 (final Iterator<Argument> it = this.args.iterator(); it.hasNext();)
      {
        final Argument a = it.next();
        if (newShort != null && newShort.equals(a.getShortIdentifier())
            || newLong != null && newLong.equals(a.getLongIdentifier()))
        {
          it.remove();
          break;
        }
      }
      success = this.args.add(arg);
    }
    return success;
  }
  /**
   * Indicates whether this group contains any members.
   * 
   * @return boolean where true means this group contains members
@@ -143,12 +140,11 @@
  /**
   * Indicates whether this group contains any non-hidden members.
   * 
   * @return boolean where true means this group contains non-hidden
   *         members
   * @return boolean where true means this group contains non-hidden members
   */
  boolean containsNonHiddenArguments()
  {
    for (Argument arg : args)
    for (final Argument arg : args)
    {
      if (!arg.isHidden())
      {
@@ -161,36 +157,25 @@
  /**
   * Adds an argument to this group.
   * Gets the list of arguments associated with this group.
   * 
   * @param arg
   *          to add
   * @return boolean where true indicates the add was successful
   * @return list of associated arguments
   */
  boolean addArgument(Argument arg)
  List<Argument> getArguments()
  {
    boolean success = false;
    if (arg != null)
    {
      Character newShort = arg.getShortIdentifier();
      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();)
      {
        Argument a = it.next();
        if (newShort != null && newShort.equals(a.getShortIdentifier())
            || newLong != null && newLong.equals(a.getLongIdentifier()))
        {
          it.remove();
          break;
        }
    return Collections.unmodifiableList(args);
      }
      success = this.args.add(arg);
    }
    return success;
  /**
   * Gets the description for this group of arguments.
   *
   * @return description for this argument group
   */
  LocalizableMessage getDescription()
  {
    return this.description;
  }
@@ -202,9 +187,22 @@
   *          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;
  }
}
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;
    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);
    addArgument(argument, ioArgGroup);
        }
        continue;
  /**
   * 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);
      }
      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)
  /**
   * 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()
        {
          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);
        }
      }
    }
    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 truncated after the above file
sdk/src/com/sun/opends/sdk/tools/ArgumentParserConnectionFactory.java sdk/src/com/sun/opends/sdk/tools/AuthenticatedConnectionFactory.java sdk/src/com/sun/opends/sdk/tools/BooleanArgument.java sdk/src/com/sun/opends/sdk/tools/CLIException.java sdk/src/com/sun/opends/sdk/tools/ConsoleApplication.java sdk/src/com/sun/opends/sdk/tools/DataSource.java sdk/src/com/sun/opends/sdk/tools/DistrustAllTrustManager.java (deleted) sdk/src/com/sun/opends/sdk/tools/FileBasedArgument.java sdk/src/com/sun/opends/sdk/tools/HostnameMismatchCertificateException.java (deleted) sdk/src/com/sun/opends/sdk/tools/IntegerArgument.java sdk/src/com/sun/opends/sdk/tools/LDAPCompare.java sdk/src/com/sun/opends/sdk/tools/LDAPModify.java sdk/src/com/sun/opends/sdk/tools/LDAPPasswordModify.java sdk/src/com/sun/opends/sdk/tools/LDAPSearch.java sdk/src/com/sun/opends/sdk/tools/ModRate.java sdk/src/com/sun/opends/sdk/tools/MultiChoiceArgument.java sdk/src/com/sun/opends/sdk/tools/MultiColumnPrinter.java sdk/src/com/sun/opends/sdk/tools/PerformanceRunner.java sdk/src/com/sun/opends/sdk/tools/PromptingTrustManager.java sdk/src/com/sun/opends/sdk/tools/SearchRate.java sdk/src/com/sun/opends/sdk/tools/SelectableCertificateKeyManager.java (deleted) sdk/src/com/sun/opends/sdk/tools/StringArgument.java sdk/src/com/sun/opends/sdk/tools/ToolConstants.java sdk/src/com/sun/opends/sdk/tools/TrustAllTrustManager.java (deleted) sdk/src/com/sun/opends/sdk/tools/TrustStoreTrustManager.java (deleted) sdk/src/com/sun/opends/sdk/tools/Utils.java sdk/src/com/sun/opends/sdk/tools/package-info.java sdk/src/com/sun/opends/sdk/util/ASCIICharProp.java sdk/src/com/sun/opends/sdk/util/AbstractFutureResult.java sdk/src/com/sun/opends/sdk/util/Base64.java sdk/src/com/sun/opends/sdk/util/ByteSequenceOutputStream.java sdk/src/com/sun/opends/sdk/util/Collections2.java sdk/src/com/sun/opends/sdk/util/CompletedFutureResult.java sdk/src/com/sun/opends/sdk/util/Function.java sdk/src/com/sun/opends/sdk/util/Functions.java sdk/src/com/sun/opends/sdk/util/FutureResultTransformer.java sdk/src/com/sun/opends/sdk/util/Iterables.java sdk/src/com/sun/opends/sdk/util/Iterators.java sdk/src/com/sun/opends/sdk/util/LocalizableMessageDescriptor.java sdk/src/com/sun/opends/sdk/util/Platform.java sdk/src/com/sun/opends/sdk/util/Predicate.java sdk/src/com/sun/opends/sdk/util/RecursiveFutureResult.java sdk/src/com/sun/opends/sdk/util/SSLUtils.java (deleted) sdk/src/com/sun/opends/sdk/util/SizeLimitInputStream.java sdk/src/com/sun/opends/sdk/util/StaticUtils.java sdk/src/com/sun/opends/sdk/util/StringPrepProfile.java sdk/src/com/sun/opends/sdk/util/SubstringReader.java sdk/src/com/sun/opends/sdk/util/Validator.java sdk/src/com/sun/opends/sdk/util/package-info.java sdk/src/org/opends/sdk/AVA.java sdk/src/org/opends/sdk/AbstractAsynchronousConnection.java sdk/src/org/opends/sdk/AbstractAttribute.java sdk/src/org/opends/sdk/AbstractConnection.java sdk/src/org/opends/sdk/AbstractConnectionFactory.java sdk/src/org/opends/sdk/AbstractEntry.java sdk/src/org/opends/sdk/AbstractFilterVisitor.java sdk/src/org/opends/sdk/AbstractMapEntry.java sdk/src/org/opends/sdk/Assertion.java sdk/src/org/opends/sdk/AssertionFailureException.java sdk/src/org/opends/sdk/AsynchronousConnection.java sdk/src/org/opends/sdk/Attribute.java sdk/src/org/opends/sdk/AttributeDescription.java sdk/src/org/opends/sdk/AttributeFactory.java sdk/src/org/opends/sdk/AuthenticatedConnectionFactory.java sdk/src/org/opends/sdk/AuthenticationException.java sdk/src/org/opends/sdk/AuthorizationException.java sdk/src/org/opends/sdk/ByteSequence.java sdk/src/org/opends/sdk/ByteSequenceReader.java sdk/src/org/opends/sdk/ByteString.java sdk/src/org/opends/sdk/ByteStringBuilder.java sdk/src/org/opends/sdk/CancelledResultException.java sdk/src/org/opends/sdk/ConditionResult.java sdk/src/org/opends/sdk/Connection.java sdk/src/org/opends/sdk/ConnectionEventListener.java sdk/src/org/opends/sdk/ConnectionException.java sdk/src/org/opends/sdk/ConnectionFactory.java sdk/src/org/opends/sdk/ConnectionPool.java sdk/src/org/opends/sdk/ConnectionSecurityLayer.java sdk/src/org/opends/sdk/Connections.java sdk/src/org/opends/sdk/ConstraintViolationException.java sdk/src/org/opends/sdk/DN.java sdk/src/org/opends/sdk/DecodeException.java sdk/src/org/opends/sdk/DecodeOptions.java sdk/src/org/opends/sdk/DereferenceAliasesPolicy.java sdk/src/org/opends/sdk/Entry.java sdk/src/org/opends/sdk/EntryFactory.java sdk/src/org/opends/sdk/EntryNotFoundException.java sdk/src/org/opends/sdk/ErrorResultException.java sdk/src/org/opends/sdk/ErrorResultIOException.java sdk/src/org/opends/sdk/FailoverLoadBalancingAlgorithm.java sdk/src/org/opends/sdk/Filter.java sdk/src/org/opends/sdk/FilterVisitor.java sdk/src/org/opends/sdk/FutureResult.java sdk/src/org/opends/sdk/HeartBeatConnectionFactory.java sdk/src/org/opends/sdk/IntermediateResponseHandler.java sdk/src/org/opends/sdk/InternalConnectionFactory.java sdk/src/org/opends/sdk/KeyManagers.java sdk/src/org/opends/sdk/LDAPClientContext.java sdk/src/org/opends/sdk/LDAPConnectionFactory.java sdk/src/org/opends/sdk/LDAPListener.java sdk/src/org/opends/sdk/LDAPListenerOptions.java sdk/src/org/opends/sdk/LDAPOptions.java sdk/src/org/opends/sdk/LDAPUrl.java sdk/src/org/opends/sdk/LinkedAttribute.java sdk/src/org/opends/sdk/LinkedHashMapEntry.java sdk/src/org/opends/sdk/LoadBalancingAlgorithm.java sdk/src/org/opends/sdk/LoadBalancingConnectionFactory.java sdk/src/org/opends/sdk/LocalizableException.java sdk/src/org/opends/sdk/LocalizableMessage.java sdk/src/org/opends/sdk/LocalizableMessageBuilder.java sdk/src/org/opends/sdk/LocalizedIllegalArgumentException.java sdk/src/org/opends/sdk/Matcher.java sdk/src/org/opends/sdk/Modification.java sdk/src/org/opends/sdk/ModificationType.java sdk/src/org/opends/sdk/MultipleEntriesFoundException.java sdk/src/org/opends/sdk/RDN.java sdk/src/org/opends/sdk/ReferralException.java sdk/src/org/opends/sdk/ResultCode.java sdk/src/org/opends/sdk/ResultHandler.java sdk/src/org/opends/sdk/RootDSE.java sdk/src/org/opends/sdk/SSLContextBuilder.java sdk/src/org/opends/sdk/SchemaResolver.java sdk/src/org/opends/sdk/SearchResultHandler.java sdk/src/org/opends/sdk/SearchScope.java sdk/src/org/opends/sdk/ServerConnection.java sdk/src/org/opends/sdk/ServerConnectionFactory.java sdk/src/org/opends/sdk/SortKey.java sdk/src/org/opends/sdk/SortedEntry.java (deleted) sdk/src/org/opends/sdk/SynchronousConnection.java sdk/src/org/opends/sdk/TimeoutResultException.java sdk/src/org/opends/sdk/TreeMapEntry.java sdk/src/org/opends/sdk/TrustManagers.java sdk/src/org/opends/sdk/Types.java sdk/src/org/opends/sdk/asn1/ASN1.java sdk/src/org/opends/sdk/asn1/ASN1ByteSequenceReader.java sdk/src/org/opends/sdk/asn1/ASN1Constants.java sdk/src/org/opends/sdk/asn1/ASN1InputStreamReader.java sdk/src/org/opends/sdk/asn1/ASN1OutputStreamWriter.java sdk/src/org/opends/sdk/asn1/ASN1Reader.java sdk/src/org/opends/sdk/asn1/ASN1Writer.java sdk/src/org/opends/sdk/asn1/AbstractASN1Reader.java sdk/src/org/opends/sdk/asn1/AbstractASN1Writer.java sdk/src/org/opends/sdk/asn1/package-info.java sdk/src/org/opends/sdk/controls/AccountUsabilityControl.java (deleted) sdk/src/org/opends/sdk/controls/AssertionControl.java (deleted) sdk/src/org/opends/sdk/controls/AssertionRequestControl.java sdk/src/org/opends/sdk/controls/AuthorizationIdentityControl.java (deleted) sdk/src/org/opends/sdk/controls/AuthorizationIdentityRequestControl.java sdk/src/org/opends/sdk/controls/AuthorizationIdentityResponseControl.java sdk/src/org/opends/sdk/controls/Control.java sdk/src/org/opends/sdk/controls/ControlDecoder.java sdk/src/org/opends/sdk/controls/EntryChangeNotificationControl.java (deleted) sdk/src/org/opends/sdk/controls/EntryChangeNotificationResponseControl.java sdk/src/org/opends/sdk/controls/GenericControl.java sdk/src/org/opends/sdk/controls/GetEffectiveRightsRequestControl.java sdk/src/org/opends/sdk/controls/ManageDsaITRequestControl.java sdk/src/org/opends/sdk/controls/MatchedValuesControl.java (deleted) sdk/src/org/opends/sdk/controls/MatchedValuesRequestControl.java sdk/src/org/opends/sdk/controls/PagedResultsControl.java (deleted) sdk/src/org/opends/sdk/controls/PasswordExpiredControl.java (deleted) sdk/src/org/opends/sdk/controls/PasswordExpiredResponseControl.java sdk/src/org/opends/sdk/controls/PasswordExpiringControl.java (deleted) sdk/src/org/opends/sdk/controls/PasswordExpiringResponseControl.java sdk/src/org/opends/sdk/controls/PasswordPolicyControl.java (deleted) sdk/src/org/opends/sdk/controls/PasswordPolicyErrorType.java sdk/src/org/opends/sdk/controls/PasswordPolicyRequestControl.java sdk/src/org/opends/sdk/controls/PasswordPolicyResponseControl.java sdk/src/org/opends/sdk/controls/PasswordPolicyWarningType.java sdk/src/org/opends/sdk/controls/PermissiveModifyRequestControl.java sdk/src/org/opends/sdk/controls/PersistentSearchChangeType.java sdk/src/org/opends/sdk/controls/PersistentSearchControl.java (deleted) sdk/src/org/opends/sdk/controls/PersistentSearchRequestControl.java sdk/src/org/opends/sdk/controls/PostReadControl.java (deleted) sdk/src/org/opends/sdk/controls/PostReadRequestControl.java sdk/src/org/opends/sdk/controls/PostReadResponseControl.java sdk/src/org/opends/sdk/controls/PreReadControl.java (deleted) sdk/src/org/opends/sdk/controls/PreReadRequestControl.java sdk/src/org/opends/sdk/controls/PreReadResponseControl.java sdk/src/org/opends/sdk/controls/ProxiedAuthV1Control.java (deleted) sdk/src/org/opends/sdk/controls/ProxiedAuthV1RequestControl.java sdk/src/org/opends/sdk/controls/ProxiedAuthV2Control.java (deleted) sdk/src/org/opends/sdk/controls/ProxiedAuthV2RequestControl.java sdk/src/org/opends/sdk/controls/ServerSideSortControl.java (deleted) sdk/src/org/opends/sdk/controls/ServerSideSortRequestControl.java sdk/src/org/opends/sdk/controls/ServerSideSortResponseControl.java sdk/src/org/opends/sdk/controls/SimplePagedResultsControl.java sdk/src/org/opends/sdk/controls/SortKey.java (deleted) sdk/src/org/opends/sdk/controls/SortResult.java (deleted) sdk/src/org/opends/sdk/controls/SubentriesRequestControl.java sdk/src/org/opends/sdk/controls/SubtreeDeleteControl.java (deleted) sdk/src/org/opends/sdk/controls/SubtreeDeleteRequestControl.java sdk/src/org/opends/sdk/controls/VLVControl.java (deleted) sdk/src/org/opends/sdk/controls/VLVResult.java (deleted) sdk/src/org/opends/sdk/controls/VLVTarget.java (deleted) sdk/src/org/opends/sdk/controls/VirtualListViewRequestControl.java sdk/src/org/opends/sdk/controls/VirtualListViewResponseControl.java sdk/src/org/opends/sdk/controls/package-info.java sdk/src/org/opends/sdk/extensions/CancelRequest.java (deleted) sdk/src/org/opends/sdk/extensions/ExtendedOperation.java (deleted) sdk/src/org/opends/sdk/extensions/GetConnectionIDRequest.java (deleted) sdk/src/org/opends/sdk/extensions/GetConnectionIDResult.java (deleted) sdk/src/org/opends/sdk/extensions/GetSymmetricKeyRequest.java (deleted) sdk/src/org/opends/sdk/extensions/PasswordModifyRequest.java (deleted) sdk/src/org/opends/sdk/extensions/PasswordModifyResult.java (deleted) sdk/src/org/opends/sdk/extensions/PasswordPolicyStateExtendedOperation.java (deleted) sdk/src/org/opends/sdk/extensions/StartTLSRequest.java (deleted) sdk/src/org/opends/sdk/extensions/WhoAmIRequest.java (deleted) sdk/src/org/opends/sdk/extensions/WhoAmIResult.java (deleted) sdk/src/org/opends/sdk/extensions/package-info.java (deleted) sdk/src/org/opends/sdk/ldap/LDAPConnectionFactory.java (deleted) sdk/src/org/opends/sdk/ldap/LDAPConnectionOptions.java (deleted) sdk/src/org/opends/sdk/ldap/LDAPDecoder.java (deleted) sdk/src/org/opends/sdk/ldap/LDAPEncoder.java (deleted) sdk/src/org/opends/sdk/ldap/ResolvedSchema.java (deleted) sdk/src/org/opends/sdk/ldif/AbstractLDIFReader.java sdk/src/org/opends/sdk/ldif/AbstractLDIFStream.java sdk/src/org/opends/sdk/ldif/AbstractLDIFWriter.java sdk/src/org/opends/sdk/ldif/ChangeRecord.java sdk/src/org/opends/sdk/ldif/ChangeRecordReader.java sdk/src/org/opends/sdk/ldif/ChangeRecordVisitor.java sdk/src/org/opends/sdk/ldif/ChangeRecordVisitorWriter.java sdk/src/org/opends/sdk/ldif/ChangeRecordWriter.java sdk/src/org/opends/sdk/ldif/ConnectionChangeRecordWriter.java sdk/src/org/opends/sdk/ldif/ConnectionEntryWriter.java sdk/src/org/opends/sdk/ldif/EntryReader.java sdk/src/org/opends/sdk/ldif/EntryWriter.java sdk/src/org/opends/sdk/ldif/LDIFChangeRecordReader.java sdk/src/org/opends/sdk/ldif/LDIFChangeRecordWriter.java sdk/src/org/opends/sdk/ldif/LDIFEntryReader.java sdk/src/org/opends/sdk/ldif/LDIFEntryWriter.java sdk/src/org/opends/sdk/requests/AbandonRequest.java sdk/src/org/opends/sdk/requests/AbandonRequestImpl.java sdk/src/org/opends/sdk/requests/AbstractBindRequest.java sdk/src/org/opends/sdk/requests/AbstractExtendedRequest.java sdk/src/org/opends/sdk/requests/AbstractRequestImpl.java sdk/src/org/opends/sdk/requests/AbstractSASLBindRequest.java sdk/src/org/opends/sdk/requests/AbstractUnmodifiableRequestImpl.java sdk/src/org/opends/sdk/requests/AddRequest.java sdk/src/org/opends/sdk/requests/AddRequestImpl.java sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequest.java sdk/src/org/opends/sdk/requests/AnonymousSASLBindRequestImpl.java sdk/src/org/opends/sdk/requests/BindClient.java sdk/src/org/opends/sdk/requests/BindClientImpl.java sdk/src/org/opends/sdk/requests/BindRequest.java sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequest.java sdk/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestImpl.java sdk/src/org/opends/sdk/requests/CancelExtendedRequest.java sdk/src/org/opends/sdk/requests/CancelExtendedRequestImpl.java sdk/src/org/opends/sdk/requests/CompareRequest.java sdk/src/org/opends/sdk/requests/CompareRequestImpl.java sdk/src/org/opends/sdk/requests/DeleteRequest.java sdk/src/org/opends/sdk/requests/DeleteRequestImpl.java sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequest.java sdk/src/org/opends/sdk/requests/DigestMD5SASLBindRequestImpl.java sdk/src/org/opends/sdk/requests/ExtendedRequest.java sdk/src/org/opends/sdk/requests/ExtendedRequestDecoder.java sdk/src/org/opends/sdk/requests/ExternalSASLBindRequest.java sdk/src/org/opends/sdk/requests/ExternalSASLBindRequestImpl.java sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequest.java sdk/src/org/opends/sdk/requests/GSSAPISASLBindRequestImpl.java sdk/src/org/opends/sdk/requests/GenericBindRequest.java sdk/src/org/opends/sdk/requests/GenericBindRequestImpl.java sdk/src/org/opends/sdk/requests/GenericExtendedRequest.java sdk/src/org/opends/sdk/requests/GenericExtendedRequestImpl.java sdk/src/org/opends/sdk/requests/ModifyDNRequest.java sdk/src/org/opends/sdk/requests/ModifyDNRequestImpl.java sdk/src/org/opends/sdk/requests/ModifyRequest.java sdk/src/org/opends/sdk/requests/ModifyRequestImpl.java sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequest.java sdk/src/org/opends/sdk/requests/PasswordModifyExtendedRequestImpl.java sdk/src/org/opends/sdk/requests/PlainSASLBindRequest.java sdk/src/org/opends/sdk/requests/PlainSASLBindRequestImpl.java sdk/src/org/opends/sdk/requests/Request.java sdk/src/org/opends/sdk/requests/Requests.java sdk/src/org/opends/sdk/requests/SASLBindClientImpl.java sdk/src/org/opends/sdk/requests/SASLBindRequest.java sdk/src/org/opends/sdk/requests/SearchRequest.java sdk/src/org/opends/sdk/requests/SearchRequestImpl.java sdk/src/org/opends/sdk/requests/SimpleBindRequest.java sdk/src/org/opends/sdk/requests/SimpleBindRequestImpl.java sdk/src/org/opends/sdk/requests/StartTLSExtendedRequest.java sdk/src/org/opends/sdk/requests/StartTLSExtendedRequestImpl.java sdk/src/org/opends/sdk/requests/UnbindRequest.java sdk/src/org/opends/sdk/requests/UnbindRequestImpl.java sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequest.java sdk/src/org/opends/sdk/requests/WhoAmIExtendedRequestImpl.java sdk/src/org/opends/sdk/requests/package-info.java sdk/src/org/opends/sdk/responses/AbstractExtendedResult.java sdk/src/org/opends/sdk/responses/AbstractIntermediateResponse.java sdk/src/org/opends/sdk/responses/AbstractResponseImpl.java sdk/src/org/opends/sdk/responses/AbstractResultImpl.java sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResponseImpl.java sdk/src/org/opends/sdk/responses/AbstractUnmodifiableResultImpl.java sdk/src/org/opends/sdk/responses/BindResult.java sdk/src/org/opends/sdk/responses/BindResultImpl.java sdk/src/org/opends/sdk/responses/CompareResult.java sdk/src/org/opends/sdk/responses/CompareResultImpl.java sdk/src/org/opends/sdk/responses/ExtendedResult.java sdk/src/org/opends/sdk/responses/ExtendedResultDecoder.java sdk/src/org/opends/sdk/responses/GenericExtendedResult.java sdk/src/org/opends/sdk/responses/GenericExtendedResultImpl.java sdk/src/org/opends/sdk/responses/GenericIntermediateResponse.java sdk/src/org/opends/sdk/responses/GenericIntermediateResponseImpl.java sdk/src/org/opends/sdk/responses/IntermediateResponse.java sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResult.java sdk/src/org/opends/sdk/responses/PasswordModifyExtendedResultImpl.java sdk/src/org/opends/sdk/responses/Response.java sdk/src/org/opends/sdk/responses/Responses.java sdk/src/org/opends/sdk/responses/Result.java sdk/src/org/opends/sdk/responses/ResultImpl.java sdk/src/org/opends/sdk/responses/SearchResultEntry.java sdk/src/org/opends/sdk/responses/SearchResultEntryImpl.java sdk/src/org/opends/sdk/responses/SearchResultReference.java sdk/src/org/opends/sdk/responses/SearchResultReferenceImpl.java sdk/src/org/opends/sdk/responses/WhoAmIExtendedResult.java sdk/src/org/opends/sdk/responses/WhoAmIExtendedResultImpl.java sdk/src/org/opends/sdk/responses/package-info.java sdk/src/org/opends/sdk/sasl/AbstractSASLContext.java (deleted) sdk/src/org/opends/sdk/sasl/AnonymousSASLBindRequest.java (deleted) sdk/src/org/opends/sdk/sasl/CRAMMD5SASLBindRequest.java (deleted) sdk/src/org/opends/sdk/sasl/DigestMD5SASLBindRequest.java (deleted) sdk/src/org/opends/sdk/sasl/ExternalSASLBindRequest.java (deleted) sdk/src/org/opends/sdk/sasl/GSSAPISASLBindRequest.java (deleted) sdk/src/org/opends/sdk/sasl/GenericSASLBindRequest.java (deleted) sdk/src/org/opends/sdk/sasl/NameCallbackHandler.java (deleted) sdk/src/org/opends/sdk/sasl/PlainSASLBindRequest.java (deleted) sdk/src/org/opends/sdk/sasl/SASLBindRequest.java (deleted) sdk/src/org/opends/sdk/sasl/SASLContext.java (deleted) sdk/src/org/opends/sdk/sasl/TextInputCallbackHandler.java (deleted) sdk/src/org/opends/sdk/schema/AbstractMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/AbstractOrderingMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/AbstractSubstringMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/AbstractSyntaxImpl.java sdk/src/org/opends/sdk/schema/AttributeType.java sdk/src/org/opends/sdk/schema/AttributeTypeSyntaxImpl.java sdk/src/org/opends/sdk/schema/AttributeUsage.java sdk/src/org/opends/sdk/schema/AuthPasswordExactEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/AuthPasswordSyntaxImpl.java sdk/src/org/opends/sdk/schema/BinarySyntaxImpl.java sdk/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/BitStringSyntaxImpl.java sdk/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/BooleanSyntaxImpl.java sdk/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseIgnoreListEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseIgnoreListSubstringMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/CertificateListSyntaxImpl.java sdk/src/org/opends/sdk/schema/CertificatePairSyntaxImpl.java sdk/src/org/opends/sdk/schema/CertificateSyntaxImpl.java sdk/src/org/opends/sdk/schema/ConflictingSchemaElementException.java sdk/src/org/opends/sdk/schema/CoreSchema.java sdk/src/org/opends/sdk/schema/CoreSchemaImpl.java sdk/src/org/opends/sdk/schema/CountryStringSyntaxImpl.java sdk/src/org/opends/sdk/schema/DITContentRule.java sdk/src/org/opends/sdk/schema/DITContentRuleSyntaxImpl.java sdk/src/org/opends/sdk/schema/DITStructureRule.java sdk/src/org/opends/sdk/schema/DITStructureRuleSyntaxImpl.java sdk/src/org/opends/sdk/schema/DeliveryMethodSyntaxImpl.java sdk/src/org/opends/sdk/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/DirectoryStringSyntaxImpl.java sdk/src/org/opends/sdk/schema/DistinguishedNameEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/DistinguishedNameSyntaxImpl.java sdk/src/org/opends/sdk/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/EnhancedGuideSyntaxImpl.java sdk/src/org/opends/sdk/schema/EnumOrderingMatchingRule.java sdk/src/org/opends/sdk/schema/EnumSyntaxImpl.java sdk/src/org/opends/sdk/schema/EqualLengthApproximateMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/FacsimileNumberSyntaxImpl.java sdk/src/org/opends/sdk/schema/FaxSyntaxImpl.java sdk/src/org/opends/sdk/schema/GeneralizedTimeEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/GeneralizedTimeOrderingMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/GeneralizedTimeSyntaxImpl.java sdk/src/org/opends/sdk/schema/GenerateCoreSchema.java sdk/src/org/opends/sdk/schema/GuideSyntaxImpl.java sdk/src/org/opends/sdk/schema/IA5StringSyntaxImpl.java sdk/src/org/opends/sdk/schema/IntegerEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/IntegerOrderingMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/IntegerSyntaxImpl.java sdk/src/org/opends/sdk/schema/JPEGSyntaxImpl.java sdk/src/org/opends/sdk/schema/KeywordEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/LDAPSyntaxDescriptionSyntaxImpl.java sdk/src/org/opends/sdk/schema/MatchingRule.java sdk/src/org/opends/sdk/schema/MatchingRuleImpl.java sdk/src/org/opends/sdk/schema/MatchingRuleSyntaxImpl.java sdk/src/org/opends/sdk/schema/MatchingRuleUse.java sdk/src/org/opends/sdk/schema/MatchingRuleUseSyntaxImpl.java sdk/src/org/opends/sdk/schema/NameAndOptionalUIDSyntaxImpl.java sdk/src/org/opends/sdk/schema/NameForm.java sdk/src/org/opends/sdk/schema/NameFormSyntaxImpl.java sdk/src/org/opends/sdk/schema/NumericStringEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/NumericStringOrderingMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/NumericStringSubstringMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/NumericStringSyntaxImpl.java sdk/src/org/opends/sdk/schema/OIDSyntaxImpl.java sdk/src/org/opends/sdk/schema/ObjectClass.java sdk/src/org/opends/sdk/schema/ObjectClassSyntaxImpl.java sdk/src/org/opends/sdk/schema/ObjectClassType.java sdk/src/org/opends/sdk/schema/ObjectIdentifierEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/OctetStringEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/OctetStringOrderingMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/OctetStringSubstringMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/OctetStringSyntaxImpl.java sdk/src/org/opends/sdk/schema/OtherMailboxSyntaxImpl.java sdk/src/org/opends/sdk/schema/PostalAddressSyntaxImpl.java sdk/src/org/opends/sdk/schema/PresentationAddressEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/PresentationAddressSyntaxImpl.java sdk/src/org/opends/sdk/schema/PrintableStringSyntaxImpl.java sdk/src/org/opends/sdk/schema/ProtocolInformationEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/ProtocolInformationSyntaxImpl.java sdk/src/org/opends/sdk/schema/RegexSyntaxImpl.java sdk/src/org/opends/sdk/schema/Schema.java sdk/src/org/opends/sdk/schema/SchemaBuilder.java sdk/src/org/opends/sdk/schema/SchemaCompatOptions.java sdk/src/org/opends/sdk/schema/SchemaConstants.java sdk/src/org/opends/sdk/schema/SchemaElement.java sdk/src/org/opends/sdk/schema/SchemaException.java sdk/src/org/opends/sdk/schema/SchemaUtils.java sdk/src/org/opends/sdk/schema/SubstringAssertionSyntaxImpl.java sdk/src/org/opends/sdk/schema/SupportedAlgorithmSyntaxImpl.java sdk/src/org/opends/sdk/schema/Syntax.java sdk/src/org/opends/sdk/schema/SyntaxImpl.java sdk/src/org/opends/sdk/schema/TelephoneNumberEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/TelephoneNumberSubstringMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/TelephoneNumberSyntaxImpl.java sdk/src/org/opends/sdk/schema/TeletexTerminalIdentifierSyntaxImpl.java sdk/src/org/opends/sdk/schema/TelexNumberSyntaxImpl.java sdk/src/org/opends/sdk/schema/UTCTimeSyntaxImpl.java sdk/src/org/opends/sdk/schema/UUIDEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/UUIDOrderingMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/UUIDSyntaxImpl.java sdk/src/org/opends/sdk/schema/UniqueMemberEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/UnknownSchemaElementException.java sdk/src/org/opends/sdk/schema/UserPasswordExactEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/UserPasswordSyntaxImpl.java sdk/src/org/opends/sdk/schema/WordEqualityMatchingRuleImpl.java sdk/src/org/opends/sdk/schema/package-info.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityRequestControlTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/controls/AccountUsabilityResponseControlTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferReaderTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/ASN1BufferWriterTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/GlobalTransportFactoryTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/ldap/LDAPTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/messages/MessagesTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/tools/ToolsTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/ASCIICharPropTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/Base64TestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StaticUtilsTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/StringPrepProfileTestCase.java sdk/tests/unit-tests-testng/src/com/sun/opends/sdk/util/UtilTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/AttributeDescriptionTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/AuthenticatedConnectionFactoryTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteSequenceTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringBuilderTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/ByteStringTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/ConnectionFactoryTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/DNTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/EntryTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/FilterTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/HeartBeatConnectionFactoryTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/InternalConnectionFactoryTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPConnectionFactoryTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPServer.java sdk/tests/unit-tests-testng/src/org/opends/sdk/LDAPUrlTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/LinkedAttributeTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/OpenDSTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/RDNTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/SdkTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/SortedEntryTest.java (deleted) sdk/tests/unit-tests-testng/src/org/opends/sdk/SuiteRunner.java sdk/tests/unit-tests-testng/src/org/opends/sdk/SynchronousConnectionTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/TestCaseUtils.java sdk/tests/unit-tests-testng/src/org/opends/sdk/TestListener.java sdk/tests/unit-tests-testng/src/org/opends/sdk/TypesTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ByteSequenceReaderTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1InputStreamReaderTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1OutputStreamWriterTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1ReaderTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/asn1/ASN1WriterTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/controls/ControlsTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFEntryReaderTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/ldif/LDIFTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AbandonRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AddRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/AnonymousSASLBindRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/BindRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CRAMMD5SASLBindRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/CompareRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DeleteRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/DigestMD5SASLBindRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExtendedRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ExternalSASLBindRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GSSAPISASLBindRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/GenericBindRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyDNRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/ModifyRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/PlainSASLBindRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/RequestsTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/SimpleBindRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/requests/UnbindRequestTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/responses/ResponsesTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AbstractSchemaElementTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/ApproximateMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/AttributeTypeTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringEqualityMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BitStringSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/BooleanEqualityMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactEqualityMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5EqualityMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactIA5SubstringMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactOrderingMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseExactSubstringMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreEqualityMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5EqualityMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreOrderingMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/CaseIgnoreSubstringMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/DITContentRuleSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/EnumSyntaxTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GeneralizedTimeSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/GuideSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/IA5StringSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/LDAPSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/MatchingRuleUseSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OrderingMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/OtherMailboxSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/RegexSyntaxTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SchemaUtilsTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstitutionSyntaxTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SubstringMatchingRuleTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/SyntaxTestCase.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/TelexSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UTCTimeSyntaxTest.java sdk/tests/unit-tests-testng/src/org/opends/sdk/schema/UUIDSyntaxTest.java