Synchronize SDK on java.net with internal repository.
18 files copied
66 files deleted
154 files added
11 files renamed
369 files modified
| | |
| | | ! CDDL HEADER END |
| | | ! |
| | | ! |
| | | ! Copyright 2009 Sun Microsystems, Inc. |
| | | ! Copyright 2009-2010 Sun Microsystems, Inc. |
| | | ! --> |
| | | |
| | | <project name="OpenDS LDAP SDK" basedir="." default="package"> |
| | |
| | | |
| | | <!-- 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" /> |
| | |
| | | |
| | | <!-- 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> |
| | | |
| | |
| | | </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" /> |
| | |
| | | <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> |
| | | |
| | | |
| | |
| | | <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}" /> |
| New file |
| | |
| | | /* |
| | | * 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); |
| | | } |
| | | } |
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 |
| | |
| | | * 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; |
| | | |
| | | |
| | | |
| New file |
| | |
| | | <?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> |
| New file |
| | |
| | | <?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> |
| | | |
| | |
| | | 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 |
| | |
| | | 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% |
| | |
| | | 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 |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | |
| | | } |
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 |
| | |
| | | * 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; |
| | | |
| | | |
| | | |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | } |
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 |
| | |
| | | * 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(); |
| | | } |
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 |
| | |
| | | * 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(); |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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; |
| | | } |
| | | } |
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 |
| | |
| | | */ |
| | | |
| | | /** |
| | | * 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; |
| | | |
| | | |
| | | |
| File was renamed from sdk/src/com/sun/opends/sdk/ldap/ASN1StreamReader.java |
| | |
| | | * 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; |
| | |
| | | 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; |
| | | |
| | | |
| | |
| | | /** |
| | | * 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; |
| | | |
| | |
| | | |
| | | |
| | | |
| | | 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); |
| | |
| | | { |
| | | 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; |
| | |
| | | |
| | | |
| | | |
| | | public ChildSequenceLimiter startSequence(int readLimit) |
| | | public ChildSequenceLimiter startSequence(final int readLimit) |
| | | { |
| | | if (child == null) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | 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()); |
| | | } |
| | | |
| | |
| | | |
| | | public int remaining() |
| | | { |
| | | return streamReader.availableDataSize(); |
| | | return buffer.remaining(); |
| | | } |
| | | |
| | | |
| | | |
| | | public ChildSequenceLimiter startSequence(int readLimit) |
| | | public ChildSequenceLimiter startSequence(final int readLimit) |
| | | { |
| | | if (child == null) |
| | | { |
| | |
| | | |
| | | private interface SequenceLimiter |
| | | { |
| | | public void checkLimit(int readSize) throws IOException, |
| | | BufferUnderflowException; |
| | | public void checkLimit(int readSize) throws IOException; |
| | | |
| | | |
| | | |
| | |
| | | |
| | | 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(); |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | public void prepare() |
| | | { |
| | | // Nothing to do |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | |
| | | |
| | | 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; |
| | |
| | | /** |
| | | * {@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 |
| | |
| | | |
| | | 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); |
| | | } |
| | | |
| | |
| | | |
| | | 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); |
| | | } |
| | | |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | // 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; |
| | |
| | | |
| | | 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; |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ByteStringBuilder readOctetString(ByteStringBuilder builder) |
| | | public ByteStringBuilder readOctetString(final ByteStringBuilder builder) |
| | | throws IOException |
| | | { |
| | | // Read the header if haven't done so already |
| | |
| | | // 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; |
| | |
| | | } |
| | | |
| | | byte[] readBuffer; |
| | | if (peekLength <= buffer.length) |
| | | if (peekLength <= stringBuffer.length) |
| | | { |
| | | readBuffer = buffer; |
| | | readBuffer = stringBuffer; |
| | | } |
| | | else |
| | | { |
| | |
| | | } |
| | | |
| | | readLimiter.checkLimit(peekLength); |
| | | streamReader.readByteArray(readBuffer, 0, peekLength); |
| | | buffer.get(readBuffer, 0, peekLength); |
| | | |
| | | state = ELEMENT_READ_STATE_NEED_TYPE; |
| | | |
| | |
| | | { |
| | | str = new String(readBuffer, 0, peekLength, "UTF-8"); |
| | | } |
| | | catch (Exception e) |
| | | catch (final Exception e) |
| | | { |
| | | if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING)) |
| | | { |
| | |
| | | + 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; |
| | |
| | | |
| | | |
| | | |
| | | 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} |
| | | */ |
| | |
| | | readLimiter.checkLimit(peekLength); |
| | | for (int i = 0; i < peekLength; i++) |
| | | { |
| | | streamReader.readByte(); |
| | | buffer.get(); |
| | | } |
| | | state = ELEMENT_READ_STATE_NEED_TYPE; |
| | | return this; |
| | |
| | | |
| | | |
| | | |
| | | 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)) |
| | |
| | | readLimiter.checkLimit(lengthBytesNeeded); |
| | | while (lengthBytesNeeded > 0) |
| | | { |
| | | readByte = streamReader.readByte(); |
| | | readByte = buffer.get(); |
| | | peekLength = (peekLength << 8) | (readByte & 0xFF); |
| | | lengthBytesNeeded--; |
| | | } |
| | |
| | | // 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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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)) |
| | |
| | | } |
| | | |
| | | 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); |
| | | } |
| | |
| | | readLimiter.checkLimit(lengthBytesNeeded); |
| | | while (lengthBytesNeeded > 0) |
| | | { |
| | | readByte = streamReader.readByte(); |
| | | readByte = buffer.get(); |
| | | peekLength = (peekLength << 8) | (readByte & 0xFF); |
| | | lengthBytesNeeded--; |
| | | } |
| | |
| | | // 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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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)) |
| | |
| | | } |
| | | |
| | | readLimiter.checkLimit(1); |
| | | peekType = streamReader.readByte(); |
| | | peekType = buffer.get(); |
| | | state = ELEMENT_READ_STATE_NEED_FIRST_LENGTH_BYTE; |
| | | return true; |
| | | } |
| File was renamed from sdk/src/com/sun/opends/sdk/ldap/ASN1StreamWriter.java |
| | |
| | | * 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; |
| | |
| | | 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; |
| | | |
| | | |
| | |
| | | /** |
| | | * 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 |
| | | { |
| | |
| | | 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)) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | public SequenceBuffer startSequence(byte type) throws IOException |
| | | public SequenceBuffer startSequence(final byte type) throws IOException |
| | | { |
| | | if (child == null) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | 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); |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | |
| | | |
| | | 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) |
| | | { |
| | |
| | | child.parent = this; |
| | | } |
| | | |
| | | streamWriter.writeByte(type); |
| | | outBuffer.ensureAdditionalCapacity(1); |
| | | outBuffer.put(type); |
| | | child.buffer.clear(); |
| | | |
| | | return child; |
| | |
| | | |
| | | |
| | | |
| | | 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); |
| | | } |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | | |
| | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | |
| | |
| | | */ |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ASN1Writer writeBoolean(byte type, boolean booleanValue) |
| | | public ASN1Writer writeBoolean(final byte type, final boolean booleanValue) |
| | | throws IOException |
| | | { |
| | | sequenceBuffer.writeByte(type); |
| | |
| | | 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; |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ASN1Writer writeEnumerated(byte type, int intValue) |
| | | public ASN1Writer writeEnumerated(final byte type, final int intValue) |
| | | throws IOException |
| | | { |
| | | return writeInteger(type, intValue); |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ASN1Writer writeInteger(byte type, int intValue) |
| | | public ASN1Writer writeInteger(final byte type, final int intValue) |
| | | throws IOException |
| | | { |
| | | sequenceBuffer.writeByte(type); |
| | |
| | | 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)) |
| | |
| | | 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)) |
| | |
| | | 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 |
| | |
| | | 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; |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ASN1Writer writeInteger(byte type, long longValue) |
| | | public ASN1Writer writeInteger(final byte type, final long longValue) |
| | | throws IOException |
| | | { |
| | | sequenceBuffer.writeByte(type); |
| | |
| | | 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)) |
| | |
| | | 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)) |
| | |
| | | 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)) |
| | |
| | | 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)) |
| | |
| | | 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)) |
| | |
| | | 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)) |
| | |
| | | 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 |
| | |
| | | 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; |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ASN1Writer writeNull(byte type) throws IOException |
| | | public ASN1Writer writeNull(final byte type) throws IOException |
| | | { |
| | | sequenceBuffer.writeByte(type); |
| | | writeLength(sequenceBuffer, 0); |
| | |
| | | /** |
| | | * {@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); |
| | |
| | | |
| | | 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; |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ASN1Writer writeOctetString(byte type, ByteSequence value) |
| | | public ASN1Writer writeOctetString(final byte type, final ByteSequence value) |
| | | throws IOException |
| | | { |
| | | sequenceBuffer.writeByte(type); |
| | |
| | | |
| | | 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; |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public ASN1Writer writeOctetString(byte type, String value) |
| | | public ASN1Writer writeOctetString(final byte type, final String value) |
| | | throws IOException |
| | | { |
| | | sequenceBuffer.writeByte(type); |
| | |
| | | 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; |
| | | } |
| | |
| | | /** |
| | | * {@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); |
| | |
| | | /** |
| | | * {@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. |
| | |
| | | |
| | | |
| | | |
| | | 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. |
| | |
| | | * @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) |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | |
| | | * 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(); |
| | | } |
| | | |
| | | |
| | |
| | | |
| | | |
| | | |
| | | 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()) |
| | | { |
| | |
| | | |
| | | |
| | | |
| | | abstract S newErrorResult(ResultCode resultCode, |
| | | String diagnosticMessage, Throwable cause); |
| | | final void updateTimestamp() |
| | | { |
| | | timestamp = System.currentTimeMillis(); |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | | |
| | | |
| | | |
| | |
| | | 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; |
| | | } |
| | | |
| | | |
| | |
| | | * {@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; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | |
| | | |
| | | |
| | | |
| | | 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(); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | return request; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | CompareResult newErrorResult(final ResultCode resultCode, |
| | | final String diagnosticMessage, final Throwable cause) |
| | | { |
| | | return Responses.newCompareResult(resultCode).setDiagnosticMessage( |
| | | diagnosticMessage).setCause(cause); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | | |
| | | |
| | |
| | | * <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; |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@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); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@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; |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void addConnectionEventListener( |
| | | ConnectionEventListener listener) throws IllegalStateException, |
| | | NullPointerException |
| | | public void addConnectionEventListener(final ConnectionEventListener listener) |
| | | throws IllegalStateException, NullPointerException |
| | | { |
| | | Validator.ensureNotNull(listener); |
| | | listeners.add(listener); |
| | |
| | | /** |
| | | * {@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( |
| | |
| | | } |
| | | |
| | | 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; |
| | | } |
| | |
| | | /** |
| | | * {@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. |
| | |
| | | |
| | | 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 : ""))); |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@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( |
| | |
| | | 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; |
| | | } |
| | |
| | | /** |
| | | * {@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; |
| | | } |
| | |
| | | /** |
| | | * {@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; |
| | | } |
| | |
| | | /** |
| | | * {@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; |
| | | } |
| | |
| | | /** |
| | | * {@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; |
| | | } |
| | |
| | | * {@inheritDoc} |
| | | */ |
| | | public void removeConnectionEventListener( |
| | | ConnectionEventListener listener) throws NullPointerException |
| | | final ConnectionEventListener listener) throws NullPointerException |
| | | { |
| | | Validator.ensureNotNull(listener); |
| | | listeners.remove(listener); |
| | |
| | | /** |
| | | * {@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) |
| | | { |
| | |
| | | } |
| | | |
| | | // 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. |
| | | } |
| | | } |
| | | |
| | |
| | | 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. |
| | | } |
| | |
| | | // 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)); |
| | |
| | | |
| | | |
| | | |
| | | 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); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | 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. |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | protected LDAPConnection transformResult(Result result) |
| | | @Override |
| | | protected LDAPConnection transformResult(final Result result) |
| | | throws ErrorResultException |
| | | { |
| | | return connection; |
| | |
| | | |
| | | }; |
| | | |
| | | 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); |
| | | } |
| | | |
| | |
| | | { |
| | | 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); |
| | | } |
| | | |
| | | }; |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void cancelled(Connection connection) |
| | | public void cancelled() |
| | | { |
| | | // Ignore this. |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void completed(Connection connection, Connection result) |
| | | public void completed(final Connection connection) |
| | | { |
| | | futureConnectionResult.handleResult(adaptConnection(connection)); |
| | | } |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void failed(Connection connection, Throwable throwable) |
| | | public void failed(final Throwable throwable) |
| | | { |
| | | futureConnectionResult |
| | | .handleErrorResult(adaptConnectionException(throwable)); |
| | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | public void updated(Connection connection, Connection result) |
| | | public void updated(final Connection connection) |
| | | { |
| | | // Ignore this. |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | /** |
| | | * {@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 |
| | | { |
| | |
| | | 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; |
| | | } |
| | | |
| | |
| | | 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); |
| | | } |
| | | } |
| | |
| | | */ |
| | | 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. |
| | | */ |
| | |
| | | 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; |
| | | |
| | |
| | | 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; |
| | | |
| | |
| | | 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; |
| | | |
| | |
| | | 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; |
| | | |
| | |
| | | /** |
| | | * 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. |
| | | } |
| | | } |
| | |
| | | |
| | | 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); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | return request; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | R newErrorResult(final ResultCode resultCode, final String diagnosticMessage, |
| | | final Throwable cause) |
| | | { |
| | | return request.getResultDecoder().adaptExtendedErrorResult(resultCode, "", |
| | | diagnosticMessage); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | |
| | | /** |
| | | * 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; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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; |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | |
| | | * 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 |
| | |
| | | // 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 |
| | |
| | | // 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(); |
| | | } |
| | | |
| | | |
| | |
| | | { |
| | | return request; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | Result newErrorResult(final ResultCode resultCode, |
| | | final String diagnosticMessage, final Throwable cause) |
| | | { |
| | | return Responses.newResult(resultCode).setDiagnosticMessage( |
| | | diagnosticMessage).setCause(cause); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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); |
| | | } |
| | | |
| | | } |
| | | } |
| File was renamed from sdk/src/org/opends/sdk/ldap/LDAPUtils.java |
| | |
| | | * Copyright 2009 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | package org.opends.sdk.ldap; |
| | | package com.sun.opends.sdk.ldap; |
| | | |
| | | |
| | | |
| | |
| | | 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; |
| | |
| | | writer.writeEndSequence(); |
| | | return null; |
| | | } |
| | | catch (IOException e) |
| | | catch (final IOException e) |
| | | { |
| | | return e; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | public IOException visitApproxMatchFilter(ASN1Writer writer, |
| | | String attributeDescription, ByteString assertionValue) |
| | | public IOException visitApproxMatchFilter(final ASN1Writer writer, |
| | | final String attributeDescription, final ByteString assertionValue) |
| | | { |
| | | try |
| | | { |
| | |
| | | writer.writeEndSequence(); |
| | | return null; |
| | | } |
| | | catch (IOException e) |
| | | catch (final IOException e) |
| | | { |
| | | return e; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | public IOException visitEqualityMatchFilter(ASN1Writer writer, |
| | | String attributeDescription, ByteString assertionValue) |
| | | public IOException visitEqualityMatchFilter(final ASN1Writer writer, |
| | | final String attributeDescription, final ByteString assertionValue) |
| | | { |
| | | try |
| | | { |
| | |
| | | writer.writeEndSequence(); |
| | | return null; |
| | | } |
| | | catch (IOException e) |
| | | catch (final IOException e) |
| | | { |
| | | return e; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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 |
| | | { |
| | |
| | | |
| | | 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) |
| | | { |
| | |
| | | writer.writeEndSequence(); |
| | | return null; |
| | | } |
| | | catch (IOException e) |
| | | catch (final IOException e) |
| | | { |
| | | return e; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | public IOException visitGreaterOrEqualFilter(ASN1Writer writer, |
| | | String attributeDescription, ByteString assertionValue) |
| | | public IOException visitGreaterOrEqualFilter(final ASN1Writer writer, |
| | | final String attributeDescription, final ByteString assertionValue) |
| | | { |
| | | try |
| | | { |
| | |
| | | writer.writeEndSequence(); |
| | | return null; |
| | | } |
| | | catch (IOException e) |
| | | catch (final IOException e) |
| | | { |
| | | return e; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | public IOException visitLessOrEqualFilter(ASN1Writer writer, |
| | | String attributeDescription, ByteString assertionValue) |
| | | public IOException visitLessOrEqualFilter(final ASN1Writer writer, |
| | | final String attributeDescription, final ByteString assertionValue) |
| | | { |
| | | try |
| | | { |
| | |
| | | writer.writeEndSequence(); |
| | | return null; |
| | | } |
| | | catch (IOException e) |
| | | catch (final IOException e) |
| | | { |
| | | return e; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | |
| | | writer.writeEndSequence(); |
| | | return null; |
| | | } |
| | | catch (IOException e) |
| | | catch (final IOException e) |
| | | { |
| | | return e; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | |
| | | writer.writeEndSequence(); |
| | | return null; |
| | | } |
| | | catch (IOException e) |
| | | catch (final IOException e) |
| | | { |
| | | return e; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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 |
| | | { |
| | |
| | | writer.writeOctetString(TYPE_SUBINITIAL, initialSubstring); |
| | | } |
| | | |
| | | for (ByteSequence anySubstring : anySubstrings) |
| | | for (final ByteSequence anySubstring : anySubstrings) |
| | | { |
| | | writer.writeOctetString(TYPE_SUBANY, anySubstring); |
| | | } |
| | |
| | | writer.writeEndSequence(); |
| | | return null; |
| | | } |
| | | catch (IOException e) |
| | | catch (final IOException e) |
| | | { |
| | | return e; |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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; |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 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) |
| | | { |
| | |
| | | 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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | |
| | | { |
| | | 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 |
| | |
| | | |
| | | |
| | | // Decodes an approximate match filter. |
| | | private static Filter decodeApproxMatchFilter(ASN1Reader reader) |
| | | private static Filter decodeApproxMatchFilter(final ASN1Reader reader) |
| | | throws IOException |
| | | { |
| | | String attributeDescription; |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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) |
| | |
| | | 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; |
| | |
| | | { |
| | | 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; |
| | |
| | | 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; |
| | |
| | | |
| | | |
| | | // Decodes an or filter. |
| | | private static Filter decodeOrFilter(ASN1Reader reader) |
| | | private static Filter decodeOrFilter(final ASN1Reader reader) |
| | | throws IOException |
| | | { |
| | | Filter filter; |
| | |
| | | { |
| | | 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 |
| | |
| | | |
| | | |
| | | // Decodes a sub-strings filter. |
| | | private static Filter decodeSubstringsFilter(ASN1Reader reader) |
| | | private static Filter decodeSubstringsFilter(final ASN1Reader reader) |
| | | throws IOException |
| | | { |
| | | ByteString initialSubstring = null; |
| | |
| | | { |
| | | 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); |
| | | } |
| | |
| | | anySubstrings = Collections.emptyList(); |
| | | } |
| | | |
| | | return Filter.newSubstringsFilter(attributeDescription, |
| | | initialSubstring, anySubstrings, finalSubstring); |
| | | return Filter.newSubstringsFilter(attributeDescription, initialSubstring, |
| | | anySubstrings, finalSubstring); |
| | | } |
| | | |
| | | |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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()); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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()); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | 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)); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * 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(); |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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()); |
| | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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()); |
| | |
| | | * 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; |
| | |
| | | |
| | | |
| | | |
| | | 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; |
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 |
| | |
| | | * 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; |
| | | |
| | | |
| | | |
| | |
| | | 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 |
| | |
| | | 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 |
| | |
| | | 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 |
| | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | * @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 |
| | |
| | | // 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; |
| | |
| | | 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. |
| | |
| | | |
| | | |
| | | /** |
| | | * 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) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * 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) |
| | | { |
| | |
| | | * |
| | | * @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) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * 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) |
| | | { |
| | |
| | | * 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) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * 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) |
| | | { |
| | |
| | | |
| | | |
| | | 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; |
| | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | { |
| | |
| | | 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; |
| | |
| | | * 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; |
| | |
| | | |
| | | 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); |
| | | } |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * 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() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | |
| | | |
| | | /** |
| | | * 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() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | |
| | |
| | | * @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(); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | | |
| | |
| | | * @param message |
| | | * The message that explains the problem that occurred. |
| | | */ |
| | | ArgumentException(LocalizableMessage message) |
| | | ArgumentException(final LocalizableMessage message) |
| | | { |
| | | super(String.valueOf(message)); |
| | | this.message = message; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | |
| | | private List<Argument> args = null; |
| | | |
| | | // Governs groups position within usage statement |
| | | private Integer priority; |
| | | private final Integer priority; |
| | | |
| | | |
| | | |
| | |
| | | * 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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | |
| | | /** |
| | | * 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()) |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | |
| | |
| | | * 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; |
| | | } |
| | | |
| | | } |
| | |
| | | |
| | | 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; |
| | |
| | | |
| | | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | | { |
| | |
| | | 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; |
| | | |
| | |
| | | |
| | | // 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. |
| | |
| | | |
| | | // 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; |
| | |
| | | // 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; |
| | |
| | | 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 = " "; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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); |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 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); |
| | | } |
| | | |
| | |
| | | // 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 |
| | | } |
| | |
| | | } |
| | | 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); |
| | | } |
| | | } |
| | |
| | | |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | |
| | |
| | | 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"); } |
| | | */ |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | // 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 |
| | |
| | | { |
| | | if (currentPropertyName.startsWith(scriptName)) |
| | | { |
| | | propertyName = currentPropertyName.substring(scriptName |
| | | .length() + 1); |
| | | propertyName = currentPropertyName |
| | | .substring(scriptName.length() + 1); |
| | | } |
| | | else |
| | | { |
| | |
| | | .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; |
| | |
| | | |
| | | |
| | | /** |
| | | * 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) |
| | |
| | | |
| | | 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); |
| | |
| | | } |
| | | } |
| | | |
| | | for (Argument a : argGroup.getArguments()) |
| | | for (final Argument a : argGroup.getArguments()) |
| | | { |
| | | // If this argument is hidden, then skip it. |
| | | if (a.isHidden()) |
| | |
| | | |
| | | |
| | | /** |
| | | * 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 |
| | |
| | | |
| | | |
| | | /** |
| | | * 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() |
| | | { |
| | |
| | | |
| | | |
| | | /** |
| | | * 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())) |
| | | { |
| | |
| | | |
| | | if (longID != null) |
| | | { |
| | | StringBuilder newBuffer = new StringBuilder(); |
| | | final StringBuilder newBuffer = new StringBuilder(); |
| | | newBuffer.append(", --"); |
| | | newBuffer.append(longID); |
| | | |
| | |
| | | newBuffer.append(a.getValuePlaceholder()); |
| | | } |
| | | |
| | | int lineLength = (buffer.length() - currentLength) |
| | | final int lineLength = (buffer.length() - currentLength) |
| | | + newBuffer.length(); |
| | | if (lineLength > MAX_LENGTH) |
| | | { |
| | |
| | | // 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); |
| | |
| | | && (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; |
| | | } |
| | | } |
| 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 |