Merge branch 'opendj-sdk'
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!-- |
| | | The contents of this file are subject to the terms of the Common Development and |
| | | Distribution License (the License). You may not use this file except in compliance with the |
| | | License. |
| | | |
| | | You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | specific language governing permission and limitations under the License. |
| | | |
| | | When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | information: "Portions Copyright [year] [name of copyright owner]". |
| | | |
| | | Copyright 2014-2016 ForgeRock AS. |
| | | --> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <parent> |
| | | <artifactId>opendj-sdk-parent</artifactId> |
| | | <groupId>org.forgerock.opendj</groupId> |
| | | <version>4.0.0-SNAPSHOT</version> |
| | | </parent> |
| | | |
| | | <artifactId>opendj-cli</artifactId> |
| | | <name>OpenDJ CLI API</name> |
| | | <description>This module includes CLI API for implementing CLI applications.</description> |
| | | |
| | | <packaging>bundle</packaging> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.forgerock.opendj</groupId> |
| | | <artifactId>opendj-core</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.forgerock.opendj</groupId> |
| | | <artifactId>opendj-core</artifactId> |
| | | <type>test-jar</type> |
| | | <scope>test</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.forgerock.commons</groupId> |
| | | <artifactId>i18n-core</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.forgerock</groupId> |
| | | <artifactId>forgerock-build-tools</artifactId> |
| | | <scope>test</scope> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.freemarker</groupId> |
| | | <artifactId>freemarker</artifactId> |
| | | <version>2.3.21</version> |
| | | <scope>provided</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | |
| | | <properties> |
| | | <opendj.osgi.import.additional> |
| | | org.forgerock.opendj.*;provide:=true |
| | | </opendj.osgi.import.additional> |
| | | </properties> |
| | | |
| | | |
| | | <build> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.forgerock.commons</groupId> |
| | | <artifactId>i18n-maven-plugin</artifactId> |
| | | <executions> |
| | | <execution> |
| | | <phase>generate-sources</phase> |
| | | <goals> |
| | | <goal>generate-messages</goal> |
| | | </goals> |
| | | <configuration> |
| | | <messageFiles> |
| | | <messageFile>com/forgerock/opendj/cli/cli.properties</messageFile> |
| | | </messageFiles> |
| | | </configuration> |
| | | </execution> |
| | | </executions> |
| | | </plugin> |
| | | |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-surefire-plugin</artifactId> |
| | | </plugin> |
| | | |
| | | <plugin> |
| | | <groupId>org.codehaus.mojo</groupId> |
| | | <artifactId>cobertura-maven-plugin</artifactId> |
| | | </plugin> |
| | | |
| | | <!-- Creates opendj-cli bundle --> |
| | | <plugin> |
| | | <groupId>org.apache.felix</groupId> |
| | | <artifactId>maven-bundle-plugin</artifactId> |
| | | <configuration> |
| | | <instructions> |
| | | <Export-Package>com.forgerock.opendj.cli</Export-Package> |
| | | </instructions> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | |
| | | |
| | | <reporting> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-project-info-reports-plugin</artifactId> |
| | | <reportSets> |
| | | <reportSet> |
| | | <reports> |
| | | <report>mailing-list</report> |
| | | <report>issue-tracking</report> |
| | | <report>license</report> |
| | | <report>cim</report> |
| | | <report>distribution-management</report> |
| | | </reports> |
| | | </reportSet> |
| | | </reportSets> |
| | | </plugin> |
| | | |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-javadoc-plugin</artifactId> |
| | | <configuration> |
| | | <links> |
| | | <link>http://commons.forgerock.org/i18n-framework/i18n-core/apidocs</link> |
| | | </links> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | </reporting> |
| | | </project> |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2009 Parametric Technology Corporation (PTC) |
| | | * Portions copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.net.Socket; |
| | | import java.security.KeyStore; |
| | | import java.security.KeyStoreException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.security.NoSuchProviderException; |
| | | import java.security.Principal; |
| | | import java.security.PrivateKey; |
| | | import java.security.UnrecoverableKeyException; |
| | | import java.security.cert.X509Certificate; |
| | | import javax.net.ssl.KeyManager; |
| | | import javax.net.ssl.KeyManagerFactory; |
| | | import javax.net.ssl.TrustManagerFactory; |
| | | import javax.net.ssl.X509KeyManager; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | |
| | | /** |
| | | * 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. |
| | | * <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). |
| | | * <p> |
| | | * NOTE: this class is not aimed to be used when we have connections in |
| | | * parallel. |
| | | */ |
| | | final class ApplicationKeyManager implements X509KeyManager { |
| | | private static final LocalizedLogger LOG = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | /** |
| | | * The default keyManager. |
| | | */ |
| | | private X509KeyManager keyManager; |
| | | |
| | | /** |
| | | * The default constructor. |
| | | * |
| | | * @param keystore |
| | | * The key store to use for this key manager. |
| | | * @param password |
| | | * The key store password to use for this key manager. |
| | | */ |
| | | ApplicationKeyManager(final KeyStore keystore, final char[] password) { |
| | | KeyManagerFactory kmf = null; |
| | | String userSpecifiedAlgo = System.getProperty("org.opendj.admin.keymanageralgo"); |
| | | String userSpecifiedProvider = System.getProperty("org.opendj.admin.keymanagerprovider"); |
| | | |
| | | // Handle IBM specific cases if the user did not specify a algorithm |
| | | // and/or provider. |
| | | final String vendor = System.getProperty("java.vendor"); |
| | | if (vendor.startsWith("IBM")) { |
| | | if (userSpecifiedAlgo == null) { |
| | | userSpecifiedAlgo = "IbmX509"; |
| | | } |
| | | if (userSpecifiedProvider == null) { |
| | | userSpecifiedProvider = "IBMJSSE2"; |
| | | } |
| | | } |
| | | |
| | | // Have some fall backs to choose the provider and algorithm of the |
| | | // key manager. First see if the user wanted to use something |
| | | // specific, then try with the SunJSSE provider and SunX509 |
| | | // algorithm. Finally, fall back to the default algorithm of the JVM. |
| | | final String[] preferredProvider = { userSpecifiedProvider, "SunJSSE", null, null }; |
| | | final String[] preferredAlgo = { userSpecifiedAlgo, "SunX509", "SunX509", |
| | | TrustManagerFactory.getDefaultAlgorithm() }; |
| | | for (int i = 0; i < preferredProvider.length && keyManager == null; i++) { |
| | | final String provider = preferredProvider[i]; |
| | | final String algo = preferredAlgo[i]; |
| | | if (algo == null) { |
| | | continue; |
| | | } |
| | | try { |
| | | if (provider != null) { |
| | | kmf = KeyManagerFactory.getInstance(algo, provider); |
| | | } else { |
| | | kmf = KeyManagerFactory.getInstance(algo); |
| | | } |
| | | kmf.init(keystore, password); |
| | | final KeyManager[] kms = kmf.getKeyManagers(); |
| | | /* |
| | | * Iterate over the returned key managers, look for an instance |
| | | * of X509KeyManager. If found, use that as our "default" key |
| | | * manager. |
| | | */ |
| | | for (final KeyManager km : kms) { |
| | | if (km instanceof X509KeyManager) { |
| | | keyManager = (X509KeyManager) km; |
| | | break; |
| | | } |
| | | } |
| | | } catch (final NoSuchAlgorithmException e) { |
| | | // Nothing to do. Maybe we should avoid this and be strict, but |
| | | // we are in a best effort mode. |
| | | LOG.warn(LocalizableMessage.raw("Error with the algorithm", e)); |
| | | } catch (final KeyStoreException e) { |
| | | // Nothing to do. Maybe we should avoid this and be strict, but |
| | | // we are in a best effort mode.. |
| | | LOG.warn(LocalizableMessage.raw("Error with the keystore", e)); |
| | | } catch (final UnrecoverableKeyException e) { |
| | | // Nothing to do. Maybe we should avoid this and be strict, but |
| | | // we are in a best effort mode. |
| | | LOG.warn(LocalizableMessage.raw("Error with the key", e)); |
| | | } catch (final NoSuchProviderException e) { |
| | | // Nothing to do. Maybe we should avoid this and be strict, but |
| | | // we are in a best effort mode. |
| | | LOG.warn(LocalizableMessage.raw("Error with the provider", e)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | * @param issuers |
| | | * 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. |
| | | * @return the alias name for the desired key, or null if there are no |
| | | * matches. |
| | | */ |
| | | @Override |
| | | public String chooseClientAlias(final String[] keyType, final Principal[] issuers, |
| | | final Socket socket) { |
| | | if (keyManager != null) { |
| | | return keyManager.chooseClientAlias(keyType, issuers, socket); |
| | | } |
| | | return 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). |
| | | * |
| | | * @param keyType |
| | | * 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. |
| | | * @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. |
| | | * @return the alias name for the desired key, or null if there are no |
| | | * matches. |
| | | */ |
| | | @Override |
| | | public String chooseServerAlias(final String keyType, final Principal[] issuers, final Socket socket) { |
| | | if (keyManager != null) { |
| | | return keyManager.chooseServerAlias(keyType, issuers, socket); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * Returns the certificate chain associated with the given alias. |
| | | * |
| | | * @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. |
| | | */ |
| | | @Override |
| | | public X509Certificate[] getCertificateChain(final String alias) { |
| | | if (keyManager != null) { |
| | | return keyManager.getCertificateChain(alias); |
| | | } |
| | | return 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). |
| | | * |
| | | * @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. |
| | | */ |
| | | @Override |
| | | public String[] getClientAliases(final String keyType, final Principal[] issuers) { |
| | | if (keyManager != null) { |
| | | return keyManager.getClientAliases(keyType, issuers); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * Returns the key associated with the given alias. |
| | | * |
| | | * @param alias |
| | | * the alias name |
| | | * @return the requested key, or null if the alias can't be found. |
| | | */ |
| | | @Override |
| | | public PrivateKey getPrivateKey(final String alias) { |
| | | if (keyManager != null) { |
| | | return keyManager.getPrivateKey(alias); |
| | | } |
| | | return 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). |
| | | * |
| | | * @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. |
| | | */ |
| | | @Override |
| | | public String[] getServerAliases(final String keyType, final Principal[] issuers) { |
| | | if (keyManager != null) { |
| | | return keyManager.getServerAliases(keyType, issuers); |
| | | } |
| | | return null; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | |
| | | import java.util.Iterator; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | import org.forgerock.util.Reject; |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public abstract class Argument implements DocDescriptionSupplement { |
| | | |
| | | /** |
| | | * An abstract base class to build a generic {@link Argument}. |
| | | * |
| | | * @param <B> |
| | | * The concrete {@link ArgumentBuilder} subclass. |
| | | * @param <T> |
| | | * The default value type of the {@link Argument}. |
| | | * @param <A> |
| | | * The concrete {@link Argument} type to build. |
| | | */ |
| | | static abstract class ArgumentBuilder<B extends ArgumentBuilder<B, T, A>, T, A extends Argument> { |
| | | T defaultValue; |
| | | LocalizableMessage description; |
| | | LocalizableMessage docDescriptionSupplement; |
| | | boolean hidden; |
| | | final String longIdentifier; |
| | | boolean multiValued; |
| | | boolean needsValue = true; |
| | | boolean required; |
| | | Character shortIdentifier; |
| | | LocalizableMessage valuePlaceholder; |
| | | |
| | | ArgumentBuilder(final String longIdentifier) { |
| | | Reject.ifNull(longIdentifier, "An argument must have a long identifier"); |
| | | this.longIdentifier = longIdentifier; |
| | | } |
| | | |
| | | abstract B getThis(); |
| | | |
| | | /** |
| | | * Build the argument. |
| | | * |
| | | * @return The argument built. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to |
| | | * create this argument. |
| | | */ |
| | | public abstract A buildArgument() throws ArgumentException; |
| | | |
| | | /** |
| | | * Build the argument and add it to the provided {@link ArgumentParser}. |
| | | * |
| | | * @param parser |
| | | * The argument parser. |
| | | * @return The argument built. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to |
| | | * create this argument. |
| | | */ |
| | | public A buildAndAddToParser(final ArgumentParser parser) throws ArgumentException { |
| | | final A arg = buildArgument(); |
| | | parser.addArgument(arg); |
| | | return arg; |
| | | } |
| | | |
| | | /** |
| | | * Build the argument and add it to the provided {@link SubCommand}. |
| | | * |
| | | * @param subCommand |
| | | * The sub command. |
| | | * @return The argument built. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to |
| | | * create this argument. |
| | | */ |
| | | public A buildAndAddToSubCommand(final SubCommand subCommand) throws ArgumentException { |
| | | final A arg = buildArgument(); |
| | | subCommand.addArgument(arg); |
| | | return arg; |
| | | } |
| | | |
| | | /** |
| | | * Sets this argument default value. |
| | | * |
| | | * @param defaultValue |
| | | * The default value. |
| | | * @return This builder. |
| | | */ |
| | | public B defaultValue(final T defaultValue) { |
| | | this.defaultValue = defaultValue; |
| | | return getThis(); |
| | | } |
| | | |
| | | /** |
| | | * Sets this argument description. |
| | | * |
| | | * @param description |
| | | * The localized description. |
| | | * @return This builder. |
| | | */ |
| | | public B description(final LocalizableMessage description) { |
| | | this.description = description; |
| | | return getThis(); |
| | | } |
| | | |
| | | /** |
| | | * Sets a supplement to the description intended for use in generated reference documentation. |
| | | * |
| | | * @param docDescriptionSupplement |
| | | * The supplement to the description for use in generated reference documentation. |
| | | * @return This builder. |
| | | */ |
| | | public B docDescriptionSupplement(final LocalizableMessage docDescriptionSupplement) { |
| | | this.docDescriptionSupplement = docDescriptionSupplement; |
| | | return getThis(); |
| | | } |
| | | |
| | | /** |
| | | * Specifies that this argument is hidden. |
| | | * |
| | | * @return This builder. |
| | | */ |
| | | public B hidden() { |
| | | this.hidden = true; |
| | | return getThis(); |
| | | } |
| | | |
| | | /** |
| | | * Specifies that this argument may have multiple values. |
| | | * |
| | | * @return This builder. |
| | | */ |
| | | public B multiValued() { |
| | | this.multiValued = true; |
| | | return getThis(); |
| | | } |
| | | |
| | | /** |
| | | * Specifies that this argument is required. |
| | | * |
| | | * @return This builder. |
| | | */ |
| | | public B required() { |
| | | this.required = true; |
| | | return getThis(); |
| | | } |
| | | |
| | | /** |
| | | * Sets this argument single-character identifier. |
| | | * |
| | | * @param shortIdentifier |
| | | * The single-character identifier. |
| | | * @return This builder. |
| | | */ |
| | | public B shortIdentifier(final Character shortIdentifier) { |
| | | this.shortIdentifier = shortIdentifier; |
| | | return getThis(); |
| | | } |
| | | |
| | | /** |
| | | * Sets this argument value placeholder, which will be used in usage information. |
| | | * |
| | | * @param valuePlaceholder |
| | | * The localized value placeholder. |
| | | * @return This builder. |
| | | */ |
| | | public B valuePlaceholder(final LocalizableMessage valuePlaceholder) { |
| | | this.valuePlaceholder = valuePlaceholder; |
| | | return getThis(); |
| | | } |
| | | } |
| | | |
| | | /** The long identifier for this argument. */ |
| | | final String longIdentifier; |
| | | |
| | | /** The single-character identifier for this argument. */ |
| | | private final Character shortIdentifier; |
| | | /** The unique ID of the description for this argument. */ |
| | | private final LocalizableMessage description; |
| | | /** Indicates whether this argument should be hidden in the usage information. */ |
| | | private final boolean isHidden; |
| | | /** Indicates whether this argument may be specified more than once for multiple values. */ |
| | | private final boolean isMultiValued; |
| | | /** Indicates whether this argument is required to have a value. */ |
| | | private final boolean isRequired; |
| | | /** Indicates whether this argument requires a value. */ |
| | | private final boolean needsValue; |
| | | /** The default value for the argument if none other is provided. */ |
| | | private final String defaultValue; |
| | | /** The value placeholder for this argument, which will be used in usage information. */ |
| | | private final LocalizableMessage valuePlaceholder; |
| | | |
| | | /** The set of values for this argument. */ |
| | | private final LinkedList<String> values = new LinkedList<>(); |
| | | |
| | | /** Indicates whether this argument was provided in the set of command-line arguments. */ |
| | | private boolean isPresent; |
| | | |
| | | /** |
| | | * Indicates whether this argument was provided in the set of |
| | | * properties found in a properties file. |
| | | */ |
| | | private boolean isValueSetByProperty; |
| | | |
| | | <B extends ArgumentBuilder<B, T, A>, T, A extends Argument> Argument(final ArgumentBuilder<B, T, A> builder) |
| | | throws ArgumentException { |
| | | this.shortIdentifier = builder.shortIdentifier; |
| | | this.longIdentifier = builder.longIdentifier; |
| | | this.isRequired = builder.required; |
| | | this.isMultiValued = builder.multiValued; |
| | | this.needsValue = builder.needsValue; |
| | | this.valuePlaceholder = builder.valuePlaceholder; |
| | | this.defaultValue = builder.defaultValue != null ? String.valueOf(builder.defaultValue) : null; |
| | | this.description = builder.description; |
| | | this.isHidden = builder.hidden; |
| | | this.docDescriptionSupplement = builder.docDescriptionSupplement; |
| | | |
| | | if (needsValue && valuePlaceholder == null) { |
| | | throw new ArgumentException(ERR_ARG_NO_VALUE_PLACEHOLDER.get(longIdentifier)); |
| | | } |
| | | |
| | | isPresent = false; |
| | | } |
| | | |
| | | /** |
| | | * 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(final String valueString) { |
| | | if (!isMultiValued) { |
| | | clearValues(); |
| | | } |
| | | values.add(valueString); |
| | | } |
| | | |
| | | /** |
| | | * Clears the set of values assigned to this argument. |
| | | */ |
| | | public void clearValues() { |
| | | values.clear(); |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public String getDefaultValue() { |
| | | return defaultValue; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the human-readable description for this argument. |
| | | * |
| | | * @return The human-readable description for this argument. |
| | | */ |
| | | public LocalizableMessage getDescription() { |
| | | return description != null ? description : LocalizableMessage.EMPTY; |
| | | } |
| | | |
| | | /** A supplement to the description intended for use in generated reference documentation. */ |
| | | private LocalizableMessage docDescriptionSupplement; |
| | | |
| | | @Override |
| | | public LocalizableMessage getDocDescriptionSupplement() { |
| | | return docDescriptionSupplement != null ? docDescriptionSupplement : LocalizableMessage.EMPTY; |
| | | } |
| | | |
| | | /** |
| | | * 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()) { |
| | | throw new ArgumentException(ERR_ARG_NO_INT_VALUE.get(longIdentifier)); |
| | | } |
| | | |
| | | final Iterator<String> iterator = values.iterator(); |
| | | final String valueString = iterator.next(); |
| | | if (iterator.hasNext()) { |
| | | throw new ArgumentException(ERR_ARG_INT_MULTIPLE_VALUES.get(longIdentifier)); |
| | | } |
| | | |
| | | try { |
| | | return Integer.parseInt(valueString); |
| | | } catch (final Exception e) { |
| | | throw new ArgumentException(ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, longIdentifier), e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 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 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() { |
| | | return !values.isEmpty() ? values.getFirst() : defaultValue; |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public List<String> getValues() { |
| | | return values; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether this argument has at least one value. |
| | | * |
| | | * @return <CODE>true</CODE> if this argument has at least one value, or |
| | | * <CODE>false</CODE> if it does not have any values. |
| | | */ |
| | | public boolean hasValue() { |
| | | return !values.isEmpty(); |
| | | } |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether this argument is required to have at least one value. |
| | | * |
| | | * @return <CODE>true</CODE> if this argument is required to have at least |
| | | * one value, or <CODE>false</CODE> if it does not need to have a value. |
| | | */ |
| | | public boolean 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 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; |
| | | } |
| | | |
| | | void valueSetByProperty() { |
| | | isValueSetByProperty = true; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether the provided value is acceptable for use in this |
| | | * argument. |
| | | * |
| | | * @param valueString |
| | | * The value for which to make the determination. |
| | | * @param invalidReason |
| | | * A buffer into which the invalid reason may be written if the |
| | | * value is not acceptable. |
| | | * @return <CODE>true</CODE> if the value is acceptable, or |
| | | * <CODE>false</CODE> if it is not. |
| | | */ |
| | | public abstract boolean valueIsAcceptable(String valueString, LocalizableMessageBuilder invalidReason); |
| | | |
| | | @Override |
| | | public String toString() { |
| | | final StringBuilder sb = new StringBuilder(); |
| | | sb.append(getClass().getSimpleName()); |
| | | sb.append("("); |
| | | if (longIdentifier != null) { |
| | | sb.append("longID="); |
| | | sb.append(longIdentifier); |
| | | } |
| | | if (shortIdentifier != null) { |
| | | if (longIdentifier != null) { |
| | | sb.append(", "); |
| | | } |
| | | sb.append("shortID="); |
| | | sb.append(shortIdentifier); |
| | | } |
| | | sb.append(", values=").append(values); |
| | | sb.append(")"); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean equals(final Object arg) { |
| | | return this == arg || (arg instanceof Argument && ((Argument) arg).longIdentifier.equals(this.longIdentifier)); |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() { |
| | | return longIdentifier.hashCode(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | /** |
| | | * This class contains short and long options used by the argument in CLI. |
| | | */ |
| | | public final class ArgumentConstants { |
| | | |
| | | /** |
| | | * The name of the SASL property that can be used to provide the |
| | | * authentication ID for the bind. |
| | | */ |
| | | public static final String SASL_PROPERTY_AUTHID = "authid"; |
| | | /** |
| | | * The name of the SASL property that can be used to provide the |
| | | * authorization ID for the bind. |
| | | */ |
| | | public static final String SASL_PROPERTY_AUTHZID = "authzid"; |
| | | /** |
| | | * The name of the SASL property that can be used to provide the digest URI |
| | | * for the bind. |
| | | */ |
| | | public static final String SASL_PROPERTY_DIGEST_URI = "digest-uri"; |
| | | /** |
| | | * The name of the SASL property that can be used to provide the KDC for use |
| | | * in Kerberos authentication. |
| | | */ |
| | | public static final String SASL_PROPERTY_KDC = "kdc"; |
| | | /** |
| | | * The name of the SASL property that can be used to provide the quality of |
| | | * protection for the bind. |
| | | */ |
| | | public static final String SASL_PROPERTY_QOP = "qop"; |
| | | /** |
| | | * The name of the SASL property that can be used to provide the realm for |
| | | * the bind. |
| | | */ |
| | | public static final String SASL_PROPERTY_REALM = "realm"; |
| | | /** |
| | | * The name of the SASL property that can be used to provide the SASL |
| | | * mechanism to use. |
| | | */ |
| | | public static final String SASL_PROPERTY_MECH = "mech"; |
| | | |
| | | /** The value for the long option batch. */ |
| | | public static final String OPTION_LONG_BATCH = "batch"; |
| | | /** The value for the short option batchFilePath. */ |
| | | public static final char OPTION_SHORT_BATCH_FILE_PATH = 'F'; |
| | | /** The value for the long option batchFilePath. */ |
| | | public static final String OPTION_LONG_BATCH_FILE_PATH = "batchFilePath"; |
| | | |
| | | /** The value for the short option host name. */ |
| | | public static final char OPTION_SHORT_HOST = 'h'; |
| | | /** The value for the long option host name. */ |
| | | public static final String OPTION_LONG_HOST = "hostname"; |
| | | |
| | | /** The value for the short option port. */ |
| | | public static final char OPTION_SHORT_PORT = 'p'; |
| | | /** The value for the long option port. */ |
| | | public static final String OPTION_LONG_PORT = "port"; |
| | | |
| | | /** The value for the short option useSSL. */ |
| | | public static final char OPTION_SHORT_USE_SSL = 'Z'; |
| | | /** The value for the long option useSSL. */ |
| | | public static final String OPTION_LONG_USE_SSL = "useSSL"; |
| | | |
| | | /** The value for the short option baseDN. */ |
| | | public static final char OPTION_SHORT_BASEDN = 'b'; |
| | | /** The value for the long option baseDN. */ |
| | | public static final String OPTION_LONG_BASEDN = "baseDN"; |
| | | |
| | | /** The value for the short option bindDN. */ |
| | | public static final char OPTION_SHORT_BINDDN = 'D'; |
| | | /** The value for the long option bindDN. */ |
| | | public static final String OPTION_LONG_BINDDN = "bindDN"; |
| | | |
| | | /** The value for the short option bindPassword. */ |
| | | public static final char OPTION_SHORT_BINDPWD = 'w'; |
| | | /** The value for the long option bindPassword. */ |
| | | public static final String OPTION_LONG_BINDPWD = "bindPassword"; |
| | | |
| | | /** The value for the short option bindPasswordFile. */ |
| | | public static final char OPTION_SHORT_BINDPWD_FILE = 'j'; |
| | | /** The value for the long option bindPasswordFile. */ |
| | | public static final String OPTION_LONG_BINDPWD_FILE = "bindPasswordFile"; |
| | | |
| | | /** The value for the short option compress. */ |
| | | public static final char OPTION_SHORT_COMPRESS = 'c'; |
| | | /** The value for the long option compress. */ |
| | | public static final String OPTION_LONG_COMPRESS = "compress"; |
| | | |
| | | /** The value for the short option filename. */ |
| | | public static final char OPTION_SHORT_FILENAME = 'f'; |
| | | /** The value for the long option filename. */ |
| | | public static final String OPTION_LONG_FILENAME = "filename"; |
| | | |
| | | /** The value for the short option ldifFile. */ |
| | | public static final char OPTION_SHORT_LDIF_FILE = 'l'; |
| | | /** The value for the long option ldifFile. */ |
| | | public static final String OPTION_LONG_LDIF_FILE = "ldifFile"; |
| | | |
| | | /** The value for the short option useStartTLS. */ |
| | | public static final char OPTION_SHORT_START_TLS = 'q'; |
| | | /** The value for the long option useStartTLS. */ |
| | | public static final String OPTION_LONG_START_TLS = "useStartTLS"; |
| | | |
| | | /** The value for the short option randomSeed. */ |
| | | public static final char OPTION_SHORT_RANDOM_SEED = 's'; |
| | | /** The value for the long option randomSeed. */ |
| | | public static final String OPTION_LONG_RANDOM_SEED = "randomSeed"; |
| | | |
| | | /** The value for the short option keyStorePath. */ |
| | | public static final char OPTION_SHORT_KEYSTOREPATH = 'K'; |
| | | /** The value for the long option keyStorePath. */ |
| | | public static final String OPTION_LONG_KEYSTOREPATH = "keyStorePath"; |
| | | |
| | | /** The value for the short option trustStorePath. */ |
| | | public static final char OPTION_SHORT_TRUSTSTOREPATH = 'P'; |
| | | /** The value for the long option trustStorePath. */ |
| | | public static final String OPTION_LONG_TRUSTSTOREPATH = "trustStorePath"; |
| | | |
| | | /** The value for the short option keyStorePassword. */ |
| | | public static final char OPTION_SHORT_KEYSTORE_PWD = 'W'; |
| | | /** The value for the long option keyStorePassword. */ |
| | | public static final String OPTION_LONG_KEYSTORE_PWD = "keyStorePassword"; |
| | | |
| | | /** The value for the short option trustStorePassword. */ |
| | | public static final char OPTION_SHORT_TRUSTSTORE_PWD = 'T'; |
| | | /** The value for the long option trustStorePassword. */ |
| | | public static final String OPTION_LONG_TRUSTSTORE_PWD = "trustStorePassword"; |
| | | |
| | | /** The value for the short option keyStorePasswordFile . */ |
| | | public static final char OPTION_SHORT_KEYSTORE_PWD_FILE = 'u'; |
| | | /** The value for the long option keyStorePasswordFile . */ |
| | | public static final String OPTION_LONG_KEYSTORE_PWD_FILE = "keyStorePasswordFile"; |
| | | |
| | | /** The value for the short option keyStorePasswordFile . */ |
| | | public static final char OPTION_SHORT_TRUSTSTORE_PWD_FILE = 'U'; |
| | | /** The value for the long option keyStorePasswordFile . */ |
| | | public static final String OPTION_LONG_TRUSTSTORE_PWD_FILE = "trustStorePasswordFile"; |
| | | /** The value for the short option trustAll . */ |
| | | public static final char OPTION_SHORT_TRUSTALL = 'X'; |
| | | /** The value for the long option trustAll . */ |
| | | public static final String OPTION_LONG_TRUSTALL = "trustAll"; |
| | | |
| | | /** The value for the short option certNickname . */ |
| | | public static final char OPTION_SHORT_CERT_NICKNAME = 'N'; |
| | | /** The value for the long option certNickname . */ |
| | | public static final String OPTION_LONG_CERT_NICKNAME = "certNickname"; |
| | | |
| | | /** The value for the long option assertionFilter . */ |
| | | public static final String OPTION_LONG_ASSERTION_FILE = "assertionFilter"; |
| | | |
| | | /** The value for the short option dry-run. */ |
| | | public static final char OPTION_SHORT_DRYRUN = 'n'; |
| | | /** The value for the long option dry-run. */ |
| | | public static final String OPTION_LONG_DRYRUN = "dry-run"; |
| | | |
| | | /** The value for the short option help. */ |
| | | public static final char OPTION_SHORT_HELP = 'H'; |
| | | /** The value for the long option help. */ |
| | | public static final String OPTION_LONG_HELP = "help"; |
| | | |
| | | /** The value for the long option cli. */ |
| | | public static final String OPTION_LONG_CLI = "cli"; |
| | | /** The value for the short option cli. */ |
| | | public static final char OPTION_SHORT_CLI = 'i'; |
| | | |
| | | /** The value for the short option proxyAs. */ |
| | | public static final char OPTION_SHORT_PROXYAUTHID = 'Y'; |
| | | /** The value for the long option proxyAs. */ |
| | | public static final String OPTION_LONG_PROXYAUTHID = "proxyAs"; |
| | | |
| | | /** The value for the short option saslOption. */ |
| | | public static final char OPTION_SHORT_SASLOPTION = 'o'; |
| | | /** The value for the long option saslOption. */ |
| | | public static final String OPTION_LONG_SASLOPTION = "saslOption"; |
| | | |
| | | /** The value for the short option searchScope. */ |
| | | public static final char OPTION_SHORT_SEARCHSCOPE = 's'; |
| | | /** The value for the long option searchScope. */ |
| | | public static final String OPTION_LONG_SEARCHSCOPE = "searchScope"; |
| | | |
| | | /** The value for the short option geteffectiverights control authzid. */ |
| | | public static final char OPTION_SHORT_EFFECTIVERIGHTSUSER = 'g'; |
| | | /** The value for the long option geteffectiverights control authzid. */ |
| | | public static final String OPTION_LONG_EFFECTIVERIGHTSUSER = "getEffectiveRightsAuthzid"; |
| | | /** The value for the short option geteffectiveights control attributes. */ |
| | | public static final char OPTION_SHORT_EFFECTIVERIGHTSATTR = 'e'; |
| | | /** |
| | | * The value for the long option geteffectiverights control specific |
| | | * attribute list. |
| | | */ |
| | | public static final String OPTION_LONG_EFFECTIVERIGHTSATTR = "getEffectiveRightsAttribute"; |
| | | |
| | | /** The value for the short option protocol version attributes. */ |
| | | public static final char OPTION_SHORT_PROTOCOL_VERSION = 'V'; |
| | | /** The value for the long option protocol version attribute. */ |
| | | public static final String OPTION_LONG_PROTOCOL_VERSION = "ldapVersion"; |
| | | |
| | | /** The value for the long option version. */ |
| | | public static final char OPTION_SHORT_PRODUCT_VERSION = 'V'; |
| | | /** The value for the long option version. */ |
| | | public static final String OPTION_LONG_PRODUCT_VERSION = "version"; |
| | | |
| | | /** The value for the long "checkStoppability" {@link Argument}. */ |
| | | public static final String OPTION_LONG_CHECK_STOPPABILITY = "checkStoppability"; |
| | | /** The value for the long "windowsNetStop" {@link Argument}. */ |
| | | public static final String OPTION_LONG_WINDOWS_NET_STOP = "windowsNetStop"; |
| | | |
| | | /** Value for the quiet option short form. */ |
| | | public static final Character OPTION_SHORT_QUIET = 'Q'; |
| | | /** Value for the quiet option long form. */ |
| | | public static final String OPTION_LONG_QUIET = "quiet"; |
| | | |
| | | /** Value for non-interactive session short form. */ |
| | | public static final Character OPTION_SHORT_NO_PROMPT = 'n'; |
| | | /** Value for non-interactive session long form. */ |
| | | public static final String OPTION_LONG_NO_PROMPT = "no-prompt"; |
| | | |
| | | /** Long form of script friendly option. */ |
| | | public static final String OPTION_LONG_SCRIPT_FRIENDLY = "script-friendly"; |
| | | /** Short form of script friendly option. */ |
| | | public static final Character OPTION_SHORT_SCRIPT_FRIENDLY = 's'; |
| | | |
| | | /** Value for verbose option short form. */ |
| | | public static final Character OPTION_SHORT_VERBOSE = 'v'; |
| | | /** Value for verbose option long form. */ |
| | | public static final String OPTION_LONG_VERBOSE = "verbose"; |
| | | |
| | | /** The value for the long option propertiesFilePAth . */ |
| | | public static final String OPTION_LONG_PROP_FILE_PATH = "propertiesFilePath"; |
| | | /** The value for the long option propertiesFilePAth . */ |
| | | public static final String OPTION_LONG_NO_PROP_FILE = "noPropertiesFile"; |
| | | |
| | | /** Long form of referenced host name. */ |
| | | public static final String OPTION_LONG_REFERENCED_HOST_NAME = "referencedHostName"; |
| | | |
| | | /** Long form of admin UID. */ |
| | | public static final String OPTION_LONG_ADMIN_UID = "adminUID"; |
| | | |
| | | /** Long form of report authorization ID connection option. */ |
| | | public static final String OPTION_LONG_REPORT_AUTHZ_ID = "reportAuthzID"; |
| | | |
| | | /** Long form of use password policy control connection option. */ |
| | | public static final String OPTION_LONG_USE_PW_POLICY_CTL = "usePasswordPolicyControl"; |
| | | |
| | | /** Long form of use SASL external connection option. */ |
| | | public static final String OPTION_LONG_USE_SASL_EXTERNAL = "useSASLExternal"; |
| | | |
| | | /** Long form of option for the command-line encoding option. */ |
| | | public static final String OPTION_LONG_ENCODING = "encoding"; |
| | | |
| | | /** Long form of option specifying no wrapping of the command-line. */ |
| | | public static final String OPTION_LONG_DONT_WRAP = "dontWrap"; |
| | | |
| | | /** The value for the long option targetDN. */ |
| | | public static final String OPTION_LONG_TARGETDN = "targetDN"; |
| | | |
| | | /** Long form of email notification upon completion option. */ |
| | | public static final String OPTION_LONG_COMPLETION_NOTIFICATION_EMAIL = "completionNotify"; |
| | | /** Short form of email notification upon completion option. */ |
| | | public static final Character OPTION_SHORT_COMPLETION_NOTIFICATION_EMAIL = null; |
| | | |
| | | /** Long form of email notification upon error option. */ |
| | | public static final String OPTION_LONG_ERROR_NOTIFICATION_EMAIL = "errorNotify"; |
| | | /** Short form of email notification upon error option. */ |
| | | public static final Character OPTION_SHORT_ERROR_NOTIFICATION_EMAIL = null; |
| | | |
| | | /** Long form of dependency option. */ |
| | | public static final String OPTION_LONG_DEPENDENCY = "dependency"; |
| | | /** Short form of dependency option. */ |
| | | public static final Character OPTION_SHORT_DEPENDENCY = null; |
| | | |
| | | /** Long form of failed dependency action option. */ |
| | | public static final String OPTION_LONG_FAILED_DEPENDENCY_ACTION = "failedDependencyAction"; |
| | | /** Short form of failed dependency action option. */ |
| | | public static final Character OPTION_SHORT_FAILED_DEPENDENCY_ACTION = null; |
| | | |
| | | /** The default separator to be used in tables. */ |
| | | public static final String LIST_TABLE_SEPARATOR = ":"; |
| | | |
| | | /** The value for the short option output LDIF filename. */ |
| | | public static final char OPTION_SHORT_OUTPUT_LDIF_FILENAME = 'o'; |
| | | /** The value for the long option output LDIF filename. */ |
| | | public static final String OPTION_LONG_OUTPUT_LDIF_FILENAME = "outputLDIF"; |
| | | |
| | | /** The value for the long option to automatically accept the license if present. */ |
| | | public static final String OPTION_LONG_ACCEPT_LICENSE = "acceptLicense"; |
| | | |
| | | /** The value for the short option rootUserDN. */ |
| | | public static final char OPTION_SHORT_ROOT_USER_DN = 'D'; |
| | | /** The value for the long option rootUserDN. */ |
| | | public static final String OPTION_LONG_ROOT_USER_DN = "rootUserDN"; |
| | | |
| | | /** The value for the long option connect timeout attribute. */ |
| | | public static final String OPTION_LONG_CONNECT_TIMEOUT = "connectTimeout"; |
| | | |
| | | /** The value for the long option advanced. */ |
| | | public static final String OPTION_LONG_ADVANCED = "advanced"; |
| | | |
| | | /** Display the equivalent non-interactive command. */ |
| | | public static final String OPTION_LONG_DISPLAY_EQUIVALENT = "displayCommand"; |
| | | |
| | | /** The path where we write the equivalent non-interactive command. */ |
| | | public static final String OPTION_LONG_EQUIVALENT_COMMAND_FILE_PATH = "commandFilePath"; |
| | | |
| | | /** The value for the short option remote . */ |
| | | public static final char OPTION_SHORT_REMOTE = 'r'; |
| | | /** The value for the long option remote . */ |
| | | public static final String OPTION_LONG_REMOTE = "remote"; |
| | | |
| | | /** The value for the short option configClass. */ |
| | | public static final char OPTION_SHORT_CONFIG_CLASS = 'C'; |
| | | /** The value for the long option configClass. */ |
| | | public static final String OPTION_LONG_CONFIG_CLASS = "configClass"; |
| | | |
| | | /** Value for the server root option short form. */ |
| | | public static final Character OPTION_SHORT_SERVER_ROOT = 'R'; |
| | | |
| | | /** Value for the server root option long form. */ |
| | | public static final String OPTION_LONG_SERVER_ROOT = "serverRoot"; |
| | | |
| | | /** Value for the control option short form. */ |
| | | public static final Character OPTION_SHORT_CONTROL = 'J'; |
| | | /** Value for the control option long form. */ |
| | | public static final String OPTION_LONG_CONTROL = "control"; |
| | | |
| | | /** Recurring task option long form. */ |
| | | public static final String OPTION_LONG_RECURRING_TASK = "recurringTask"; |
| | | /** Recurring task option short form. */ |
| | | public static final Character OPTION_SHORT_RECURRING_TASK = null; |
| | | |
| | | /** Subentries control option long form. */ |
| | | public static final String OPTION_LONG_SUBENTRIES = "subEntries"; |
| | | /** Subentries control option short form. */ |
| | | public static final Character OPTION_SHORT_SUBENTRIES = null; |
| | | |
| | | /** Scheduled start date/time option long form. */ |
| | | public static final String OPTION_LONG_START_DATETIME = "start"; |
| | | /** Scheduled start date/time option short form. */ |
| | | public static final Character OPTION_SHORT_START_DATETIME = 't'; |
| | | |
| | | /** Long form of admin password. */ |
| | | public static final String OPTION_LONG_ADMIN_PWD = "adminPassword"; |
| | | /** Long form of admin password file. */ |
| | | public static final String OPTION_LONG_ADMIN_PWD_FILE = "adminPasswordFile"; |
| | | |
| | | /** |
| | | * The name of the SASL property that can be used to provide trace information |
| | | * for a SASL ANONYMOUS request. |
| | | */ |
| | | public static final String SASL_PROPERTY_TRACE = "trace"; |
| | | |
| | | /** The value for the long option force upgrade. */ |
| | | public static final String OPTION_LONG_FORCE_UPGRADE = "force"; |
| | | |
| | | /** The value for the long option ignore errors. */ |
| | | public static final String OPTION_LONG_IGNORE_ERRORS = "ignoreErrors"; |
| | | |
| | | /** Value for the restart option long form. */ |
| | | public static final String OPTION_LONG_RESTART = "restart"; |
| | | |
| | | /** The value for the hidden testonly argument. */ |
| | | public static final String OPTION_LONG_TESTONLY_ARGUMENT = "testOnly"; |
| | | |
| | | /** The value for the backend type long option. */ |
| | | public static final String OPTION_LONG_BACKEND_TYPE = "backendType"; |
| | | |
| | | /** The value for the backend type short option. */ |
| | | public static final Character OPTION_SHORT_BACKEND_TYPE = 't'; |
| | | |
| | | /** Prevent instantiation. */ |
| | | private ArgumentConstants() { |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import org.forgerock.i18n.LocalizableException; |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * This class defines an exception that may be thrown if there is a problem with |
| | | * an argument definition. |
| | | */ |
| | | @SuppressWarnings("serial") |
| | | public final class ArgumentException extends Exception implements LocalizableException { |
| | | /** The I18N message associated with this exception. */ |
| | | private final LocalizableMessage message; |
| | | |
| | | /** |
| | | * Creates a new argument exception with the provided message. |
| | | * |
| | | * @param message |
| | | * The message that explains the problem that occurred. |
| | | */ |
| | | public ArgumentException(final LocalizableMessage message) { |
| | | super(String.valueOf(message)); |
| | | this.message = message; |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public ArgumentException(final LocalizableMessage message, final Throwable cause) { |
| | | super(String.valueOf(message), cause); |
| | | this.message = message; |
| | | } |
| | | |
| | | @Override |
| | | public LocalizableMessage getMessageObject() { |
| | | return this.message; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions copyright 2012-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.util.Collections; |
| | | import java.util.Iterator; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * Class for organizing options into logical groups when argument usage is printed. To use an argument group, create an |
| | | * instance and use {@code ArgumentParser#addArgument(Argument, ArgumentGroup)} when adding arguments for to the parser. |
| | | */ |
| | | public final class ArgumentGroup implements Comparable<ArgumentGroup> { |
| | | |
| | | /** Description for this group of arguments. */ |
| | | private LocalizableMessage description; |
| | | /** List of arguments belonging to this group. */ |
| | | private final List<Argument> args = new LinkedList<>(); |
| | | /** Governs groups position within usage statement. */ |
| | | private final Integer priority; |
| | | |
| | | /** |
| | | * Creates a parameterized instance. |
| | | * |
| | | * @param description |
| | | * for options in this group that is printed before argument descriptions in usage output |
| | | * @param priority |
| | | * number governing the position of this group within the usage statement. Groups with higher priority |
| | | * values appear before groups with lower priority. |
| | | */ |
| | | public ArgumentGroup(final LocalizableMessage description, final int priority) { |
| | | this.description = description; |
| | | this.priority = priority; |
| | | } |
| | | |
| | | @Override |
| | | public int compareTo(final ArgumentGroup o) { |
| | | // Groups with higher priority numbers appear before |
| | | // those with lower priority in the usage output |
| | | return -1 * priority.compareTo(o.priority); |
| | | } |
| | | |
| | | /** |
| | | * Adds an argument to this group. |
| | | * |
| | | * @param arg |
| | | * to add |
| | | * @return boolean where true indicates the add was successful |
| | | */ |
| | | public boolean addArgument(final Argument arg) { |
| | | 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; |
| | | } |
| | | } |
| | | |
| | | return this.args.add(arg); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether this group contains any members. |
| | | * |
| | | * @return boolean where true means this group contains members |
| | | */ |
| | | boolean containsArguments() { |
| | | return !args.isEmpty(); |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether this group contains any non-hidden members. |
| | | * |
| | | * @return boolean where true means this group contains non-hidden members |
| | | */ |
| | | boolean containsNonHiddenArguments() { |
| | | for (final Argument arg : args) { |
| | | if (!arg.isHidden()) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Gets the list of arguments associated with this group. |
| | | * |
| | | * @return list of associated arguments |
| | | */ |
| | | List<Argument> getArguments() { |
| | | return Collections.unmodifiableList(args); |
| | | } |
| | | |
| | | /** |
| | | * Gets the description for this group of arguments. |
| | | * |
| | | * @return description for this argument group |
| | | */ |
| | | LocalizableMessage getDescription() { |
| | | return this.description; |
| | | } |
| | | |
| | | /** |
| | | * Removes an argument from this group. |
| | | * |
| | | * @param arg |
| | | * to remove |
| | | * @return boolean where true indicates the remove was successful |
| | | */ |
| | | boolean removeArgument(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; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return getClass().getSimpleName() + "(description=" + description + ")"; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2012-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.ArgumentConstants.*; |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | import static com.forgerock.opendj.cli.DocGenerationHelper.*; |
| | | import static com.forgerock.opendj.cli.Utils.*; |
| | | import static com.forgerock.opendj.util.StaticUtils.*; |
| | | |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.OutputStream; |
| | | import java.io.PrintStream; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Comparator; |
| | | import java.util.Date; |
| | | import java.util.Enumeration; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Locale; |
| | | import java.util.Map; |
| | | import java.util.Properties; |
| | | import java.util.Set; |
| | | import java.util.SortedSet; |
| | | import java.util.TreeSet; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | |
| | | /** |
| | | * 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 |
| | | * internationalizable 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. |
| | | */ |
| | | public class ArgumentParser implements ToolRefDocContainer { |
| | | |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | private static final Set<String> HOST_LONG_IDENTIFIERS = new HashSet<>(Arrays.asList( |
| | | OPTION_LONG_HOST, |
| | | OPTION_LONG_REFERENCED_HOST_NAME, |
| | | "host1", |
| | | "host2", |
| | | "hostSource", |
| | | "hostDestination")); |
| | | |
| | | /** |
| | | * The name of the OpenDJ configuration direction in the user home |
| | | * directory. |
| | | */ |
| | | public static final String DEFAULT_OPENDJ_CONFIG_DIR = ".opendj"; |
| | | /** The default properties file name. */ |
| | | public static final String DEFAULT_OPENDJ_PROPERTIES_FILE_NAME = "tools"; |
| | | /** The default properties file extension. */ |
| | | public static final String DEFAULT_OPENDJ_PROPERTIES_FILE_EXTENSION = ".properties"; |
| | | /** The name of a command-line script used to launch a tool. */ |
| | | public static final String PROPERTY_SCRIPT_NAME = "com.forgerock.opendj.ldap.tools.scriptName"; |
| | | /** The legacy name of a command-line script used to launch a tool. */ |
| | | public static final String PROPERTY_SCRIPT_NAME_LEGACY = "org.opends.server.scriptName"; |
| | | |
| | | /** The argument that will be used to indicate the file properties. */ |
| | | private StringArgument filePropertiesPathArgument; |
| | | /** The argument that will be used to indicate that we'll not look for default properties file. */ |
| | | private BooleanArgument noPropertiesFileArgument; |
| | | /** The argument that will be used to trigger the display of usage information. */ |
| | | private Argument usageArgument; |
| | | /** The argument that will be used to trigger the display of the OpenDJ version. */ |
| | | private Argument versionArgument; |
| | | |
| | | /** The set of unnamed trailing arguments that were provided for this parser. */ |
| | | private final ArrayList<String> trailingArguments = new ArrayList<>(); |
| | | |
| | | /** |
| | | * Indicates whether this parser will allow additional unnamed arguments at |
| | | * the end of the list. |
| | | */ |
| | | private final boolean allowsTrailingArguments; |
| | | /** Indicates whether long arguments should be treated in a case-sensitive manner. */ |
| | | private final boolean longArgumentsCaseSensitive; |
| | | /** Indicates whether the usage or version information has been displayed. */ |
| | | private boolean usageOrVersionDisplayed; |
| | | /** Indicates whether the version argument was provided. */ |
| | | private boolean versionPresent; |
| | | |
| | | /** The handler to call to print the product version. */ |
| | | private VersionHandler versionHandler = new VersionHandler() { |
| | | @Override |
| | | public void printVersion() { |
| | | // display nothing at all |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return "<no version displayed>"; |
| | | } |
| | | }; |
| | | |
| | | /** The set of arguments defined for this parser, referenced by short ID. */ |
| | | private final Map<Character, Argument> shortIDMap = new HashMap<>(); |
| | | /** The set of arguments defined for this parser, referenced by long ID. */ |
| | | private final Map<String, Argument> longIDMap = new HashMap<>(); |
| | | /** The total set of arguments defined for this parser. */ |
| | | private final List<Argument> argumentList = new LinkedList<>(); |
| | | |
| | | /** The maximum number of unnamed trailing arguments that may be provided. */ |
| | | private final int maxTrailingArguments; |
| | | /** The minimum number of unnamed trailing arguments that may be provided. */ |
| | | private final int minTrailingArguments; |
| | | |
| | | /** The output stream to which usage information should be printed. */ |
| | | private OutputStream usageOutputStream = System.out; |
| | | |
| | | /** |
| | | * The fully-qualified name of the Java class that should be invoked to |
| | | * launch the program with which this argument parser is associated. |
| | | */ |
| | | private final String mainClassName; |
| | | |
| | | /** |
| | | * A human-readable description for the tool, which will be included when |
| | | * displaying usage information. |
| | | */ |
| | | private final LocalizableMessage toolDescription; |
| | | /** A short description for this tool, suitable in a man page summary line. */ |
| | | private LocalizableMessage shortToolDescription; |
| | | |
| | | /** The display name that will be used for the trailing arguments in the usage information. */ |
| | | private final String trailingArgsDisplayName; |
| | | |
| | | /** Set of argument groups. */ |
| | | protected final Set<ArgumentGroup> argumentGroups = new TreeSet<>(); |
| | | |
| | | /** |
| | | * Group for arguments that have not been explicitly grouped. These will |
| | | * appear at the top of the usage statement without a header. |
| | | */ |
| | | 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. |
| | | */ |
| | | 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. |
| | | */ |
| | | protected 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. |
| | | */ |
| | | private final ArgumentGroup generalArgGroup = new ArgumentGroup( |
| | | INFO_DESCRIPTION_GENERAL_ARGS.get(), Integer.MIN_VALUE); |
| | | |
| | | private static final String INDENT = " "; |
| | | |
| | | /** |
| | | * 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. |
| | | * @param toolDescription |
| | | * 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. |
| | | */ |
| | | public ArgumentParser(final String mainClassName, final LocalizableMessage toolDescription, |
| | | final boolean longArgumentsCaseSensitive) { |
| | | this.mainClassName = mainClassName; |
| | | this.toolDescription = toolDescription; |
| | | this.longArgumentsCaseSensitive = longArgumentsCaseSensitive; |
| | | |
| | | allowsTrailingArguments = false; |
| | | trailingArgsDisplayName = null; |
| | | maxTrailingArguments = 0; |
| | | minTrailingArguments = 0; |
| | | initGroups(); |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | * @param toolDescription |
| | | * 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. |
| | | * @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. |
| | | * @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. |
| | | * @param trailingArgsDisplayName |
| | | * The display name that should be used as a placeholder for |
| | | * unnamed trailing arguments in the generated usage information. |
| | | */ |
| | | public 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; |
| | | this.longArgumentsCaseSensitive = longArgumentsCaseSensitive; |
| | | this.allowsTrailingArguments = allowsTrailingArguments; |
| | | this.minTrailingArguments = minTrailingArguments; |
| | | this.maxTrailingArguments = maxTrailingArguments; |
| | | this.trailingArgsDisplayName = trailingArgsDisplayName; |
| | | |
| | | initGroups(); |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public void addArgument(final Argument argument) throws ArgumentException { |
| | | addArgument(argument, null); |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public void addArgument(final Argument argument, ArgumentGroup group) throws ArgumentException { |
| | | final Character shortID = argument.getShortIdentifier(); |
| | | if (shortID != null && shortIDMap.containsKey(shortID)) { |
| | | final String conflictingID = shortIDMap.get(shortID).getLongIdentifier(); |
| | | throw new ArgumentException( |
| | | ERR_ARGPARSER_DUPLICATE_SHORT_ID.get(argument.getLongIdentifier(), shortID, conflictingID)); |
| | | } |
| | | |
| | | // JNR: what is the requirement for the following code? |
| | | if (versionArgument != null |
| | | && shortID != null |
| | | && shortID.equals(versionArgument.getShortIdentifier())) { |
| | | // Update the version argument to not display its short identifier. |
| | | try { |
| | | versionArgument = getVersionArgument(false); |
| | | // JNR: why not call addGeneralArgument(versionArgument) here? |
| | | this.generalArgGroup.addArgument(versionArgument); |
| | | } catch (final ArgumentException e) { |
| | | // ignore |
| | | } |
| | | } |
| | | |
| | | final String longID = formatLongIdentifier(argument.getLongIdentifier()); |
| | | if (longIDMap.containsKey(longID)) { |
| | | throw new ArgumentException(ERR_ARGPARSER_DUPLICATE_LONG_ID.get(argument.getLongIdentifier())); |
| | | } |
| | | |
| | | if (shortID != null) { |
| | | shortIDMap.put(shortID, argument); |
| | | } |
| | | |
| | | if (longID != null) { |
| | | longIDMap.put(longID, argument); |
| | | } |
| | | |
| | | argumentList.add(argument); |
| | | |
| | | if (group == null) { |
| | | group = getStandardGroup(argument); |
| | | } |
| | | group.addArgument(argument); |
| | | argumentGroups.add(group); |
| | | } |
| | | |
| | | private BooleanArgument getVersionArgument(final boolean displayShortIdentifier) throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_PRODUCT_VERSION) |
| | | .shortIdentifier(displayShortIdentifier ? OPTION_SHORT_PRODUCT_VERSION : null) |
| | | .description(INFO_DESCRIPTION_PRODUCT_VERSION.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Adds the provided argument to the set of arguments handled by this parser |
| | | * and puts the argument 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. |
| | | */ |
| | | protected void addDefaultArgument(final 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. |
| | | */ |
| | | public void addLdapConnectionArgument(final Argument argument) throws ArgumentException { |
| | | addArgument(argument, ldapArgGroup); |
| | | } |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | /** |
| | | * Check if we have a properties file. |
| | | * |
| | | * @return The properties found in the properties file or null. |
| | | * @throws ArgumentException |
| | | * If a problem was encountered while parsing the provided |
| | | * arguments. |
| | | */ |
| | | Properties checkExternalProperties() throws ArgumentException { |
| | | // We don't look for properties file. |
| | | if (noPropertiesFileArgument != null && noPropertiesFileArgument.isPresent()) { |
| | | return null; |
| | | } |
| | | |
| | | // Check if we have a properties file argument |
| | | if (filePropertiesPathArgument == null) { |
| | | return null; |
| | | } |
| | | |
| | | // check if the properties file argument has been set. If not look for default location. |
| | | String propertiesFilePath; |
| | | if (filePropertiesPathArgument.isPresent()) { |
| | | propertiesFilePath = filePropertiesPathArgument.getValue(); |
| | | } else { |
| | | // Check in "user home"/.opendj directory |
| | | final String userDir = System.getProperty("user.home"); |
| | | propertiesFilePath = |
| | | findPropertiesFile(userDir + File.separator + DEFAULT_OPENDJ_CONFIG_DIR); |
| | | } |
| | | |
| | | // We don't have a properties file location |
| | | if (propertiesFilePath == null) { |
| | | return null; |
| | | } |
| | | |
| | | // We have a location for the properties file. |
| | | try { |
| | | final Properties argumentProperties = new Properties(); |
| | | final String scriptName = getScriptName(); |
| | | final Properties p = new Properties(); |
| | | try (final FileInputStream fis = new FileInputStream(propertiesFilePath)) { |
| | | p.load(fis); |
| | | } |
| | | |
| | | for (final Enumeration<?> e = p.propertyNames(); e.hasMoreElements();) { |
| | | final String currentPropertyName = (String) e.nextElement(); |
| | | String propertyName = currentPropertyName; |
| | | |
| | | // Property name form <script name>.<property name> has the |
| | | // precedence to <property name> |
| | | if (scriptName != null) { |
| | | if (currentPropertyName.startsWith(scriptName)) { |
| | | propertyName = currentPropertyName.substring(scriptName.length() + 1); |
| | | } else if (p.containsKey(scriptName + "." + currentPropertyName)) { |
| | | continue; |
| | | } |
| | | } |
| | | argumentProperties.setProperty(propertyName.toLowerCase(), p |
| | | .getProperty(currentPropertyName)); |
| | | } |
| | | return argumentProperties; |
| | | } catch (final Exception e) { |
| | | final LocalizableMessage message = |
| | | ERR_ARGPARSER_CANNOT_READ_PROPERTIES_FILE.get(propertiesFilePath, getExceptionMessage(e)); |
| | | throw new ArgumentException(message, e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public Argument getArgumentForLongID(final String longID) { |
| | | return longIDMap.get(formatLongIdentifier(longID)); |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public List<Argument> getArgumentList() { |
| | | return argumentList; |
| | | } |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | /** |
| | | * 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) { |
| | | if (isInputOutputArgument(argument)) { |
| | | return ioArgGroup; |
| | | } else if (isGeneralArgument(argument)) { |
| | | return generalArgGroup; |
| | | } else if (isLdapConnectionArgument(argument)) { |
| | | return ldapArgGroup; |
| | | } else { |
| | | return defaultArgGroup; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | @Override |
| | | public LocalizableMessage getShortToolDescription() { |
| | | return shortToolDescription != null ? shortToolDescription : LocalizableMessage.EMPTY; |
| | | } |
| | | |
| | | @Override |
| | | public void setShortToolDescription(final LocalizableMessage shortDescription) { |
| | | this.shortToolDescription = shortDescription; |
| | | } |
| | | |
| | | /** |
| | | * A supplement to the description for this tool |
| | | * intended for use in generated reference documentation. |
| | | */ |
| | | private DocSubcommandDescriptionSupplement docToolDescriptionSupplement; |
| | | |
| | | @Override |
| | | public LocalizableMessage getDocToolDescriptionSupplement() { |
| | | this.docToolDescriptionSupplement = |
| | | constructIfNull(this.docToolDescriptionSupplement); |
| | | return this.docToolDescriptionSupplement.getDocDescriptionSupplement(); |
| | | } |
| | | |
| | | @Override |
| | | public void setDocToolDescriptionSupplement(final LocalizableMessage supplement) { |
| | | this.docToolDescriptionSupplement = |
| | | constructIfNull(this.docToolDescriptionSupplement); |
| | | this.docToolDescriptionSupplement.setDocDescriptionSupplement(supplement); |
| | | } |
| | | |
| | | /** |
| | | * A supplement to the description for all subcommands of this tool, |
| | | * intended for use in generated reference documentation. |
| | | */ |
| | | private class DocSubcommandDescriptionSupplement implements DocDescriptionSupplement { |
| | | /** A supplement to the description intended for use in generated reference documentation. */ |
| | | private LocalizableMessage docDescriptionSupplement; |
| | | |
| | | @Override |
| | | public LocalizableMessage getDocDescriptionSupplement() { |
| | | return docDescriptionSupplement != null ? docDescriptionSupplement : LocalizableMessage.EMPTY; |
| | | } |
| | | |
| | | private void setDocDescriptionSupplement(final LocalizableMessage docDescriptionSupplement) { |
| | | this.docDescriptionSupplement = docDescriptionSupplement; |
| | | } |
| | | } |
| | | |
| | | private DocSubcommandDescriptionSupplement docSubcommandsDescriptionSupplement; |
| | | |
| | | @Override |
| | | public LocalizableMessage getDocSubcommandsDescriptionSupplement() { |
| | | this.docSubcommandsDescriptionSupplement = |
| | | constructIfNull(this.docSubcommandsDescriptionSupplement); |
| | | return this.docSubcommandsDescriptionSupplement.getDocDescriptionSupplement(); |
| | | } |
| | | |
| | | @Override |
| | | public void setDocSubcommandsDescriptionSupplement(final LocalizableMessage supplement) { |
| | | this.docSubcommandsDescriptionSupplement = |
| | | constructIfNull(this.docSubcommandsDescriptionSupplement); |
| | | this.docSubcommandsDescriptionSupplement.setDocDescriptionSupplement(supplement); |
| | | } |
| | | |
| | | private DocSubcommandDescriptionSupplement constructIfNull(DocSubcommandDescriptionSupplement supplement) { |
| | | if (supplement != null) { |
| | | return supplement; |
| | | } |
| | | return new DocSubcommandDescriptionSupplement(); |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public 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. |
| | | */ |
| | | public String getUsage() { |
| | | final StringBuilder buffer = new StringBuilder(); |
| | | usageOrVersionDisplayed = true; |
| | | if (System.getProperty("org.forgerock.opendj.gendoc") != null) { |
| | | toRefEntry(buffer, getSynopsisArgs(), argumentList); |
| | | } else { |
| | | getUsage(buffer); |
| | | } |
| | | return buffer.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Return the list of arguments for the generated reference documentation. |
| | | * |
| | | * @return The list of arguments for the generated reference documentation. |
| | | */ |
| | | String getSynopsisArgs() { |
| | | if (allowsTrailingArguments()) { |
| | | if (trailingArgsDisplayName != null) { |
| | | return trailingArgsDisplayName; |
| | | } else { |
| | | return INFO_ARGPARSER_USAGE_TRAILINGARGS.get().toString(); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * Appends a generated DocBook XML RefEntry (man page) to the StringBuilder. |
| | | * |
| | | * @param builder Append the RefEntry element to this. |
| | | * @param synopsisArgs List of arguments for the command synopsis. |
| | | * @param argList List of (global) arguments for this tool. |
| | | */ |
| | | void toRefEntry(StringBuilder builder, String synopsisArgs, List<Argument> argList) { |
| | | final String scriptName = getScriptName(); |
| | | if (scriptName == null) { |
| | | throw new RuntimeException("The script name should have been set via the environment property '" |
| | | + PROPERTY_SCRIPT_NAME + "'."); |
| | | } |
| | | |
| | | final Map<String, Object> map = new HashMap<>(); |
| | | map.put("locale", Locale.getDefault().getLanguage()); |
| | | map.put("year", new SimpleDateFormat("yyyy").format(new Date())); |
| | | map.put("name", scriptName); |
| | | map.put("shortDesc", getShortToolDescription()); |
| | | map.put("descTitle", REF_TITLE_DESCRIPTION.get()); |
| | | map.put("args", synopsisArgs); |
| | | map.put("description", eolToNewPara(getToolDescription())); |
| | | map.put("info", getDocToolDescriptionSupplement()); |
| | | if (!argList.isEmpty()) { |
| | | map.put("optionSection", getOptionsRefSect1(scriptName)); |
| | | } |
| | | map.put("subcommands", null); |
| | | map.put("trailingSectionString", System.getProperty("org.forgerock.opendj.gendoc.trailing")); |
| | | applyTemplate(builder, "refEntry.ftl", map); |
| | | } |
| | | |
| | | /** |
| | | * Returns a String with line separators replaced by {@code </para><para>}. |
| | | * @param input String in which to replace line separators. |
| | | * @return A String with line separators replaced by {@code </para><para>}. |
| | | */ |
| | | String eolToNewPara(final LocalizableMessage input) { |
| | | return input.toString().replaceAll(EOL, "</para><para>"); |
| | | } |
| | | |
| | | /** |
| | | * Returns a generated DocBook XML RefSect1 element for all command options. |
| | | * @param scriptName The name of this script. |
| | | * @return The RefSect1 element as a String. |
| | | */ |
| | | protected String getOptionsRefSect1(String scriptName) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("name", scriptName); |
| | | map.put("title", REF_TITLE_OPTIONS.get()); |
| | | map.put("intro", REF_INTRO_OPTIONS.get(scriptName)); |
| | | |
| | | Argument helpArgument = null; |
| | | final boolean printHeaders = printUsageGroupHeaders(); |
| | | List<Map<String, Object>> groups = new LinkedList<>(); |
| | | for (final ArgumentGroup argGroup : argumentGroups) { |
| | | Map<String, Object> group = new HashMap<>(); |
| | | |
| | | // Add the group's description if any |
| | | if (argGroup.containsArguments() && printHeaders) { |
| | | LocalizableMessage description = argGroup.getDescription(); |
| | | if (description != LocalizableMessage.EMPTY) { |
| | | group.put("description", eolToNewPara(description)); |
| | | } else { |
| | | group.put("description", INFO_SUBCMDPARSER_WHERE_OPTIONS_INCLUDE.get()); |
| | | } |
| | | } |
| | | |
| | | List<Map<String, Object>> options = new LinkedList<>(); |
| | | final SortedSet<Argument> args = sortArguments(argGroup.getArguments()); |
| | | for (final Argument a : args) { |
| | | if (a.isHidden()) { |
| | | continue; |
| | | } |
| | | |
| | | final Map<String, Object> argumentMap = getArgumentMap(a); |
| | | // Return a generic FQDN for localhost as the default hostname in reference documentation. |
| | | if (isHostNameArgument(a)) { |
| | | argumentMap.put("default", REF_DEFAULT.get("localhost.localdomain")); |
| | | } |
| | | |
| | | // Return a generic message as default backend type depends on the server distribution. |
| | | if (a.getLongIdentifier().equals(OPTION_LONG_BACKEND_TYPE)) { |
| | | argumentMap.put("default", REF_DEFAULT_BACKEND_TYPE.get().toString()); |
| | | } |
| | | |
| | | // The help argument should be added at the end. |
| | | if (isUsageArgument(a)) { |
| | | helpArgument = a; |
| | | continue; |
| | | } |
| | | |
| | | options.add(argumentMap); |
| | | } |
| | | group.put("options", options); |
| | | if (!options.isEmpty()) { |
| | | groups.add(group); |
| | | } |
| | | } |
| | | if (helpArgument != null) { |
| | | Map<String, Object> helpGroup = new HashMap<>(); |
| | | helpGroup.put("description", null); |
| | | List<Map<String, Object>> options = new LinkedList<>(); |
| | | options.add(getArgumentMap(helpArgument)); |
| | | helpGroup.put("options", options); |
| | | groups.add(helpGroup); |
| | | } |
| | | map.put("groups", groups); |
| | | |
| | | StringBuilder sb = new StringBuilder(); |
| | | applyTemplate(sb, "optionsRefSect1.ftl", map); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Returns true if this argument is for setting a hostname. |
| | | * @param a The argument. |
| | | * @return true if this argument is for setting a hostname. |
| | | */ |
| | | boolean isHostNameArgument(final Argument a) { |
| | | return HOST_LONG_IDENTIFIERS.contains(a.getLongIdentifier()); |
| | | } |
| | | |
| | | /** |
| | | * Returns a map containing information about an argument option. |
| | | * @param a The argument |
| | | * @return A map containing information about an argument option |
| | | */ |
| | | private Map<String, Object> getArgumentMap(final Argument a) { |
| | | Map<String, Object> option = new HashMap<>(); |
| | | option.put("synopsis", getOptionSynopsis(a)); |
| | | option.put("description", eolToNewPara(a.getDescription())); |
| | | String dv = a.getDefaultValue(); |
| | | option.put("default", dv != null ? REF_DEFAULT.get(dv) : null); |
| | | option.put("info", a.getDocDescriptionSupplement()); |
| | | return option; |
| | | } |
| | | |
| | | /** |
| | | * Writes message to the usage output stream. |
| | | * |
| | | * @param message the message to write |
| | | */ |
| | | void writeToUsageOutputStream(CharSequence message) { |
| | | try { |
| | | usageOutputStream.write(getBytes(message.toString())); |
| | | } catch (final Exception e) { |
| | | logger.traceException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Appends usage information based on the defined arguments to the provided |
| | | * buffer. |
| | | * |
| | | * @param buffer |
| | | * The buffer to which the usage information should be appended. |
| | | */ |
| | | private void getUsage(final StringBuilder buffer) { |
| | | buffer.append(getLocalizableScriptName()); |
| | | if (allowsTrailingArguments) { |
| | | buffer.append(" "); |
| | | if (trailingArgsDisplayName != null) { |
| | | buffer.append(trailingArgsDisplayName); |
| | | } else { |
| | | buffer.append(INFO_ARGPARSER_USAGE_TRAILINGARGS.get()); |
| | | } |
| | | } |
| | | buffer.append(EOL); |
| | | buffer.append(EOL); |
| | | if (toolDescription != null && toolDescription.length() > 0) { |
| | | buffer.append(wrapText(toolDescription.toString(), MAX_LINE_WIDTH - 1)); |
| | | buffer.append(EOL); |
| | | buffer.append(EOL); |
| | | } |
| | | buffer.append(INFO_SUBCMDPARSER_WHERE_OPTIONS_INCLUDE.get()); |
| | | buffer.append(EOL); |
| | | buffer.append(EOL); |
| | | |
| | | Argument helpArgument = null; |
| | | |
| | | final boolean printHeaders = printUsageGroupHeaders(); |
| | | for (final ArgumentGroup argGroup : argumentGroups) { |
| | | if (argGroup.containsArguments() && printHeaders) { |
| | | // Print the groups description if any |
| | | final LocalizableMessage groupDesc = argGroup.getDescription(); |
| | | if (groupDesc != null && !LocalizableMessage.EMPTY.equals(groupDesc)) { |
| | | buffer.append(EOL); |
| | | buffer.append(wrapText(groupDesc.toString(), MAX_LINE_WIDTH - 1)); |
| | | buffer.append(EOL); |
| | | buffer.append(EOL); |
| | | } |
| | | } |
| | | |
| | | final SortedSet<Argument> args = sortArguments(argGroup.getArguments()); |
| | | for (final Argument a : args) { |
| | | if (a.isHidden()) { |
| | | continue; |
| | | } |
| | | |
| | | // Help argument should be printed at the end |
| | | if (isUsageArgument(a)) { |
| | | helpArgument = a; |
| | | continue; |
| | | } |
| | | printArgumentUsage(a, buffer); |
| | | } |
| | | } |
| | | if (helpArgument != null) { |
| | | printArgumentUsage(helpArgument, buffer); |
| | | } else { |
| | | buffer.append(EOL); |
| | | buffer.append("-?"); |
| | | buffer.append(EOL); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Sorts arguments by identifier, lowercase options first then uppercase. |
| | | * |
| | | * @param arguments The arguments to sort. |
| | | * @return The set of arguments in sorted order. |
| | | */ |
| | | SortedSet<Argument> sortArguments(final List<Argument> arguments) { |
| | | final SortedSet<Argument> result = new TreeSet<>(new Comparator<Argument>() { |
| | | |
| | | @Override |
| | | public int compare(final Argument o1, final Argument o2) { |
| | | final String s1 = getIdentifier(o1); |
| | | final String s2 = getIdentifier(o2); |
| | | final int res = s1.compareToIgnoreCase(s2); |
| | | if (res != 0) { |
| | | return res; |
| | | } |
| | | // Lowercase options first then uppercase. |
| | | return -s1.compareTo(s2); |
| | | } |
| | | |
| | | private String getIdentifier(final Argument o1) { |
| | | if (o1.getShortIdentifier() != null) { |
| | | return o1.getShortIdentifier().toString(); |
| | | } |
| | | return o1.getLongIdentifier(); |
| | | } |
| | | |
| | | }); |
| | | result.addAll(arguments); |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * Returns the script name or a Java equivalent command-line string. |
| | | * |
| | | * @return the script name or a Java equivalent command-line string |
| | | */ |
| | | String getScriptNameOrJava() { |
| | | final String scriptName = getScriptName(); |
| | | if (scriptName != null && scriptName.length() != 0) { |
| | | return scriptName; |
| | | } |
| | | return "java " + getMainClassName(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the script name as a {@link LocalizableMessage}. |
| | | * |
| | | * @return the script name as a {@link LocalizableMessage} |
| | | */ |
| | | LocalizableMessage getLocalizableScriptName() { |
| | | final String scriptName = getScriptName(); |
| | | if (scriptName == null || scriptName.length() == 0) { |
| | | return INFO_ARGPARSER_USAGE_JAVA_CLASSNAME.get(mainClassName); |
| | | } |
| | | return INFO_ARGPARSER_USAGE_JAVA_SCRIPTNAME.get(scriptName); |
| | | } |
| | | |
| | | /** |
| | | * Returns the script name if set. |
| | | * |
| | | * @return the script name, or {@code null} if not set |
| | | */ |
| | | String getScriptName() { |
| | | final String scriptName = System.getProperty(PROPERTY_SCRIPT_NAME); |
| | | if (scriptName != null && scriptName.length() != 0) { |
| | | return scriptName; |
| | | } |
| | | final String legacyScriptName = System.getProperty(PROPERTY_SCRIPT_NAME_LEGACY); |
| | | if (legacyScriptName != null && legacyScriptName.length() != 0) { |
| | | return legacyScriptName; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * Returns the usage argument. |
| | | * |
| | | * @return the usageArgument |
| | | */ |
| | | Argument getUsageArgument() { |
| | | return usageArgument; |
| | | } |
| | | |
| | | /** |
| | | * Returns whether the provided argument is the usage argument. |
| | | * |
| | | * @param a the argument to test |
| | | * @return true if the provided argument is the usage argument, false otherwise |
| | | */ |
| | | boolean isUsageArgument(final Argument a) { |
| | | return usageArgument != null && usageArgument.getLongIdentifier().equals(a.getLongIdentifier()); |
| | | } |
| | | |
| | | /** Prints the version. */ |
| | | void printVersion() { |
| | | versionPresent = true; |
| | | usageOrVersionDisplayed = true; |
| | | versionHandler.printVersion(); |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public boolean isUsageArgumentPresent() { |
| | | return usageArgument != null && usageArgument.isPresent(); |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public boolean isVersionArgumentPresent() { |
| | | return versionPresent; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether subcommand names and long argument strings should be treated in a case-sensitive manner. |
| | | * |
| | | * @return <CODE>true</CODE> if subcommand names and long argument strings should be treated in a case-sensitive |
| | | * manner, or <CODE>false</CODE> if they should not. |
| | | */ |
| | | boolean longArgumentsCaseSensitive() { |
| | | return longArgumentsCaseSensitive; |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public 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. |
| | | */ |
| | | public void parseArguments(final String[] rawArguments, Properties argumentProperties) throws ArgumentException { |
| | | 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 equalsPos < 0, this is fine. The value is not part of the argument name token. |
| | | if (equalPos == 0) { |
| | | // The argument starts with "--=", which is not acceptable. |
| | | throw new ArgumentException(ERR_ARGPARSER_LONG_ARG_WITHOUT_NAME.get(arg)); |
| | | } else if (equalPos > 0) { |
| | | // 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; |
| | | argName = formatLongIdentifier(argName); |
| | | |
| | | // Get the argument with the specified name. |
| | | final Argument a = longIDMap.get(argName); |
| | | if (a == null) { |
| | | if (OPTION_LONG_HELP.equals(argName)) { |
| | | // "--help" will always be interpreted as requesting usage information. |
| | | writeToUsageOutputStream(getUsage()); |
| | | return; |
| | | } else if (OPTION_LONG_PRODUCT_VERSION.equals(argName)) { |
| | | // "--version" will always be interpreted as requesting version information. |
| | | printVersion(); |
| | | return; |
| | | } else { |
| | | // There is no such argument registered. |
| | | throw new ArgumentException( |
| | | ERR_ARGPARSER_NO_ARGUMENT_WITH_LONG_ID.get(origArgName)); |
| | | } |
| | | } else { |
| | | a.setPresent(true); |
| | | |
| | | // If this is the usage argument, then immediately stop and |
| | | // print usage information. |
| | | if (isUsageArgument(a)) { |
| | | writeToUsageOutputStream(getUsage()); |
| | | 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) { |
| | | throw new ArgumentException( |
| | | ERR_ARGPARSER_NO_VALUE_FOR_ARGUMENT_WITH_LONG_ID.get(origArgName)); |
| | | } |
| | | |
| | | argValue = rawArguments[++i]; |
| | | } |
| | | |
| | | final LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder(); |
| | | if (!a.valueIsAcceptable(argValue, invalidReason)) { |
| | | throw new ArgumentException( |
| | | ERR_ARGPARSER_VALUE_UNACCEPTABLE_FOR_LONG_ID.get(argValue, |
| | | origArgName, invalidReason)); |
| | | } |
| | | |
| | | // If the argument already has a value, then make sure it is |
| | | // acceptable to have more than one. |
| | | if (a.hasValue() && !a.isMultiValued()) { |
| | | throw new ArgumentException(ERR_ARGPARSER_NOT_MULTIVALUED_FOR_LONG_ID.get(origArgName)); |
| | | } |
| | | |
| | | a.addValue(argValue); |
| | | } else if (argValue != null) { |
| | | throw new ArgumentException( |
| | | ERR_ARGPARSER_ARG_FOR_LONG_ID_DOESNT_TAKE_VALUE.get(origArgName)); |
| | | } |
| | | } 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("-")) { |
| | | throw new ArgumentException(ERR_ARGPARSER_INVALID_DASH_AS_ARGUMENT.get()); |
| | | } |
| | | |
| | | 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 == '?') { |
| | | writeToUsageOutputStream(getUsage()); |
| | | return; |
| | | } else if (versionHandler != null && argCharacter == OPTION_SHORT_PRODUCT_VERSION |
| | | && !shortIDMap.containsKey(OPTION_SHORT_PRODUCT_VERSION)) { |
| | | printVersion(); |
| | | return; |
| | | } else { |
| | | // There is no such argument registered. |
| | | throw new ArgumentException(ERR_ARGPARSER_NO_ARGUMENT_WITH_SHORT_ID.get(argCharacter)); |
| | | } |
| | | } else { |
| | | a.setPresent(true); |
| | | |
| | | // If this is the usage argument, then immediately stop and |
| | | // print usage information. |
| | | if (isUsageArgument(a)) { |
| | | writeToUsageOutputStream(getUsage()); |
| | | 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) { |
| | | throw new ArgumentException( |
| | | ERR_ARGPARSER_NO_VALUE_FOR_ARGUMENT_WITH_SHORT_ID.get(argCharacter)); |
| | | } |
| | | |
| | | argValue = rawArguments[++i]; |
| | | } |
| | | |
| | | final LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder(); |
| | | if (!a.valueIsAcceptable(argValue, invalidReason)) { |
| | | throw new ArgumentException(ERR_ARGPARSER_VALUE_UNACCEPTABLE_FOR_SHORT_ID.get( |
| | | argValue, argCharacter, invalidReason)); |
| | | } |
| | | |
| | | // If the argument already has a value, then make sure it is |
| | | // acceptable to have more than one. |
| | | if (a.hasValue() && !a.isMultiValued()) { |
| | | throw new ArgumentException(ERR_ARGPARSER_NOT_MULTIVALUED_FOR_SHORT_ID.get(argCharacter)); |
| | | } |
| | | |
| | | 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. |
| | | throw new ArgumentException( |
| | | ERR_ARGPARSER_NO_ARGUMENT_WITH_SHORT_ID.get(argCharacter)); |
| | | } 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. |
| | | throw new ArgumentException( |
| | | ERR_ARGPARSER_CANT_MIX_ARGS_WITH_VALUES.get(argCharacter, argValue, c)); |
| | | } else { |
| | | b.setPresent(true); |
| | | |
| | | // If this is the usage argument, |
| | | // then immediately stop and print usage information. |
| | | if (isUsageArgument(b)) { |
| | | writeToUsageOutputStream(getUsage()); |
| | | 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. |
| | | throw new ArgumentException(ERR_ARGPARSER_DISALLOWED_TRAILING_ARGUMENT.get(arg)); |
| | | } |
| | | } |
| | | |
| | | // If we allow trailing arguments and there is a minimum number, |
| | | // then make sure at least that many were provided. |
| | | if (allowsTrailingArguments |
| | | && minTrailingArguments > 0 |
| | | && trailingArguments.size() < minTrailingArguments) { |
| | | throw new ArgumentException(ERR_ARGPARSER_TOO_FEW_TRAILING_ARGUMENTS.get(minTrailingArguments)); |
| | | } |
| | | |
| | | // 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. |
| | | normalizeArguments(argumentProperties, argumentList); |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public void parseArguments(final String[] rawArguments, final String propertiesFile, |
| | | final boolean requirePropertiesFile) throws ArgumentException { |
| | | Properties argumentProperties = null; |
| | | |
| | | try (final FileInputStream fis = new FileInputStream(propertiesFile)) { |
| | | final Properties p = new Properties(); |
| | | p.load(fis); |
| | | argumentProperties = p; |
| | | } catch (final Exception e) { |
| | | if (requirePropertiesFile) { |
| | | final LocalizableMessage message = |
| | | ERR_ARGPARSER_CANNOT_READ_PROPERTIES_FILE.get(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 provided argument which will be used to identify the file |
| | | * properties. |
| | | * |
| | | * @param argument |
| | | * The argument which will be used to identify the file |
| | | * properties. |
| | | */ |
| | | public void setFilePropertiesArgument(final 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. |
| | | */ |
| | | public 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. |
| | | */ |
| | | public 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. |
| | | */ |
| | | public void setUsageArgument(final Argument argument, final OutputStream outputStream) { |
| | | usageArgument = argument; |
| | | usageOutputStream = outputStream; |
| | | } |
| | | |
| | | /** |
| | | * Sets whether the usage or version displayed. |
| | | * |
| | | * @param usageOrVersionDisplayed the usageOrVersionDisplayed to set |
| | | */ |
| | | public void setUsageOrVersionDisplayed(boolean usageOrVersionDisplayed) { |
| | | this.usageOrVersionDisplayed = usageOrVersionDisplayed; |
| | | } |
| | | |
| | | /** |
| | | * Sets the version handler which will be used to display the product version. |
| | | * |
| | | * @param handler |
| | | * The version handler. |
| | | */ |
| | | public void setVersionHandler(final VersionHandler handler) { |
| | | versionHandler = handler; |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public boolean usageOrVersionDisplayed() { |
| | | return 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_OPENDJ_PROPERTIES_FILE_NAME |
| | | + DEFAULT_OPENDJ_PROPERTIES_FILE_EXTENSION); |
| | | if (f.exists() && f.canRead()) { |
| | | return f.getAbsolutePath(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private void initGroups() { |
| | | this.argumentGroups.add(defaultArgGroup); |
| | | this.argumentGroups.add(ldapArgGroup); |
| | | this.argumentGroups.add(generalArgGroup); |
| | | this.argumentGroups.add(ioArgGroup); |
| | | |
| | | try { |
| | | versionArgument = getVersionArgument(true); |
| | | // JNR: why not call addGeneralArgument(versionArgument) here? |
| | | this.generalArgGroup.addArgument(versionArgument); |
| | | } catch (final ArgumentException e) { |
| | | // ignore |
| | | } |
| | | } |
| | | |
| | | private boolean isGeneralArgument(final Argument arg) { |
| | | if (arg != null) { |
| | | final String longId = arg.getLongIdentifier(); |
| | | return OPTION_LONG_HELP.equals(longId) || OPTION_LONG_PRODUCT_VERSION.equals(longId); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private boolean isInputOutputArgument(final Argument arg) { |
| | | if (arg != null) { |
| | | final String longId = arg.getLongIdentifier(); |
| | | return 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 false; |
| | | } |
| | | |
| | | private boolean isLdapConnectionArgument(final Argument arg) { |
| | | if (arg != null) { |
| | | final String longId = arg.getLongIdentifier(); |
| | | return 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 false; |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | private void printArgumentUsage(final Argument a, final StringBuilder buffer) { |
| | | printLineForShortLongArgument(a, buffer); |
| | | |
| | | // Write one or more lines with the description of the argument. |
| | | // We will 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. |
| | | final int indentLength = INDENT.length(); |
| | | buffer.append(wrapText(a.getDescription(), MAX_LINE_WIDTH, indentLength)); |
| | | buffer.append(EOL); |
| | | |
| | | if (a.needsValue() && a.getDefaultValue() != null && a.getDefaultValue().length() > 0) { |
| | | buffer.append(INDENT); |
| | | buffer.append(INFO_ARGPARSER_USAGE_DEFAULT_VALUE.get(a.getDefaultValue())); |
| | | buffer.append(EOL); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Appends a line with the short and/or long identifiers that may be used for the argument to the provided string |
| | | * builder. |
| | | * |
| | | * @param a the argument for which to print a line |
| | | * @param buffer the string builder where to append the line |
| | | */ |
| | | void printLineForShortLongArgument(final Argument a, final StringBuilder buffer) { |
| | | final Character shortID = a.getShortIdentifier(); |
| | | final String longID = a.getLongIdentifier(); |
| | | if (shortID != null) { |
| | | if (isUsageArgument(a)) { |
| | | buffer.append("-?, "); |
| | | } |
| | | |
| | | buffer.append("-"); |
| | | buffer.append(shortID.charValue()); |
| | | |
| | | if (a.needsValue() && longID == null) { |
| | | buffer.append(" "); |
| | | buffer.append(a.getValuePlaceholder()); |
| | | } |
| | | |
| | | if (longID != null) { |
| | | final StringBuilder newBuffer = new StringBuilder(); |
| | | newBuffer.append(", --"); |
| | | newBuffer.append(longID); |
| | | |
| | | if (a.needsValue()) { |
| | | newBuffer.append(" "); |
| | | newBuffer.append(a.getValuePlaceholder()); |
| | | } |
| | | |
| | | final int currentLength = buffer.length(); |
| | | final int lineLength = (buffer.length() - currentLength) + newBuffer.length(); |
| | | if (lineLength > MAX_LINE_WIDTH) { |
| | | buffer.append(EOL); |
| | | } |
| | | buffer.append(newBuffer); |
| | | } |
| | | |
| | | buffer.append(EOL); |
| | | } else if (longID != null) { |
| | | if (isUsageArgument(a)) { |
| | | buffer.append("-?, "); |
| | | } |
| | | buffer.append("--"); |
| | | buffer.append(longID); |
| | | |
| | | if (a.needsValue()) { |
| | | buffer.append(" "); |
| | | buffer.append(a.getValuePlaceholder()); |
| | | } |
| | | |
| | | buffer.append(EOL); |
| | | } |
| | | } |
| | | |
| | | void normalizeArguments(final Properties argumentProperties, final List<Argument> arguments) |
| | | throws ArgumentException { |
| | | for (final Argument a : arguments) { |
| | | // See if there is a value in the properties that can be used |
| | | if (!a.isPresent() && argumentProperties != null) { |
| | | final String value = argumentProperties.getProperty(a.getLongIdentifier().toLowerCase()); |
| | | final LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder(); |
| | | if (value != null) { |
| | | boolean addValue = (a instanceof BooleanArgument) || a.valueIsAcceptable(value, invalidReason); |
| | | if (addValue) { |
| | | a.addValue(value); |
| | | if (a.needsValue()) { |
| | | a.setPresent(true); |
| | | } |
| | | a.valueSetByProperty(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | 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()) { |
| | | throw new ArgumentException(ERR_ARGPARSER_NO_VALUE_FOR_REQUIRED_ARG.get(a.getLongIdentifier())); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Displays the provided message on the provided stream followed by a help usage reference. |
| | | * |
| | | * @param printStream |
| | | * The stream to print error message and help reference message. |
| | | * @param message |
| | | * The error message to print. |
| | | */ |
| | | public void displayMessageAndUsageReference(final PrintStream printStream, final LocalizableMessage message) { |
| | | printWrappedText(printStream, message); |
| | | printStream.println(); |
| | | printWrappedText(printStream, getHelpUsageReference()); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a string describing how the user can get more help. |
| | | * |
| | | * @return A string describing how the user can get more help. |
| | | */ |
| | | public LocalizableMessage getHelpUsageReference() { |
| | | setUsageOrVersionDisplayed(true); |
| | | |
| | | LocalizableMessageBuilder buffer = new LocalizableMessageBuilder(); |
| | | buffer.append(INFO_GLOBAL_HELP_REFERENCE.get(getScriptNameOrJava())); |
| | | buffer.append(EOL); |
| | | return buffer.toMessage(); |
| | | } |
| | | |
| | | /** |
| | | * Get the password which has to be used for the command without prompting the user. If no password was specified, |
| | | * return null. |
| | | * |
| | | * @param clearArg |
| | | * The password StringArgument argument. |
| | | * @param fileArg |
| | | * The password FileBased argument. |
| | | * @return The password stored into the specified file on by the command line argument, or null it if not specified. |
| | | */ |
| | | public static String getBindPassword(StringArgument clearArg, FileBasedArgument fileArg) { |
| | | if (clearArg.isPresent()) { |
| | | return clearArg.getValue(); |
| | | } else if (fileArg.isPresent()) { |
| | | return fileArg.getValue(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * Replace the provided {@link Argument} from this parser by the provided {@link Argument}. |
| | | * If the {@link Argument} is not present in this parser, do nothing. |
| | | * |
| | | * @param argument |
| | | * The {@link Argument} to replace. |
| | | */ |
| | | public void replaceArgument(final Argument argument) { |
| | | replaceArgumentInCollections(longIDMap, shortIDMap, argumentList, argument); |
| | | } |
| | | |
| | | void replaceArgumentInCollections(final Map<String, Argument> longIDToArg, |
| | | final Map<Character, Argument> shortIDToArg, final List<Argument> argumentList, final Argument argument) { |
| | | final String longID = formatLongIdentifier(argument.getLongIdentifier()); |
| | | if (!longIDToArg.containsKey(longID)) { |
| | | return; |
| | | } |
| | | longIDToArg.put(longID, argument); |
| | | shortIDToArg.put(argument.getShortIdentifier(), argument); |
| | | argumentList.remove(argument); |
| | | argumentList.add(argument); |
| | | for (final ArgumentGroup group : argumentGroups) { |
| | | if (group.getArguments().contains(argument)) { |
| | | group.removeArgument(argument); |
| | | group.addArgument(argument); |
| | | } |
| | | } |
| | | } |
| | | |
| | | String formatLongIdentifier(final String longIdentifier) { |
| | | return longArgumentsCaseSensitive ? longIdentifier : toLowerCase(longIdentifier); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.ERR_BOOLEANARG_NO_VALUE_ALLOWED; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | |
| | | /** |
| | | * This class defines an argument type that will be used to represent Boolean |
| | | * values. These arguments will never take values from the command line but and |
| | | * will never be required. If the argument is provided, then it will be |
| | | * considered true, and if not then it will be considered false. As such, the |
| | | * default value will always be "false". |
| | | */ |
| | | public final class BooleanArgument extends Argument { |
| | | |
| | | /** |
| | | * Returns a builder which can be used for incrementally constructing a new |
| | | * {@link BooleanArgument}. |
| | | * |
| | | * @param longIdentifier |
| | | * The long identifier that will be used to refer to this argument. |
| | | * @return A builder to continue building the {@link BooleanArgument}. |
| | | */ |
| | | public static Builder builder(final String longIdentifier) { |
| | | return new Builder(longIdentifier); |
| | | } |
| | | |
| | | /** A fluent API for incrementally constructing {@link BooleanArgument}. */ |
| | | public static final class Builder extends ArgumentBuilder<Builder, Boolean, BooleanArgument> { |
| | | private Builder(final String longIdentifier) { |
| | | super(longIdentifier); |
| | | this.needsValue = false; |
| | | this.defaultValue = false; |
| | | } |
| | | |
| | | @Override |
| | | Builder getThis() { |
| | | return this; |
| | | } |
| | | |
| | | @Override |
| | | public BooleanArgument buildArgument() throws ArgumentException { |
| | | return new BooleanArgument(this); |
| | | } |
| | | } |
| | | |
| | | private BooleanArgument(final Builder builder) throws ArgumentException { |
| | | super(builder); |
| | | } |
| | | |
| | | @Override |
| | | public final void addValue(final String valueString) { |
| | | if (valueString != null) { |
| | | clearValues(); |
| | | super.addValue(valueString); |
| | | super.setPresent(Boolean.valueOf(valueString)); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public final void setPresent(final boolean isPresent) { |
| | | addValue(String.valueOf(isPresent)); |
| | | } |
| | | |
| | | @Override |
| | | public boolean valueIsAcceptable(final String valueString, final LocalizableMessageBuilder invalidReason) { |
| | | // This argument type should never have a value, so any value |
| | | // provided will be unacceptable. |
| | | invalidReason.append(ERR_BOOLEANARG_NO_VALUE_ALLOWED.get(longIdentifier)); |
| | | |
| | | return false; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2012-2015 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | /** |
| | | * This class defines a number of constants used by tools. |
| | | */ |
| | | public final class CliConstants { |
| | | |
| | | /** The minimum java specification supported string version. */ |
| | | public static final float MINIMUM_JAVA_VERSION = 1.7F; |
| | | |
| | | /** Default value for LDAP connection timeout. */ |
| | | public static final int DEFAULT_LDAP_CONNECT_TIMEOUT = 30000; |
| | | |
| | | /** Default value for incrementing port number. */ |
| | | public static final int PORT_INCREMENT = 1000; |
| | | |
| | | /** Default port number for the LDAP port. */ |
| | | public static final int DEFAULT_LDAP_PORT = 389; |
| | | |
| | | /** Default port number for the LDAPS port. */ |
| | | public static final int DEFAULT_LDAPS_PORT = 1636; |
| | | |
| | | /** Default port number for the administrator port. */ |
| | | public static final int DEFAULT_ADMIN_PORT = 1444; |
| | | |
| | | /** Default port number for the SSL Connection. */ |
| | | public static final int DEFAULT_SSL_PORT = 636; |
| | | |
| | | /** Default port number for the JMX Connection handler. */ |
| | | public static final int DEFAULT_JMX_PORT = 1689; |
| | | |
| | | /** Default port number for the HTTP Connection handler. */ |
| | | public static final int DEFAULT_HTTP_PORT = 8080; |
| | | |
| | | /** Default port number for the SNMP Connection handler. */ |
| | | public static final int DEFAULT_SNMP_PORT = 161; |
| | | |
| | | /** Default name of root user DN. */ |
| | | public static final String DEFAULT_ROOT_USER_DN = "cn=Directory Manager"; |
| | | |
| | | /** Default Administration Connector port. */ |
| | | public static final int DEFAULT_ADMINISTRATION_CONNECTOR_PORT = 4444; |
| | | |
| | | /** Default Administration UID. */ |
| | | public static final String GLOBAL_ADMIN_UID = "admin"; |
| | | |
| | | |
| | | /** Prevent instantiation. */ |
| | | private CliConstants() { |
| | | |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.ERR_CONSOLE_INPUT_ERROR; |
| | | import org.forgerock.i18n.LocalizableException; |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * This class defines an exception that may be thrown if a local problem occurs in a Directory Server client. |
| | | */ |
| | | public class ClientException 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 = 1384120263337669664L; |
| | | |
| | | /** The return code. */ |
| | | private ReturnCode returnCode; |
| | | |
| | | /** The message linked to that exception. */ |
| | | private final LocalizableMessage message; |
| | | |
| | | /** |
| | | * Adapts any exception that may have occurred whilst reading input from the |
| | | * console. |
| | | * |
| | | * @param cause |
| | | * The exception that occurred whilst reading input from the |
| | | * console. |
| | | * @return Returns a new CLI exception describing a problem that occurred |
| | | * whilst reading input from the console. |
| | | */ |
| | | public static ClientException adaptInputException(final Throwable cause) { |
| | | return new ClientException(ReturnCode.ERROR_USER_DATA, ERR_CONSOLE_INPUT_ERROR.get(cause.getMessage()), cause); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new client exception with the provided message. |
| | | * |
| | | * @param exitCode |
| | | * The exit code that may be used if the client considers this to be a fatal problem. |
| | | * @param message |
| | | * The message that explains the problem that occurred. |
| | | */ |
| | | public ClientException(ReturnCode exitCode, LocalizableMessage message) { |
| | | super(message.toString()); |
| | | this.returnCode = exitCode; |
| | | this.message = message; |
| | | } |
| | | |
| | | /** |
| | | * Creates a new client exception with the provided message and root cause. |
| | | * |
| | | * @param exitCode |
| | | * The exit code that may be used if the client considers this to be a fatal problem. |
| | | * @param message |
| | | * The message that explains the problem that occurred. |
| | | * @param cause |
| | | * The exception that was caught to trigger this exception. |
| | | */ |
| | | public ClientException(ReturnCode exitCode, LocalizableMessage message, Throwable cause) { |
| | | super(message.toString(), cause); |
| | | this.returnCode = exitCode; |
| | | this.message = message; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the exit code that the client may use if it considers this to be a fatal problem. |
| | | * |
| | | * @return The exit code that the client may use if it considers this to be a fatal problem. |
| | | */ |
| | | public int getReturnCode() { |
| | | return returnCode.get(); |
| | | } |
| | | |
| | | @Override |
| | | public LocalizableMessage getMessageObject() { |
| | | return message; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008-2009 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.Utils.OBFUSCATED_VALUE; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.ArrayList; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | import java.util.TreeSet; |
| | | |
| | | import com.forgerock.opendj.util.OperatingSystem; |
| | | |
| | | /** |
| | | * Class used to be able to generate the non interactive mode. |
| | | */ |
| | | public class CommandBuilder { |
| | | private String commandName; |
| | | private String subcommandName; |
| | | private final ArrayList<Argument> args = new ArrayList<>(); |
| | | private final HashSet<Argument> obfuscatedArgs = new HashSet<>(); |
| | | |
| | | /** |
| | | * The separator used to link the lines of the resulting command-lines. |
| | | */ |
| | | public static final String LINE_SEPARATOR; |
| | | static { |
| | | if (OperatingSystem.isWindows()) { |
| | | LINE_SEPARATOR = " "; |
| | | } else { |
| | | LINE_SEPARATOR = " \\\n "; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * The separator used to link the lines of the resulting command-lines in HTML format. |
| | | */ |
| | | public static final String HTML_LINE_SEPARATOR; |
| | | static { |
| | | if (OperatingSystem.isWindows()) { |
| | | HTML_LINE_SEPARATOR = " "; |
| | | } else { |
| | | HTML_LINE_SEPARATOR = " \\<br> "; |
| | | } |
| | | } |
| | | |
| | | /** Creates a {@link CommandBuilder} with {@code null} command and subcommand names. */ |
| | | public CommandBuilder() { |
| | | this(null, null); |
| | | } |
| | | |
| | | /** |
| | | * The constructor for the CommandBuilder. |
| | | * |
| | | * @param commandName |
| | | * The command name. |
| | | * @param subcommandName |
| | | * The sub command name. |
| | | */ |
| | | public CommandBuilder(String commandName, String subcommandName) { |
| | | this.commandName = commandName; |
| | | this.subcommandName = subcommandName; |
| | | } |
| | | |
| | | /** |
| | | * Adds an argument to the list of the command builder. |
| | | * |
| | | * @param argument |
| | | * The argument to be added. |
| | | */ |
| | | public void addArgument(final Argument argument) { |
| | | // We use an ArrayList to be able to provide the possibility of updating |
| | | // the position of the attributes. |
| | | if (!args.contains(argument)) { |
| | | args.add(argument); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Adds an argument whose values must be obfuscated (passwords for instance). |
| | | * |
| | | * @param argument |
| | | * The argument to be added. |
| | | */ |
| | | public void addObfuscatedArgument(final Argument argument) { |
| | | addArgument(argument); |
| | | obfuscatedArgs.add(argument); |
| | | } |
| | | |
| | | /** |
| | | * Removes the provided argument from this CommandBuilder. |
| | | * |
| | | * @param argument |
| | | * The argument to be removed. |
| | | * @return <CODE>true</CODE> if the attribute was present and removed and <CODE>false</CODE> otherwise. |
| | | */ |
| | | public boolean removeArgument(final Argument argument) { |
| | | obfuscatedArgs.remove(argument); |
| | | return args.remove(argument); |
| | | } |
| | | |
| | | /** |
| | | * Removes the provided arguments from this CommandBuilder. |
| | | * Arguments which are not in this {@link CommandBuilder} will be ignored. |
| | | * |
| | | * @param arguments |
| | | * Arguments to be removed. |
| | | */ |
| | | public void removeArguments(final Argument... arguments) { |
| | | for (final Argument argument : arguments) { |
| | | removeArgument(argument); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Appends the arguments of another command builder to this command builder. |
| | | * |
| | | * @param builder |
| | | * The CommandBuilder to append. |
| | | */ |
| | | public void append(final CommandBuilder builder) { |
| | | for (final Argument arg : builder.args) { |
| | | if (builder.isObfuscated(arg)) { |
| | | addObfuscatedArgument(arg); |
| | | } else { |
| | | addArgument(arg); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns the String representation of this command builder (i.e. what we want to show to the user). |
| | | * |
| | | * @return The String representation of this command builder (i.e. what we want to show to the user). |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | return toString(false, LINE_SEPARATOR); |
| | | } |
| | | |
| | | /** |
| | | * Returns the String representation of this command builder (i.e. what we want to show to the user). |
| | | * |
| | | * @param lineSeparator |
| | | * The String to be used to separate lines of the command-builder. |
| | | * @return The String representation of this command builder (i.e. what we want to show to the user). |
| | | */ |
| | | public String toString(final String lineSeparator) { |
| | | return toString(false, lineSeparator); |
| | | } |
| | | |
| | | /** |
| | | * Returns the String representation of this command builder (i.e. what we want to show to the user). |
| | | * |
| | | * @param showObfuscated |
| | | * Displays in clear the obfuscated values. |
| | | * @param lineSeparator |
| | | * The String to be used to separate lines of the command-builder. |
| | | * @return The String representation of this command builder (i.e. what we want to show to the user). |
| | | */ |
| | | private String toString(final boolean showObfuscated, final String lineSeparator) { |
| | | final StringBuilder builder = new StringBuilder(); |
| | | builder.append(commandName); |
| | | if (subcommandName != null) { |
| | | builder.append(" ").append(subcommandName); |
| | | } |
| | | for (final Argument arg : args) { |
| | | // This CLI is always using SSL, and the argument has been removed from |
| | | // the user interface |
| | | if (ArgumentConstants.OPTION_LONG_USE_SSL.equals(arg.getLongIdentifier())) { |
| | | continue; |
| | | } |
| | | String argName; |
| | | if (arg.getLongIdentifier() != null) { |
| | | argName = "--" + arg.getLongIdentifier(); |
| | | } else { |
| | | argName = "-" + arg.getShortIdentifier(); |
| | | } |
| | | |
| | | if (arg instanceof BooleanArgument) { |
| | | builder.append(lineSeparator).append(argName); |
| | | } else if (arg instanceof FileBasedArgument) { |
| | | for (String value : ((FileBasedArgument) arg).getNameToValueMap().keySet()) { |
| | | builder.append(lineSeparator).append(argName).append(" "); |
| | | builder.append(getOutputValue(value, arg, showObfuscated)); |
| | | } |
| | | } else { |
| | | for (String value : arg.getValues()) { |
| | | builder.append(lineSeparator).append(argName).append(" "); |
| | | builder.append(getOutputValue(value, arg, showObfuscated)); |
| | | } |
| | | } |
| | | } |
| | | return builder.toString(); |
| | | } |
| | | |
| | | private String getOutputValue(final String value, final Argument arg, final boolean showObfuscated) { |
| | | if (isObfuscated(arg) && !showObfuscated) { |
| | | return OBFUSCATED_VALUE; |
| | | } |
| | | return escapeValue(value); |
| | | } |
| | | |
| | | /** |
| | | * Clears the arguments. |
| | | */ |
| | | public void clearArguments() { |
| | | args.clear(); |
| | | obfuscatedArgs.clear(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the list of arguments. |
| | | * |
| | | * @return The list of arguments. |
| | | */ |
| | | public List<Argument> getArguments() { |
| | | return args; |
| | | } |
| | | |
| | | /** |
| | | * Tells whether the provided argument's values must be obfuscated or not. |
| | | * |
| | | * @param argument |
| | | * The argument to handle. |
| | | * @return <CODE>true</CODE> if the attribute's values must be obfuscated and <CODE>false</CODE> otherwise. |
| | | */ |
| | | public boolean isObfuscated(final Argument argument) { |
| | | return obfuscatedArgs.contains(argument); |
| | | } |
| | | |
| | | /** Chars that require special treatment when passing them to command-line. */ |
| | | private static final Set<Character> CHARSTOESCAPE = new TreeSet<>(Arrays.asList( |
| | | ' ', '\t', '\n', '|', ';', '<', '>', '(', ')', '$', '`', '\\', '"', '\'')); |
| | | |
| | | /** |
| | | * This method simply takes a value and tries to transform it (with escape or '"') characters so that it can be used |
| | | * in a command line. |
| | | * |
| | | * @param value |
| | | * The String to be treated. |
| | | * @return The transformed value. |
| | | */ |
| | | public static String escapeValue(String value) { |
| | | final StringBuilder b = new StringBuilder(); |
| | | if (OperatingSystem.isUnix()) { |
| | | for (int i = 0; i < value.length(); i++) { |
| | | final char c = value.charAt(i); |
| | | if (CHARSTOESCAPE.contains(c)) { |
| | | b.append('\\'); |
| | | } |
| | | b.append(c); |
| | | } |
| | | } else { |
| | | b.append('"').append(value).append('"'); |
| | | } |
| | | return b.toString(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | import static com.forgerock.opendj.cli.ArgumentConstants.*; |
| | | import static com.forgerock.opendj.cli.CliConstants.DEFAULT_LDAP_CONNECT_TIMEOUT; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.opendj.ldap.SearchScope; |
| | | |
| | | /** |
| | | * This class regroup commons arguments used by the different CLI. |
| | | */ |
| | | public final class CommonArguments { |
| | | |
| | | /** Prevent instantiation. */ |
| | | private CommonArguments() { |
| | | // Nothing to do. |
| | | } |
| | | |
| | | /** |
| | | * Returns the "show usage / help" boolean argument. |
| | | * |
| | | * @return The "show usage" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument showUsageArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_HELP) |
| | | .shortIdentifier(OPTION_SHORT_HELP) |
| | | .description(INFO_DESCRIPTION_SHOWUSAGE.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "verbose" boolean argument. |
| | | * |
| | | * @return The "verbose" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument verboseArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_VERBOSE) |
| | | .shortIdentifier(OPTION_SHORT_VERBOSE) |
| | | .description(INFO_DESCRIPTION_VERBOSE.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "port" integer argument. <br> |
| | | * <i> N.B : the 'p' short option is also used by skipdecode(DBTest), |
| | | * propertiesFile(JavaPropertiesToolArguments).</i> |
| | | * |
| | | * @param defaultPort |
| | | * The default port number. |
| | | * @param description |
| | | * Port number's description. |
| | | * @return The "port" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static IntegerArgument portArgument(final int defaultPort, final LocalizableMessage description) |
| | | throws ArgumentException { |
| | | return IntegerArgument.builder(OPTION_LONG_PORT) |
| | | .shortIdentifier(OPTION_SHORT_PORT) |
| | | .description(description != null ? description : INFO_DESCRIPTION_ADMIN_PORT.get()) |
| | | .range(1, 65535) |
| | | .defaultValue(defaultPort) |
| | | .valuePlaceholder(INFO_PORT_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "propertiesFilePath" string argument. |
| | | * |
| | | * @return The "propertiesFilePath" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument propertiesFileArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_PROP_FILE_PATH) |
| | | .description(INFO_DESCRIPTION_PROP_FILE_PATH.get()) |
| | | .valuePlaceholder(INFO_PROP_FILE_PATH_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "proxyauthzid" string argument. |
| | | * |
| | | * @return The "proxyauthzid" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument proxyAuthIdArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_PROXYAUTHID) |
| | | .shortIdentifier(OPTION_SHORT_PROXYAUTHID) |
| | | .description(INFO_DESCRIPTION_PROXYAUTHZID.get()) |
| | | .valuePlaceholder(INFO_PROXYAUTHID_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "No properties file" boolean argument. |
| | | * |
| | | * @return The "noPropertiesFile" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument noPropertiesFileArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_NO_PROP_FILE) |
| | | .description(INFO_DESCRIPTION_NO_PROP_FILE.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "Continue On Error" boolean argument. <br> |
| | | * <i> N.B : the 'c' short option is also used by cleanupservice, compress.</i> |
| | | * |
| | | * @return The "continueOnError" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument continueOnErrorArgument() throws ArgumentException { |
| | | return BooleanArgument.builder("continueOnError") |
| | | .shortIdentifier('c') |
| | | .description(INFO_DESCRIPTION_CONTINUE_ON_ERROR.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "control" string argument. |
| | | * |
| | | * @return The "control" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument controlArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_CONTROL) |
| | | .shortIdentifier(OPTION_SHORT_CONTROL) |
| | | .description(INFO_DESCRIPTION_CONTROLS.get()) |
| | | .docDescriptionSupplement(SUPPLEMENT_DESCRIPTION_CONTROLS.get()) |
| | | .multiValued() |
| | | .valuePlaceholder(INFO_LDAP_CONTROL_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "ldapVersion" integer argument. |
| | | * |
| | | * @return The "ldapVersion" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static IntegerArgument ldapVersionArgument() throws ArgumentException { |
| | | return IntegerArgument.builder(OPTION_LONG_PROTOCOL_VERSION) |
| | | .shortIdentifier(OPTION_SHORT_PROTOCOL_VERSION) |
| | | .description(INFO_DESCRIPTION_VERSION.get()) |
| | | .defaultValue(3) |
| | | .valuePlaceholder(INFO_PROTOCOL_VERSION_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "quiet" boolean argument. |
| | | * |
| | | * @return The "quiet" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument quietArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_QUIET) |
| | | .shortIdentifier(OPTION_SHORT_QUIET) |
| | | .description(INFO_DESCRIPTION_QUIET.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "no-op" boolean argument. <br> |
| | | * <i> N.B : the 'n' short option is also used by backendid, newGroupName, newPassword, no-prompt.</i> |
| | | * |
| | | * @return The "no-op" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument noOpArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_DRYRUN) |
| | | .shortIdentifier(OPTION_SHORT_DRYRUN) |
| | | .description(INFO_DESCRIPTION_NOOP.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "no-prompt" boolean argument. <br> |
| | | * <i> N.B : the 'n' short option is also used by backendid, newGroupName, newPassword, no-prompt.</i> |
| | | * |
| | | * @return The "no-prompt" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument noPromptArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_NO_PROMPT) |
| | | .shortIdentifier(OPTION_SHORT_NO_PROMPT) |
| | | .description(INFO_DESCRIPTION_NO_PROMPT.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "acceptLicense" boolean argument. |
| | | * |
| | | * @return The "acceptLicense" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument acceptLicenseArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_ACCEPT_LICENSE) |
| | | .description(INFO_OPTION_ACCEPT_LICENSE.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "trustAll" boolean argument. |
| | | * |
| | | * @return The "trustAll" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument trustAllArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_TRUSTALL) |
| | | .shortIdentifier(OPTION_SHORT_TRUSTALL) |
| | | .description(INFO_DESCRIPTION_TRUSTALL.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "trustStorePath" string argument. |
| | | * |
| | | * @return The "trustStorePath" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument trustStorePathArgument() throws ArgumentException { |
| | | return trustStorePathArgument(null); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "trustStorePath" string argument initialized with the provided default value. |
| | | * |
| | | * @param defaultValue |
| | | * The "trustStorePath" argument default value |
| | | * @return The "trustStorePath" string argument initialized with the provided default value. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument trustStorePathArgument(final String defaultValue) throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_TRUSTSTOREPATH) |
| | | .shortIdentifier(OPTION_SHORT_TRUSTSTOREPATH) |
| | | .description(INFO_DESCRIPTION_TRUSTSTOREPATH.get()) |
| | | .defaultValue(defaultValue) |
| | | .valuePlaceholder(INFO_TRUSTSTOREPATH_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "truststorepw" string argument. |
| | | * |
| | | * @return The "truststorepw" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument trustStorePasswordArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_TRUSTSTORE_PWD) |
| | | .shortIdentifier(OPTION_SHORT_TRUSTSTORE_PWD) |
| | | .description(INFO_DESCRIPTION_TRUSTSTOREPASSWORD.get()) |
| | | .valuePlaceholder(INFO_TRUSTSTORE_PWD_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "trustStorePasswordFile" file argument. |
| | | * |
| | | * @return The "trustStorePasswordFile" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static FileBasedArgument trustStorePasswordFileArgument() throws ArgumentException { |
| | | return FileBasedArgument.builder(OPTION_LONG_TRUSTSTORE_PWD_FILE) |
| | | .shortIdentifier(OPTION_SHORT_TRUSTSTORE_PWD_FILE) |
| | | .description(INFO_DESCRIPTION_TRUSTSTOREPASSWORD_FILE.get()) |
| | | .valuePlaceholder(INFO_TRUSTSTORE_PWD_FILE_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns a "connectTimeout" hidden integer argument. |
| | | * |
| | | * @return A "connectTimeout" hidden integer argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static IntegerArgument connectTimeOutHiddenArgument() throws ArgumentException { |
| | | return connectTimeOutArgument(true); |
| | | } |
| | | |
| | | /** |
| | | * Returns a "connectTimeout" integer argument. |
| | | * |
| | | * @return A "connectTimeout" integer argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static IntegerArgument connectTimeOutArgument() throws ArgumentException { |
| | | return connectTimeOutArgument(false); |
| | | } |
| | | |
| | | private static IntegerArgument connectTimeOutArgument(final boolean hidden) throws ArgumentException { |
| | | final IntegerArgument.Builder builder = IntegerArgument.builder(OPTION_LONG_CONNECT_TIMEOUT) |
| | | .description(INFO_DESCRIPTION_CONNECTION_TIMEOUT.get()) |
| | | .lowerBound(0) |
| | | .defaultValue(DEFAULT_LDAP_CONNECT_TIMEOUT) |
| | | .valuePlaceholder(INFO_TIMEOUT_PLACEHOLDER.get()); |
| | | if (hidden) { |
| | | builder.hidden(); |
| | | } |
| | | return builder.buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "CLI" boolean argument. <br> |
| | | * <i> N.B : the 'i' short option is also used by encoding.</i> |
| | | * |
| | | * @return The "CLI" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument cliArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_CLI) |
| | | .shortIdentifier(OPTION_SHORT_CLI) |
| | | .description(INFO_ARGUMENT_DESCRIPTION_CLI.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "configfile" string argument. <br> |
| | | * <i> N.B : the 'f' short option is also used by filename</i> |
| | | * |
| | | * @return The "configfile" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument configFileArgument() throws ArgumentException { |
| | | return StringArgument.builder("configFile") |
| | | .shortIdentifier('f') |
| | | .description(INFO_DESCRIPTION_CONFIG_FILE.get()) |
| | | .hidden() |
| | | .required() |
| | | .valuePlaceholder(INFO_CONFIGFILE_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "configclass" string argument. |
| | | * |
| | | * @param configFileHandlerName |
| | | * The config file handler name. |
| | | * @return The "configclass" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument configClassArgument(final String configFileHandlerName) throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_CONFIG_CLASS) |
| | | .shortIdentifier(OPTION_SHORT_CONFIG_CLASS) |
| | | .description(INFO_DESCRIPTION_CONFIG_CLASS.get()) |
| | | .hidden() |
| | | .required() |
| | | .defaultValue(configFileHandlerName) |
| | | .valuePlaceholder(INFO_CONFIGCLASS_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "baseDN" string argument. |
| | | * |
| | | * @return The "baseDN" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument baseDNArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_BASEDN) |
| | | .shortIdentifier(OPTION_SHORT_BASEDN) |
| | | .description(INFO_ARGUMENT_DESCRIPTION_BASEDN.get()) |
| | | .multiValued() |
| | | .valuePlaceholder(INFO_BASEDN_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "bindDN" string argument. <br/> |
| | | * <i> N.B : the 'D' short option is also used by rootUserDN.</i> |
| | | * |
| | | * @param defaultBindDN |
| | | * The default bind DN. |
| | | * @return The "bindDN" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument bindDNArgument(final String defaultBindDN) throws ArgumentException { |
| | | return bindDNArgument(defaultBindDN, INFO_DESCRIPTION_BINDDN.get()); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the "bindDN" string argument. <br/> |
| | | * <i> N.B : the 'D' short option is also used by rootUserDN.</i> |
| | | * |
| | | * @param defaultBindDN |
| | | * The default bind DN. |
| | | * @param description |
| | | * The localized description to print in help messages. |
| | | * @return The "bindDN" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument bindDNArgument(final String defaultBindDN, final LocalizableMessage description) |
| | | throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_BINDDN) |
| | | .shortIdentifier(OPTION_SHORT_BINDDN) |
| | | .description(description) |
| | | .defaultValue(defaultBindDN) |
| | | .valuePlaceholder(INFO_BINDDN_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "bindPassword" string argument. |
| | | * |
| | | * @return The "bindPassword" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument bindPasswordArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_BINDPWD) |
| | | .shortIdentifier(OPTION_SHORT_BINDPWD) |
| | | .description(INFO_DESCRIPTION_BINDPASSWORD.get()) |
| | | .valuePlaceholder(INFO_BINDPWD_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "bindPasswordFile" file argument. |
| | | * |
| | | * @return The "bindPasswordFile" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static FileBasedArgument bindPasswordFileArgument() throws ArgumentException { |
| | | return FileBasedArgument.builder(OPTION_LONG_BINDPWD_FILE) |
| | | .shortIdentifier(OPTION_SHORT_BINDPWD_FILE) |
| | | .description(INFO_DESCRIPTION_BINDPASSWORDFILE.get()) |
| | | .valuePlaceholder(INFO_BINDPWD_FILE_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "addbaseentry" boolean argument. |
| | | * <br><i> N.B : the 'a' short option is also used by backupall, defaultAdd.</i> |
| | | * |
| | | * @return The "addbaseentry" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument addBaseEntryArgument() throws ArgumentException { |
| | | return BooleanArgument.builder("addBaseEntry") |
| | | .shortIdentifier('a') |
| | | .description(INFO_ARGUMENT_DESCRIPTION_ADDBASE.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "rejectfile" string argument. <br> |
| | | * <i> N.B : the 'R' short option is also used by restart, serverRoot.</i> |
| | | * |
| | | * @return The "rejectfile" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument rejectedImportLdifArgument() throws ArgumentException { |
| | | return StringArgument.builder("rejectFile") |
| | | .shortIdentifier('R') |
| | | .description(INFO_GENERAL_DESCRIPTION_REJECTED_FILE.get()) |
| | | .valuePlaceholder(INFO_REJECT_FILE_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "remote" boolean argument. <br> |
| | | * <i> N.B : the 'r' short option is also used by useSASLExternal, stopreason.</i> |
| | | * |
| | | * @return The "remote" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument remoteArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_REMOTE) |
| | | .shortIdentifier(OPTION_SHORT_REMOTE) |
| | | .description(INFO_DESCRIPTION_REMOTE.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "reportauthzid" boolean argument. |
| | | * |
| | | * @return The "reportauthzid" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument reportAuthzIdArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_REPORT_AUTHZ_ID) |
| | | .shortIdentifier('E') |
| | | .description(INFO_DESCRIPTION_REPORT_AUTHZID.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "restart" boolean argument. <br> |
| | | * <i> N.B : the 'R' short option is also used by rejectfile, serverRoot.</i> |
| | | * |
| | | * @return The "restart" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument restartArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_RESTART) |
| | | .shortIdentifier('R') |
| | | .description(INFO_DESCRIPTION_RESTART.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "skip file" string argument. |
| | | * |
| | | * @return The "skipFile" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument skippedImportFileArgument() throws ArgumentException { |
| | | return StringArgument.builder("skipFile") |
| | | .description(INFO_GENERAL_DESCRIPTION_SKIPPED_FILE.get()) |
| | | .valuePlaceholder(INFO_SKIP_FILE_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "sample data" integer argument. <br> |
| | | * <i> N.B : the 'd' short option is also used by backupdirectory, disableservice.</i> |
| | | * |
| | | * @return The "sampleData" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static IntegerArgument sampleDataArgument() throws ArgumentException { |
| | | return IntegerArgument.builder("sampleData") |
| | | .shortIdentifier('d') |
| | | .description(INFO_SETUP_DESCRIPTION_SAMPLE_DATA.get()) |
| | | .lowerBound(0) |
| | | .defaultValue(0) |
| | | .valuePlaceholder(INFO_NUM_ENTRIES_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "sasloption" string argument. <br> |
| | | * <i> N.B : the 'o' short option is also used by outputLDIF.</i> |
| | | * |
| | | * @return The "sasloption" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument saslArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_SASLOPTION) |
| | | .shortIdentifier(OPTION_SHORT_SASLOPTION) |
| | | .description(INFO_LDAP_CONN_DESCRIPTION_SASLOPTIONS.get()) |
| | | .multiValued() |
| | | .valuePlaceholder(INFO_SASL_OPTION_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "searchScope" string argument.<br> |
| | | * <i> N.B : the 's' short option is also used by servicestate, sourceldif, randomSeed, script-friendly.</i> |
| | | * |
| | | * @return The "searchScope" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static MultiChoiceArgument<SearchScope> searchScopeArgument() throws ArgumentException { |
| | | return MultiChoiceArgument.<SearchScope>builder(OPTION_LONG_SEARCHSCOPE) |
| | | .shortIdentifier(OPTION_SHORT_SEARCHSCOPE) |
| | | .description(INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE.get()) |
| | | .allowedValues(SearchScope.values()) |
| | | .defaultValue(SearchScope.WHOLE_SUBTREE) |
| | | .valuePlaceholder(INFO_SEARCH_SCOPE_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "script-friendly" boolean argument.<br> |
| | | * <i> N.B : the 's' short option is also used by searchScope, servicestate, sourceldif, randomSeed.</i> |
| | | * |
| | | * @return The "script-friendly" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument scriptFriendlyArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_SCRIPT_FRIENDLY) |
| | | .shortIdentifier(OPTION_SHORT_SCRIPT_FRIENDLY) |
| | | .description(INFO_DESCRIPTION_SCRIPT_FRIENDLY.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "LDAP port" integer argument. |
| | | * |
| | | * @param defaultLdapPort |
| | | * Default LDAP Connector port. |
| | | * @return The "ldapPort" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static IntegerArgument ldapPortArgument(final int defaultLdapPort) throws ArgumentException { |
| | | return IntegerArgument.builder("ldapPort") |
| | | .shortIdentifier(OPTION_SHORT_PORT) |
| | | .description(INFO_ARGUMENT_DESCRIPTION_LDAPPORT.get()) |
| | | .range(1, 65535) |
| | | .defaultValue(defaultLdapPort) |
| | | .valuePlaceholder(INFO_PORT_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "Admin port" integer argument. |
| | | * |
| | | * @param defaultAdminPort |
| | | * Default Administration Connector port. |
| | | * @return The "adminConnectorPort" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static IntegerArgument adminLdapPortArgument(final int defaultAdminPort) throws ArgumentException { |
| | | return IntegerArgument.builder("adminConnectorPort") |
| | | .description(INFO_ARGUMENT_DESCRIPTION_ADMINCONNECTORPORT.get()) |
| | | .range(1, 65535) |
| | | .defaultValue(defaultAdminPort) |
| | | .valuePlaceholder(INFO_PORT_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "advanced" boolean argument. |
| | | * |
| | | * @return The "advanced" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument advancedModeArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_ADVANCED) |
| | | .description(INFO_DESCRIPTION_ADVANCED.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "JMX port" integer argument. |
| | | * |
| | | * @param defaultJMXPort |
| | | * Default JMX port. |
| | | * @return The "jmxPort" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static IntegerArgument jmxPortArgument(final int defaultJMXPort) throws ArgumentException { |
| | | return IntegerArgument.builder("jmxPort") |
| | | .shortIdentifier('x') |
| | | .description(INFO_ARGUMENT_DESCRIPTION_SKIPPORT.get()) |
| | | .range(1, 65535) |
| | | .defaultValue(defaultJMXPort) |
| | | .valuePlaceholder(INFO_JMXPORT_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "skipPortCheck" boolean argument. |
| | | * |
| | | * @return The "skipPortCheck" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument skipPortCheckArgument() throws ArgumentException { |
| | | return BooleanArgument.builder("skipPortCheck") |
| | | .shortIdentifier('S') |
| | | .description(INFO_ARGUMENT_DESCRIPTION_SKIPPORT.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "startTLS" boolean argument. |
| | | * |
| | | * @return The "startTLS" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument startTLSArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_START_TLS) |
| | | .shortIdentifier(OPTION_SHORT_START_TLS) |
| | | .description(INFO_DESCRIPTION_START_TLS.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "rootUserDN" string argument. <br> |
| | | * <i> N.B : the 'D' short option is also used by bindDN.</i> |
| | | * |
| | | * @return The "rootUserDN" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument rootDNArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_ROOT_USER_DN) |
| | | .shortIdentifier(OPTION_SHORT_ROOT_USER_DN) |
| | | .description(INFO_ARGUMENT_DESCRIPTION_ROOTDN.get()) |
| | | .defaultValue("cn=Directory Manager") |
| | | .valuePlaceholder(INFO_ROOT_USER_DN_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "directory manager DN password" string argument. |
| | | * |
| | | * @return The "rootUserPassword" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument rootDNPwdArgument() throws ArgumentException { |
| | | return StringArgument.builder("rootUserPassword") |
| | | .shortIdentifier(OPTION_SHORT_BINDPWD) |
| | | .description(INFO_ROOT_USER_PWD_PLACEHOLDER.get()) |
| | | .valuePlaceholder(INFO_ROOT_USER_PWD_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "directory manager DN password file" file argument. |
| | | * |
| | | * @return The "rootUserPasswordFile" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static FileBasedArgument rootDNPwdFileArgument() throws ArgumentException { |
| | | return FileBasedArgument.builder("rootUserPasswordFile") |
| | | .shortIdentifier(OPTION_SHORT_BINDPWD_FILE) |
| | | .description(INFO_ARGUMENT_DESCRIPTION_ROOTPWFILE.get()) |
| | | .valuePlaceholder(INFO_ROOT_USER_PWD_FILE_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "enable window service" integer argument. |
| | | * |
| | | * @return The "enableWindowsService" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument enableWindowsServiceArgument() throws ArgumentException { |
| | | return BooleanArgument.builder("enableWindowsService") |
| | | .shortIdentifier('e') |
| | | .description(INFO_ARGUMENT_DESCRIPTION_ENABLE_WINDOWS_SERVICE.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "encoding" string argument. <br> |
| | | * <i> N.B : the 'i' short option is also used by cli</i> |
| | | * |
| | | * @return The "encoding" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument encodingArgument() throws ArgumentException { |
| | | return StringArgument.builder("encoding") |
| | | .shortIdentifier('i') |
| | | .description(INFO_DESCRIPTION_ENCODING.get()) |
| | | .valuePlaceholder(INFO_ENCODING_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "do not start" boolean argument. |
| | | * |
| | | * @return The "doNotStart" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument doNotStartArgument() throws ArgumentException { |
| | | return BooleanArgument.builder("doNotStart") |
| | | .shortIdentifier('O') |
| | | .description(INFO_SETUP_DESCRIPTION_DO_NOT_START.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "displayCommand" boolean argument. |
| | | * |
| | | * @return The "displayCommand" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument displayEquivalentCommandArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_DISPLAY_EQUIVALENT) |
| | | .description(INFO_DESCRIPTION_DISPLAY_EQUIVALENT.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "commandFilePath" string argument. |
| | | * |
| | | * @param description |
| | | * The description of this argument. |
| | | * @return The "commandFilePath" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument equivalentCommandFileArgument(final LocalizableMessage description) |
| | | throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_EQUIVALENT_COMMAND_FILE_PATH) |
| | | .description(description) |
| | | .valuePlaceholder(INFO_PATH_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "filename" string argument. |
| | | * <i> N.B : the 'f' short option is also used by configfile</i> |
| | | * @param description |
| | | * The description of this argument. |
| | | * @return The "filename" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument filenameArgument(final LocalizableMessage description) throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_FILENAME) |
| | | .shortIdentifier(OPTION_SHORT_FILENAME) |
| | | .description(description) |
| | | .valuePlaceholder(INFO_FILE_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "enable start TLS" boolean argument. |
| | | * |
| | | * @return The "enableStartTLS" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument enableTLSArgument() throws ArgumentException { |
| | | return BooleanArgument.builder("enableStartTLS") |
| | | .shortIdentifier(OPTION_SHORT_START_TLS) |
| | | .description(INFO_SETUP_DESCRIPTION_ENABLE_STARTTLS.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "ldaps port" integer argument. <br> |
| | | * <i> N.B : the 'Z' short option is also used by useSSL.</i> |
| | | * |
| | | * @param defaultSecurePort |
| | | * Default value for the LDAPS port. |
| | | * @return The "ldapsPort" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static IntegerArgument ldapsPortArgument(final int defaultSecurePort) throws ArgumentException { |
| | | return IntegerArgument.builder("ldapsPort") |
| | | .shortIdentifier(OPTION_SHORT_USE_SSL) |
| | | .description(INFO_ARGUMENT_DESCRIPTION_LDAPSPORT.get()) |
| | | .range(1, 65535) |
| | | .defaultValue(defaultSecurePort) |
| | | .valuePlaceholder(INFO_PORT_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "ldiffile" string argument. |
| | | * |
| | | * @param description |
| | | * The description of this argument. |
| | | * @return The "ldapsPort" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument ldifFileArgument(final LocalizableMessage description) throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_LDIF_FILE) |
| | | .shortIdentifier(OPTION_SHORT_LDIF_FILE) |
| | | .description(description) |
| | | .multiValued() |
| | | .valuePlaceholder(INFO_LDIFFILE_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "generate self certificate" boolean argument. |
| | | * |
| | | * @return The "generateSelfSignedCertificate" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument generateSelfSignedArgument() throws ArgumentException { |
| | | return BooleanArgument.builder("generateSelfSignedCertificate") |
| | | .description(INFO_ARGUMENT_DESCRIPTION_USE_SELF_SIGNED_CERTIFICATE.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "hostname" string argument. |
| | | * |
| | | * @param defaultHostName |
| | | * The default host name value. |
| | | * @return The "hostname" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument hostNameArgument(final String defaultHostName) throws ArgumentException { |
| | | return hostNameArgument(defaultHostName, null); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "hostname" string argument. |
| | | * |
| | | * @param defaultHostName |
| | | * The default host name value. |
| | | * @param description |
| | | * The custom description. |
| | | * @return The "hostname" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument hostNameArgument(final String defaultHostName, final LocalizableMessage description) |
| | | throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_HOST) |
| | | .shortIdentifier(OPTION_SHORT_HOST) |
| | | .description(description != null ? description : INFO_ARGUMENT_DESCRIPTION_HOST_NAME.get()) |
| | | .defaultValue(defaultHostName) |
| | | .valuePlaceholder(INFO_HOST_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "use PKCS11 key store" boolean argument. |
| | | * |
| | | * @return The "usePkcs11Keystore" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument usePKCS11KeystoreArgument() throws ArgumentException { |
| | | return BooleanArgument.builder("usePkcs11Keystore") |
| | | .description(INFO_ARGUMENT_DESCRIPTION_USE_PKCS11.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "use java key store" string argument. |
| | | * |
| | | * @return The "useJavaKeystore" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument useJavaKeyStoreArgument() throws ArgumentException { |
| | | return StringArgument.builder("useJavaKeystore") |
| | | .description(INFO_ARGUMENT_DESCRIPTION_USE_JAVAKEYSTORE.get()) |
| | | .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "use JCEKS" string argument. |
| | | * |
| | | * @return The "useJCEKS" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument useJCEKSArgument() throws ArgumentException { |
| | | return StringArgument.builder("useJCEKS") |
| | | .description(INFO_ARGUMENT_DESCRIPTION_USE_JCEKS.get()) |
| | | .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "use PKCS12 key store" string argument. |
| | | * |
| | | * @return The "usePkcs12keyStore" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument usePKCS12KeyStoreArgument() throws ArgumentException { |
| | | return StringArgument.builder("usePkcs12keyStore") |
| | | .description(INFO_ARGUMENT_DESCRIPTION_USE_PKCS12.get()) |
| | | .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "useSSL" boolean argument. <br> |
| | | * <i> N.B : the 'Z' short option is also used by ldapsport.</i> |
| | | * |
| | | * @return The "useSSL" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static BooleanArgument useSSLArgument() throws ArgumentException { |
| | | return BooleanArgument.builder(OPTION_LONG_USE_SSL) |
| | | .shortIdentifier(OPTION_SHORT_USE_SSL) |
| | | .description(INFO_DESCRIPTION_USE_SSL.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "key store password" string argument. |
| | | * |
| | | * @return The "keyStorePassword" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument keyStorePasswordArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_KEYSTORE_PWD) |
| | | .shortIdentifier(OPTION_SHORT_KEYSTORE_PWD) |
| | | .description(INFO_ARGUMENT_DESCRIPTION_KEYSTOREPASSWORD.get()) |
| | | .valuePlaceholder(INFO_KEYSTORE_PWD_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "key store password file" file argument. |
| | | * |
| | | * @return The "keyStorePassword" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static FileBasedArgument keyStorePasswordFileArgument() throws ArgumentException { |
| | | return FileBasedArgument.builder(OPTION_LONG_KEYSTORE_PWD_FILE) |
| | | .shortIdentifier(OPTION_SHORT_KEYSTORE_PWD_FILE) |
| | | .description(INFO_ARGUMENT_DESCRIPTION_KEYSTOREPASSWORD_FILE.get()) |
| | | .valuePlaceholder(INFO_KEYSTORE_PWD_FILE_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "keyStorePath" string argument. |
| | | * |
| | | * @return The "keyStorePath" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument keyStorePathArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_KEYSTOREPATH) |
| | | .shortIdentifier(OPTION_SHORT_KEYSTOREPATH) |
| | | .description(INFO_DESCRIPTION_KEYSTOREPATH.get()) |
| | | .valuePlaceholder(INFO_KEYSTOREPATH_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "key store password file" string argument. |
| | | * |
| | | * @return The "keyStorePassword" argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument certNickNameArgument() throws ArgumentException { |
| | | return StringArgument.builder(OPTION_LONG_CERT_NICKNAME) |
| | | .shortIdentifier(OPTION_SHORT_CERT_NICKNAME) |
| | | .description(INFO_ARGUMENT_DESCRIPTION_CERT_NICKNAME.get()) |
| | | .multiValued() |
| | | .valuePlaceholder(INFO_NICKNAME_PLACEHOLDER.get()) |
| | | .buildArgument(); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "admin uid" string argument with the provided description. |
| | | * |
| | | * @param description |
| | | * The argument localizable description. |
| | | * @return The "admin uid" string argument with the provided description. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument adminUid(final LocalizableMessage description) throws ArgumentException { |
| | | return adminUidArgument(false, description); |
| | | } |
| | | |
| | | /** |
| | | * Returns the "admin uid" hidden string argument. |
| | | * |
| | | * @param description |
| | | * The argument localizable description. |
| | | * @return The "admin uid" hidden string argument. |
| | | * @throws ArgumentException |
| | | * If there is a problem with any of the parameters used to create this argument. |
| | | */ |
| | | public static StringArgument adminUidHiddenArgument(final LocalizableMessage description) |
| | | throws ArgumentException { |
| | | return adminUidArgument(true, description); |
| | | } |
| | | |
| | | private static StringArgument adminUidArgument(final boolean hidden, final LocalizableMessage description) |
| | | throws ArgumentException { |
| | | final StringArgument.Builder builder = StringArgument.builder(OPTION_LONG_ADMIN_UID) |
| | | .shortIdentifier('I') |
| | | .description(description) |
| | | .defaultValue(CliConstants.GLOBAL_ADMIN_UID) |
| | | .valuePlaceholder(INFO_ADMINUID_PLACEHOLDER.get()); |
| | | if (hidden) { |
| | | builder.hidden(); |
| | | } |
| | | return builder.buildArgument(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2011-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.ArgumentConstants.*; |
| | | import static com.forgerock.opendj.cli.CliConstants.DEFAULT_LDAP_PORT; |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | import static com.forgerock.opendj.cli.Utils.getHostNameForLdapUrl; |
| | | import static com.forgerock.opendj.cli.Utils.throwIfArgumentsConflict; |
| | | import static org.forgerock.opendj.ldap.LDAPConnectionFactory.AUTHN_BIND_REQUEST; |
| | | import static org.forgerock.opendj.ldap.LDAPConnectionFactory.CONNECT_TIMEOUT; |
| | | import static org.forgerock.opendj.ldap.LDAPConnectionFactory.SSL_CONTEXT; |
| | | import static org.forgerock.opendj.ldap.LDAPConnectionFactory.SSL_USE_STARTTLS; |
| | | import static com.forgerock.opendj.cli.CommonArguments.*; |
| | | |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.IOException; |
| | | import java.net.InetAddress; |
| | | import java.security.GeneralSecurityException; |
| | | import java.security.KeyStore; |
| | | import java.security.KeyStoreException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.security.cert.CertificateException; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | import javax.net.ssl.SSLContext; |
| | | import javax.net.ssl.TrustManager; |
| | | import javax.net.ssl.X509KeyManager; |
| | | import javax.net.ssl.X509TrustManager; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.ldap.ConnectionFactory; |
| | | import org.forgerock.opendj.ldap.KeyManagers; |
| | | import org.forgerock.opendj.ldap.LDAPConnectionFactory; |
| | | import org.forgerock.opendj.ldap.SSLContextBuilder; |
| | | import org.forgerock.opendj.ldap.TrustManagers; |
| | | import org.forgerock.opendj.ldap.controls.AuthorizationIdentityRequestControl; |
| | | import org.forgerock.opendj.ldap.controls.PasswordPolicyRequestControl; |
| | | import org.forgerock.opendj.ldap.requests.BindRequest; |
| | | import org.forgerock.opendj.ldap.requests.CRAMMD5SASLBindRequest; |
| | | import org.forgerock.opendj.ldap.requests.DigestMD5SASLBindRequest; |
| | | import org.forgerock.opendj.ldap.requests.ExternalSASLBindRequest; |
| | | import org.forgerock.opendj.ldap.requests.GSSAPISASLBindRequest; |
| | | import org.forgerock.opendj.ldap.requests.PlainSASLBindRequest; |
| | | import org.forgerock.opendj.ldap.requests.Requests; |
| | | import org.forgerock.util.Options; |
| | | import org.forgerock.util.time.Duration; |
| | | |
| | | /** |
| | | * A connection factory designed for use with command line tools. |
| | | */ |
| | | public final class ConnectionFactoryProvider { |
| | | /** The Logger. */ |
| | | static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | /** The 'hostName' global argument. */ |
| | | private StringArgument hostNameArg; |
| | | /** The 'port' global argument. */ |
| | | private IntegerArgument portArg; |
| | | |
| | | /** The 'bindDN' global argument. */ |
| | | private StringArgument bindNameArg; |
| | | /** The 'bindPasswordFile' global argument. */ |
| | | private FileBasedArgument bindPasswordFileArg; |
| | | |
| | | /** The 'password' value. */ |
| | | private char[] password; |
| | | /** The 'bindPassword' global argument. */ |
| | | private StringArgument bindPasswordArg; |
| | | |
| | | /** The 'connectTimeOut' global argument. */ |
| | | private IntegerArgument connectTimeOut; |
| | | |
| | | /** The 'trustAllArg' global argument. */ |
| | | private BooleanArgument trustAllArg; |
| | | /** The 'trustStore' global argument. */ |
| | | private StringArgument trustStorePathArg; |
| | | /** The 'trustStorePassword' global argument. */ |
| | | private StringArgument trustStorePasswordArg; |
| | | /** The 'trustStorePasswordFile' global argument. */ |
| | | private FileBasedArgument trustStorePasswordFileArg; |
| | | |
| | | /** The 'keyStore' global argument. */ |
| | | private StringArgument keyStorePathArg; |
| | | /** The 'keyStorePassword' global argument. */ |
| | | private StringArgument keyStorePasswordArg; |
| | | /** The 'keyStorePasswordFile' global argument. */ |
| | | private FileBasedArgument keyStorePasswordFileArg; |
| | | |
| | | /** The 'certNicknameArg' global argument. */ |
| | | private StringArgument certNicknameArg; |
| | | |
| | | /** The 'useSSLArg' global argument. */ |
| | | private BooleanArgument useSSLArg; |
| | | /** The 'useStartTLSArg' global argument. */ |
| | | private BooleanArgument useStartTLSArg; |
| | | /** Argument indicating a SASL option. */ |
| | | private StringArgument saslOptionArg; |
| | | |
| | | /** |
| | | * Whether to request that the server return the authorization ID in the |
| | | * bind response. |
| | | */ |
| | | private final BooleanArgument reportAuthzIDArg; |
| | | |
| | | /** Whether to use the password policy control in the bind request. */ |
| | | private final BooleanArgument usePasswordPolicyControlArg; |
| | | |
| | | /** The SSL context linked to this connection. */ |
| | | private SSLContext sslContext; |
| | | |
| | | /** The basic connection factory. */ |
| | | private ConnectionFactory connFactory; |
| | | |
| | | /** The bind request to connect with. */ |
| | | private BindRequest bindRequest; |
| | | |
| | | /** The console application linked to this connection in interactive mode. */ |
| | | private final ConsoleApplication app; |
| | | |
| | | /** If this connection should be an admin connection. */ |
| | | private boolean isAdminConnection; |
| | | |
| | | /** |
| | | * Default constructor to create a connection factory designed for use with command line tools, |
| | | * adding basic LDAP connection arguments to the specified parser (e.g: hostname, bindname...etc). |
| | | * |
| | | * @param argumentParser |
| | | * The argument parser. |
| | | * @param app |
| | | * The console application linked to this connection factory. |
| | | * @throws ArgumentException |
| | | * If an error occurs during parsing the arguments. |
| | | */ |
| | | public ConnectionFactoryProvider(final ArgumentParser argumentParser, |
| | | final ConsoleApplication app) throws ArgumentException { |
| | | this(argumentParser, app, "", DEFAULT_LDAP_PORT, false); |
| | | } |
| | | |
| | | /** |
| | | * Constructor to create a connection factory designed for use with command line tools, |
| | | * adding basic LDAP connection arguments to the specified parser (e.g: hostname, bindname...etc). |
| | | * |
| | | * @param argumentParser |
| | | * The argument parser. |
| | | * @param app |
| | | * The console application linked to this connection factory. |
| | | * @param defaultBindDN |
| | | * The bind DN default's value. |
| | | * @param defaultPort |
| | | * The LDAP port default's value. |
| | | * @param alwaysSSL |
| | | * {@code true} if this connection should be used with SSL. |
| | | * @throws ArgumentException |
| | | * If an error occurs during parsing the elements. |
| | | */ |
| | | public ConnectionFactoryProvider(final ArgumentParser argumentParser, |
| | | final ConsoleApplication app, final String defaultBindDN, final int defaultPort, |
| | | final boolean alwaysSSL) throws ArgumentException { |
| | | this.app = app; |
| | | |
| | | useSSLArg = useSSLArgument(); |
| | | if (!alwaysSSL) { |
| | | argumentParser.addLdapConnectionArgument(useSSLArg); |
| | | } else { |
| | | // simulate that the useSSL arg has been given in the CLI |
| | | useSSLArg.setPresent(true); |
| | | } |
| | | |
| | | useStartTLSArg = startTLSArgument(); |
| | | if (!alwaysSSL) { |
| | | argumentParser.addLdapConnectionArgument(useStartTLSArg); |
| | | } |
| | | |
| | | String defaultHostName; |
| | | try { |
| | | defaultHostName = InetAddress.getLocalHost().getHostName(); |
| | | } catch (final Exception e) { |
| | | defaultHostName = "Unknown (" + e + ")"; |
| | | } |
| | | hostNameArg = hostNameArgument(defaultHostName); |
| | | argumentParser.addLdapConnectionArgument(hostNameArg); |
| | | |
| | | LocalizableMessage portDescription = INFO_DESCRIPTION_PORT.get(); |
| | | if (alwaysSSL) { |
| | | portDescription = INFO_DESCRIPTION_ADMIN_PORT.get(); |
| | | } |
| | | |
| | | portArg = portArgument(defaultPort, portDescription); |
| | | argumentParser.addLdapConnectionArgument(portArg); |
| | | |
| | | bindNameArg = bindDNArgument(defaultBindDN); |
| | | argumentParser.addLdapConnectionArgument(bindNameArg); |
| | | |
| | | bindPasswordArg = bindPasswordArgument(); |
| | | argumentParser.addLdapConnectionArgument(bindPasswordArg); |
| | | |
| | | bindPasswordFileArg = bindPasswordFileArgument(); |
| | | argumentParser.addLdapConnectionArgument(bindPasswordFileArg); |
| | | |
| | | saslOptionArg = saslArgument(); |
| | | argumentParser.addLdapConnectionArgument(saslOptionArg); |
| | | |
| | | trustAllArg = trustAllArgument(); |
| | | argumentParser.addLdapConnectionArgument(trustAllArg); |
| | | |
| | | trustStorePathArg = trustStorePathArgument(); |
| | | argumentParser.addLdapConnectionArgument(trustStorePathArg); |
| | | |
| | | trustStorePasswordArg = trustStorePasswordArgument(); |
| | | argumentParser.addLdapConnectionArgument(trustStorePasswordArg); |
| | | |
| | | trustStorePasswordFileArg = trustStorePasswordFileArgument(); |
| | | argumentParser.addLdapConnectionArgument(trustStorePasswordFileArg); |
| | | |
| | | keyStorePathArg = keyStorePathArgument(); |
| | | argumentParser.addLdapConnectionArgument(keyStorePathArg); |
| | | |
| | | keyStorePasswordArg = keyStorePasswordArgument(); |
| | | argumentParser.addLdapConnectionArgument(keyStorePasswordArg); |
| | | |
| | | keyStorePasswordFileArg = keyStorePasswordFileArgument(); |
| | | argumentParser.addLdapConnectionArgument(keyStorePasswordFileArg); |
| | | |
| | | certNicknameArg = certNickNameArgument(); |
| | | argumentParser.addLdapConnectionArgument(certNicknameArg); |
| | | |
| | | reportAuthzIDArg = reportAuthzIdArgument(); |
| | | argumentParser.addArgument(reportAuthzIDArg); |
| | | |
| | | connectTimeOut = connectTimeOutHiddenArgument(); |
| | | argumentParser.addArgument(connectTimeOut); |
| | | |
| | | usePasswordPolicyControlArg = |
| | | BooleanArgument.builder(OPTION_LONG_USE_PW_POLICY_CTL) |
| | | .description(INFO_DESCRIPTION_USE_PWP_CONTROL.get()) |
| | | .buildAndAddToParser(argumentParser); |
| | | } |
| | | |
| | | /** |
| | | * Returns the connect time out. |
| | | * |
| | | * @return The connect time out value. |
| | | */ |
| | | public int getConnectTimeout() { |
| | | if (connectTimeOut.isPresent()) { |
| | | try { |
| | | return connectTimeOut.getIntValue(); |
| | | } catch (ArgumentException e) { |
| | | return Integer.valueOf(connectTimeOut.getDefaultValue()); |
| | | } |
| | | } |
| | | return Integer.valueOf(connectTimeOut.getDefaultValue()); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Returns the host name if the argument is present otherwise, if the application |
| | | * is interactive, prompt the user for it. |
| | | * |
| | | * @return The host name value. |
| | | * @throws ArgumentException |
| | | * If the host name cannot be retrieved. |
| | | */ |
| | | public String getHostname() throws ArgumentException { |
| | | String value = ""; |
| | | |
| | | if (hostNameArg.isPresent()) { |
| | | value = hostNameArg.getValue(); |
| | | } else if (app.isInteractive()) { |
| | | try { |
| | | value = app.readInput(INFO_DESCRIPTION_HOST.get(), getHostNameDefaultValue(value)); |
| | | app.println(); |
| | | hostNameArg.addValue(value); |
| | | hostNameArg.setPresent(true); |
| | | } catch (ClientException e) { |
| | | throw new ArgumentException(ERR_ERROR_CANNOT_READ_HOST_NAME.get(), e); |
| | | } |
| | | } else { |
| | | return getHostNameDefaultValue(value); |
| | | } |
| | | |
| | | return getHostNameForLdapUrl(value); |
| | | } |
| | | |
| | | private String getHostNameDefaultValue(String fallbackValue) { |
| | | return hostNameArg.getDefaultValue() != null ? hostNameArg.getDefaultValue() : fallbackValue; |
| | | } |
| | | |
| | | /** |
| | | * Get the port which has to be used for the command. |
| | | * |
| | | * @return The port specified by the command line argument, or the default value, if not specified. |
| | | */ |
| | | public int getPort() { |
| | | if (portArg.isPresent()) { |
| | | try { |
| | | return portArg.getIntValue(); |
| | | } catch (ArgumentException e) { |
| | | return Integer.valueOf(portArg.getDefaultValue()); |
| | | } |
| | | } else if (app.isInteractive()) { |
| | | final LocalizableMessage portMsg = |
| | | isAdminConnection ? INFO_DESCRIPTION_ADMIN_PORT.get() : INFO_DESCRIPTION_PORT.get(); |
| | | int value = app.askPort(portMsg, Integer.valueOf(portArg.getDefaultValue()), logger); |
| | | app.println(); |
| | | portArg.addValue(Integer.toString(value)); |
| | | portArg.setPresent(true); |
| | | return value; |
| | | } |
| | | return Integer.valueOf(portArg.getDefaultValue()); |
| | | } |
| | | |
| | | /** |
| | | * Indicate if the SSL mode is required. |
| | | * |
| | | * @return True if SSL mode is required |
| | | */ |
| | | public boolean useSSL() { |
| | | return useSSLArg.isPresent(); |
| | | } |
| | | |
| | | /** |
| | | * Indicate if the startTLS mode is required. |
| | | * |
| | | * @return True if startTLS mode is required |
| | | */ |
| | | public boolean useStartTLS() { |
| | | return useStartTLSArg.isPresent(); |
| | | } |
| | | |
| | | /** |
| | | * Constructs a connection factory for pre-authenticated connections. Checks if any conflicting arguments are |
| | | * present, build the connection with selected arguments and returns the connection factory. If the application is |
| | | * interactive, it will prompt the user for missing parameters. |
| | | * |
| | | * @return The connection factory. |
| | | * @throws ArgumentException |
| | | * If an error occurs during the parsing of the arguments (conflicting arguments or if an error occurs |
| | | * during building SSL context). |
| | | */ |
| | | public ConnectionFactory getAuthenticatedConnectionFactory() throws ArgumentException { |
| | | return getConnectionFactory(true); |
| | | } |
| | | |
| | | /** |
| | | * Constructs a connection factory for unauthenticated connections. Checks if any conflicting arguments are present, |
| | | * build the connection with selected arguments and returns the connection factory. If the application is |
| | | * interactive, it will prompt the user for missing parameters. |
| | | * |
| | | * @return The connection factory. |
| | | * @throws ArgumentException |
| | | * If an error occurs during the parsing of the arguments (conflicting arguments or if an error occurs |
| | | * during building SSL context). |
| | | */ |
| | | public ConnectionFactory getUnauthenticatedConnectionFactory() throws ArgumentException { |
| | | return getConnectionFactory(false); |
| | | } |
| | | |
| | | private ConnectionFactory getConnectionFactory(boolean usePreAuthentication) throws ArgumentException { |
| | | if (connFactory == null) { |
| | | checkForConflictingArguments(); |
| | | |
| | | if (app.isInteractive()) { |
| | | boolean portIsMissing = !portArg.isPresent() || portArg.getIntValue() == 0; |
| | | boolean bindPwdIsMissing = !bindPasswordArg.isPresent() && !bindPasswordFileArg.isPresent(); |
| | | if (!hostNameArg.isPresent() || portIsMissing || !bindNameArg.isPresent() || bindPwdIsMissing) { |
| | | app.printHeader(INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS.get()); |
| | | } |
| | | if (!hostNameArg.isPresent()) { |
| | | getHostname(); |
| | | } |
| | | if (portIsMissing) { |
| | | getPort(); |
| | | } |
| | | if (!bindNameArg.isPresent()) { |
| | | getBindName(); |
| | | } |
| | | if (bindPwdIsMissing) { |
| | | getPassword(); |
| | | } |
| | | } |
| | | |
| | | try { |
| | | if (useSSLArg.isPresent() || useStartTLSArg.isPresent()) { |
| | | String clientAlias; |
| | | if (certNicknameArg.isPresent()) { |
| | | clientAlias = certNicknameArg.getValue(); |
| | | } else { |
| | | clientAlias = null; |
| | | } |
| | | |
| | | if (sslContext == null) { |
| | | final TrustManager trustManager = getTrustManager(); |
| | | |
| | | X509KeyManager keyManager = null; |
| | | final X509KeyManager akm = getKeyManager(keyStorePathArg.getValue()); |
| | | |
| | | if (akm != null && clientAlias != null) { |
| | | keyManager = KeyManagers.useSingleCertificate(clientAlias, akm); |
| | | } |
| | | |
| | | sslContext = |
| | | new SSLContextBuilder().setTrustManager(trustManager) |
| | | .setKeyManager(keyManager).getSSLContext(); |
| | | } |
| | | } |
| | | } catch (final Exception e) { |
| | | throw new ArgumentException(ERR_LDAP_CONN_CANNOT_INITIALIZE_SSL.get(e.toString()), |
| | | e); |
| | | } |
| | | |
| | | Options options = Options.defaultOptions(); |
| | | if (sslContext != null) { |
| | | options.set(SSL_CONTEXT, sslContext) |
| | | .set(SSL_USE_STARTTLS, useStartTLSArg.isPresent()); |
| | | } |
| | | options.set(CONNECT_TIMEOUT, new Duration((long) getConnectTimeout(), TimeUnit.MILLISECONDS)); |
| | | if (usePreAuthentication) { |
| | | options.set(AUTHN_BIND_REQUEST, getBindRequest()); |
| | | } |
| | | connFactory = new LDAPConnectionFactory(hostNameArg.getValue(), portArg.getIntValue(), options); |
| | | } |
| | | return connFactory; |
| | | } |
| | | |
| | | /** |
| | | * Verifies if the connection arguments are not conflicting together or if they are readable. |
| | | * |
| | | * @throws ArgumentException |
| | | * If arguments are conflicting or if the files cannot be read, |
| | | * an argument exception is thrown. |
| | | */ |
| | | private void checkForConflictingArguments() throws ArgumentException { |
| | | throwIfArgumentsConflict(bindPasswordArg, bindPasswordFileArg); |
| | | throwIfArgumentsConflict(trustAllArg, trustStorePathArg); |
| | | throwIfArgumentsConflict(trustAllArg, trustStorePasswordArg); |
| | | throwIfArgumentsConflict(trustAllArg, trustStorePasswordFileArg); |
| | | throwIfArgumentsConflict(trustStorePasswordArg, trustStorePasswordFileArg); |
| | | throwIfArgumentsConflict(useStartTLSArg, useSSLArg); |
| | | |
| | | if (trustStorePathArg.isPresent()) { |
| | | // Check that the path exists and is readable |
| | | final String value = trustStorePathArg.getValue(); |
| | | if (!canReadPath(value)) { |
| | | final LocalizableMessage message = ERR_CANNOT_READ_TRUSTSTORE.get(value); |
| | | throw new ArgumentException(message); |
| | | } |
| | | } |
| | | |
| | | if (keyStorePathArg.isPresent()) { |
| | | // Check that the path exists and is readable |
| | | final String value = keyStorePathArg.getValue(); |
| | | if (!canReadPath(value)) { |
| | | final LocalizableMessage message = ERR_CANNOT_READ_KEYSTORE.get(value); |
| | | throw new ArgumentException(message); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns {@code true} if we can read on the provided path and |
| | | * {@code false} otherwise. |
| | | * |
| | | * @param path |
| | | * the path. |
| | | * @return {@code true} if we can read on the provided path and |
| | | * {@code false} otherwise. |
| | | */ |
| | | private boolean canReadPath(final String path) { |
| | | final File file = new File(path); |
| | | return file.exists() && file.canRead(); |
| | | } |
| | | |
| | | private String getAuthID(final String mech) throws ArgumentException { |
| | | String value = getAuthID(); |
| | | if (value == null && bindNameArg.isPresent()) { |
| | | value = "dn: " + bindNameArg.getValue(); |
| | | } |
| | | if (value == null && app.isInteractive()) { |
| | | try { |
| | | value = |
| | | app.readInput(LocalizableMessage.raw("Authentication ID:"), bindNameArg |
| | | .getDefaultValue() == null ? null : "dn: " |
| | | + bindNameArg.getDefaultValue()); |
| | | } catch (ClientException e) { |
| | | throw new ArgumentException(LocalizableMessage |
| | | .raw("Unable to read authentication ID"), e); |
| | | } |
| | | } |
| | | if (value == null) { |
| | | throw new ArgumentException(ERR_LDAPAUTH_SASL_AUTHID_REQUIRED.get(mech)); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | private String getAuthID() throws ArgumentException { |
| | | return getSaslProperty(SASL_PROPERTY_AUTHID); |
| | | } |
| | | |
| | | private String getAuthzID() throws ArgumentException { |
| | | return getSaslProperty(SASL_PROPERTY_AUTHZID); |
| | | } |
| | | |
| | | /** |
| | | * Returns the bind name if the argument is present otherwise, in interactive mode, it |
| | | * will prompt the user. |
| | | * |
| | | * @return The bind name used for this connection. |
| | | * @throws ArgumentException |
| | | * If the bind name cannot be retrieved. |
| | | */ |
| | | public String getBindName() throws ArgumentException { |
| | | String value = ""; |
| | | if (bindNameArg.isPresent()) { |
| | | value = bindNameArg.getValue(); |
| | | } else if (app.isInteractive()) { |
| | | LocalizableMessage bindMsg; |
| | | if (isAdminConnection) { |
| | | bindMsg = INFO_DESCRIPTION_ADMIN_BINDDN.get(); |
| | | } else { |
| | | bindMsg = INFO_DESCRIPTION_BINDDN.get(); |
| | | } |
| | | try { |
| | | value = app.readInput(bindMsg, |
| | | bindNameArg.getDefaultValue() == null ? value : bindNameArg.getDefaultValue()); |
| | | app.println(); |
| | | bindNameArg.clearValues(); |
| | | bindNameArg.addValue(value); |
| | | bindNameArg.setPresent(true); |
| | | } catch (ClientException e) { |
| | | throw new ArgumentException(ERR_ERROR_CANNOT_READ_BIND_NAME.get(), e); |
| | | } |
| | | } |
| | | |
| | | return value; |
| | | } |
| | | |
| | | /** |
| | | * Returns the bind request for this connection. |
| | | * |
| | | * @return The bind request for this connection. |
| | | * @throws ArgumentException |
| | | * If the arguments of this connection are wrong. |
| | | */ |
| | | public BindRequest getBindRequest() throws ArgumentException { |
| | | if (bindRequest == null) { |
| | | String mech = getMechanism(); |
| | | |
| | | if (mech == null) { |
| | | if (bindNameArg.isPresent() || bindPasswordFileArg.isPresent() |
| | | || bindPasswordArg.isPresent()) { |
| | | bindRequest = Requests.newSimpleBindRequest(getBindName(), getPassword()); |
| | | } |
| | | } else if (DigestMD5SASLBindRequest.SASL_MECHANISM_NAME.equals(mech)) { |
| | | bindRequest = |
| | | Requests.newDigestMD5SASLBindRequest( |
| | | getAuthID(DigestMD5SASLBindRequest.SASL_MECHANISM_NAME), |
| | | getPassword()).setAuthorizationID(getAuthzID()) |
| | | .setRealm(getRealm()); |
| | | } else if (CRAMMD5SASLBindRequest.SASL_MECHANISM_NAME.equals(mech)) { |
| | | bindRequest = |
| | | Requests.newCRAMMD5SASLBindRequest( |
| | | getAuthID(CRAMMD5SASLBindRequest.SASL_MECHANISM_NAME), |
| | | getPassword()); |
| | | } else if (GSSAPISASLBindRequest.SASL_MECHANISM_NAME.equals(mech)) { |
| | | bindRequest = |
| | | Requests.newGSSAPISASLBindRequest( |
| | | getAuthID(GSSAPISASLBindRequest.SASL_MECHANISM_NAME), getPassword()) |
| | | .setKDCAddress(getKDC()).setRealm(getRealm()).setAuthorizationID( |
| | | getAuthzID()); |
| | | } else if (ExternalSASLBindRequest.SASL_MECHANISM_NAME.equals(mech)) { |
| | | if (sslContext == null) { |
| | | final LocalizableMessage message = ERR_TOOL_SASLEXTERNAL_NEEDS_SSL_OR_TLS.get(); |
| | | throw new ArgumentException(message); |
| | | } |
| | | if (!keyStorePathArg.isPresent() && getKeyStore() == null) { |
| | | final LocalizableMessage message = ERR_TOOL_SASLEXTERNAL_NEEDS_KEYSTORE.get(); |
| | | throw new ArgumentException(message); |
| | | } |
| | | bindRequest = |
| | | Requests.newExternalSASLBindRequest().setAuthorizationID(getAuthzID()); |
| | | } else if (PlainSASLBindRequest.SASL_MECHANISM_NAME.equals(mech)) { |
| | | bindRequest = |
| | | Requests.newPlainSASLBindRequest( |
| | | getAuthID(PlainSASLBindRequest.SASL_MECHANISM_NAME), getPassword()) |
| | | .setAuthorizationID(getAuthzID()); |
| | | } else { |
| | | throw new ArgumentException(ERR_LDAPAUTH_UNSUPPORTED_SASL_MECHANISM.get(mech)); |
| | | } |
| | | |
| | | if (reportAuthzIDArg.isPresent()) { |
| | | bindRequest.addControl(AuthorizationIdentityRequestControl.newControl(false)); |
| | | } |
| | | |
| | | if (usePasswordPolicyControlArg.isPresent()) { |
| | | bindRequest.addControl(PasswordPolicyRequestControl.newControl(false)); |
| | | } |
| | | } |
| | | return bindRequest; |
| | | } |
| | | |
| | | private String getMechanism() throws ArgumentException { |
| | | return getSaslProperty(SASL_PROPERTY_MECH); |
| | | } |
| | | |
| | | private String getKDC() throws ArgumentException { |
| | | return getSaslProperty(SASL_PROPERTY_KDC); |
| | | } |
| | | |
| | | private String getRealm() throws ArgumentException { |
| | | return getSaslProperty(SASL_PROPERTY_REALM); |
| | | } |
| | | |
| | | private String getSaslProperty(String propertyName) throws ArgumentException { |
| | | for (final String s : saslOptionArg.getValues()) { |
| | | if (s.startsWith(propertyName)) { |
| | | return parseSASLOptionValue(s); |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return connFactory.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a <CODE>KeyManager</CODE> object that may be used for |
| | | * interactions requiring access to a key manager. |
| | | * |
| | | * @param keyStoreFile |
| | | * The path to the file containing the key store data. |
| | | * @return A set of <CODE>KeyManager</CODE> objects that may be used for |
| | | * interactions requiring access to a key manager. |
| | | * @throws java.security.KeyStoreException |
| | | * If a problem occurs while interacting with the key store. |
| | | * @throws IOException |
| | | * If there is an I/O or format problem with the keystore data. |
| | | * @throws NoSuchAlgorithmException |
| | | * If a problem occurs while loading with the key store. |
| | | * @throws CertificateException |
| | | * If a problem occurs while loading with the key store. |
| | | */ |
| | | public X509KeyManager getKeyManager(String keyStoreFile) throws KeyStoreException, |
| | | IOException, NoSuchAlgorithmException, CertificateException { |
| | | if (keyStoreFile == null) { |
| | | // Lookup the file name through the JDK property. |
| | | keyStoreFile = getKeyStore(); |
| | | } |
| | | |
| | | if (keyStoreFile == null) { |
| | | return null; |
| | | } |
| | | |
| | | final String keyStorePass = getKeyStorePIN(); |
| | | char[] keyStorePIN = null; |
| | | if (keyStorePass != null) { |
| | | keyStorePIN = keyStorePass.toCharArray(); |
| | | } |
| | | |
| | | final KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType()); |
| | | try (final FileInputStream fos = new FileInputStream(keyStoreFile)) { |
| | | keystore.load(fos, keyStorePIN); |
| | | } |
| | | |
| | | return new ApplicationKeyManager(keystore, keyStorePIN); |
| | | } |
| | | |
| | | /** |
| | | * Read the KeyStore from the JSSE system property. |
| | | * |
| | | * @return The path to the key store file. |
| | | */ |
| | | |
| | | private String getKeyStore() { |
| | | return System.getProperty("javax.net.ssl.keyStore"); |
| | | } |
| | | |
| | | /** |
| | | * Read the KeyStore PIN from the JSSE system property. |
| | | * |
| | | * @return The PIN that should be used to access the key store. |
| | | */ |
| | | |
| | | private String getKeyStorePIN() { |
| | | String pwd; |
| | | if (keyStorePasswordArg.isPresent()) { |
| | | pwd = keyStorePasswordArg.getValue(); |
| | | } else if (keyStorePasswordFileArg.isPresent()) { |
| | | pwd = keyStorePasswordFileArg.getValue(); |
| | | } else { |
| | | pwd = System.getProperty("javax.net.ssl.keyStorePassword"); |
| | | } |
| | | return pwd; |
| | | } |
| | | |
| | | /** |
| | | * Get the password which has to be used for the command. In interactive mode, if |
| | | * the password arguments are missing, the user will be prompted. |
| | | * |
| | | * @return The password stored into the specified file on by the command |
| | | * line argument, or empty it if not specified. |
| | | * @throws ArgumentException |
| | | * If a problem occurs while interacting with the password. |
| | | */ |
| | | public char[] getPassword() throws ArgumentException { |
| | | char[] value = "".toCharArray(); |
| | | |
| | | if (bindPasswordArg.isPresent()) { |
| | | value = bindPasswordArg.getValue().toCharArray(); |
| | | } else if (bindPasswordFileArg.isPresent()) { |
| | | value = bindPasswordFileArg.getValue().toCharArray(); |
| | | } else if (password != null) { |
| | | return password; |
| | | } |
| | | |
| | | if (value.length == 0 && app.isInteractive()) { |
| | | LocalizableMessage msg; |
| | | if (isAdminConnection) { |
| | | msg = INFO_LDAPAUTH_PASSWORD_PROMPT.get(getBindName()); |
| | | } else { |
| | | msg = INFO_DESCRIPTION_BINDPASSWORD.get(); |
| | | } |
| | | try { |
| | | value = app.readPassword(msg); |
| | | app.println(); |
| | | } catch (ClientException e) { |
| | | throw new ArgumentException(ERR_ERROR_CANNOT_READ_PASSWORD.get(), e); |
| | | } |
| | | password = value; |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a <CODE>TrustManager</CODE> object that may be used for |
| | | * interactions requiring access to a trust manager. |
| | | * |
| | | * @return A set of <CODE>TrustManager</CODE> objects that may be used for |
| | | * interactions requiring access to a trust manager. |
| | | * @throws IOException |
| | | * If the trust store file could not be found or could not be read. |
| | | * @throws GeneralSecurityException |
| | | * If a problem occurs while interacting with the trust store. |
| | | */ |
| | | public TrustManager getTrustManager() throws IOException, GeneralSecurityException { |
| | | if (trustAllArg.isPresent()) { |
| | | return TrustManagers.trustAll(); |
| | | } |
| | | |
| | | X509TrustManager tm = null; |
| | | if (trustStorePathArg.isPresent() && trustStorePathArg.getValue().length() > 0) { |
| | | tm = TrustManagers.checkValidityDates(TrustManagers.checkHostName(hostNameArg.getValue(), |
| | | TrustManagers.checkUsingTrustStore(trustStorePathArg.getValue(), getTrustStorePIN(), null))); |
| | | } else if (getTrustStore() != null) { |
| | | tm = TrustManagers.checkValidityDates(TrustManagers.checkHostName(hostNameArg.getValue(), |
| | | TrustManagers.checkUsingTrustStore(getTrustStore(), getTrustStorePIN(), null))); |
| | | } |
| | | |
| | | if (app != null && !app.isQuiet()) { |
| | | return new PromptingTrustManager(app, tm); |
| | | } |
| | | |
| | | return tm; |
| | | } |
| | | |
| | | /** |
| | | * Read the TrustStore from the JSSE system property. |
| | | * |
| | | * @return The path to the trust store file. |
| | | */ |
| | | |
| | | private String getTrustStore() { |
| | | return System.getProperty("javax.net.ssl.trustStore"); |
| | | } |
| | | |
| | | /** |
| | | * Read the TrustStore PIN from the JSSE system property. |
| | | * |
| | | * @return The PIN that should be used to access the trust store, can be null. |
| | | */ |
| | | private char[] getTrustStorePIN() { |
| | | String pwd; |
| | | if (trustStorePasswordArg.isPresent()) { |
| | | pwd = trustStorePasswordArg.getValue(); |
| | | } else if (trustStorePasswordFileArg.isPresent()) { |
| | | pwd = trustStorePasswordFileArg.getValue(); |
| | | } else { |
| | | pwd = System.getProperty("javax.net.ssl.trustStorePassword"); |
| | | } |
| | | return pwd == null ? null : pwd.toCharArray(); |
| | | } |
| | | |
| | | private String parseSASLOptionValue(final String option) throws ArgumentException { |
| | | final int equalPos = option.indexOf('='); |
| | | if (equalPos == -1) { |
| | | throw new ArgumentException(ERR_LDAP_CONN_CANNOT_PARSE_SASL_OPTION.get(option)); |
| | | } |
| | | return option.substring(equalPos + 1, option.length()); |
| | | } |
| | | |
| | | /** |
| | | * Specifies if this connection should be an administrator connection. If sets as one, the messages prompted to the |
| | | * user will be different as a normal connection. E.g if set : |
| | | * |
| | | * <pre> |
| | | * >>>> Specify OpenDJ LDAP connection parameters |
| | | * |
| | | * Directory server administration port number [4444]: |
| | | * </pre> |
| | | * |
| | | * vs normal mode |
| | | * |
| | | * <pre> |
| | | * >>>> Specify OpenDJ LDAP connection parameters |
| | | * |
| | | * Directory server port number [1389]: |
| | | * </pre> |
| | | */ |
| | | public void setIsAnAdminConnection() { |
| | | isAdminConnection = true; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008-2009 Sun Microsystems, Inc. |
| | | * Portions copyright 2011-2016 ForgeRock AS. |
| | | * Portions copyright 2011 Nemanja Lukić |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | import static com.forgerock.opendj.cli.Utils.*; |
| | | import static com.forgerock.opendj.util.StaticUtils.*; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.Console; |
| | | import java.io.EOFException; |
| | | import java.io.IOError; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.InputStreamReader; |
| | | import java.io.PrintStream; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | |
| | | /** |
| | | * This class provides an abstract base class which can be used as the basis of a console-based application. |
| | | */ |
| | | public abstract class ConsoleApplication { |
| | | |
| | | private static final int PROGRESS_LINE = 70; |
| | | |
| | | private final BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); |
| | | private final InputStream in = System.in; |
| | | private final PrintStream out; |
| | | private final PrintStream err; |
| | | private final Console console = System.console(); |
| | | |
| | | private boolean isProgressSuite; |
| | | |
| | | /** Defines the different line styles for output. */ |
| | | public enum Style { |
| | | /** Defines a title. */ |
| | | TITLE, |
| | | /** Defines a subtitle. */ |
| | | SUBTITLE, |
| | | /** Defines a notice. */ |
| | | NOTICE, |
| | | /** Defines a normal line. */ |
| | | NORMAL, |
| | | /** Defines an error. */ |
| | | ERROR, |
| | | /** Defines a warning. */ |
| | | WARNING |
| | | } |
| | | |
| | | /** |
| | | * Creates a new console application instance. |
| | | */ |
| | | public ConsoleApplication() { |
| | | this(System.out, System.err); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new console application instance with provided standard and error out streams. |
| | | * |
| | | * @param out |
| | | * The output stream. |
| | | * @param err |
| | | * The error stream. |
| | | */ |
| | | public ConsoleApplication(PrintStream out, PrintStream err) { |
| | | this.out = out; |
| | | this.err = err; |
| | | } |
| | | |
| | | /** |
| | | * Returns the application error stream. |
| | | * |
| | | * @return The application error stream. |
| | | */ |
| | | public final PrintStream getErrorStream() { |
| | | return err; |
| | | } |
| | | |
| | | /** |
| | | * Returns the application input stream. |
| | | * |
| | | * @return The application input stream. |
| | | */ |
| | | public final InputStream getInputStream() { |
| | | return in; |
| | | } |
| | | |
| | | /** |
| | | * Returns the application output stream. |
| | | * |
| | | * @return The application output stream. |
| | | */ |
| | | public final PrintStream getOutputStream() { |
| | | return out; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the user has requested interactive behavior. The default implementation returns |
| | | * {@code true}. |
| | | * |
| | | * @return {@code true} if the user has requested interactive behavior. |
| | | */ |
| | | public boolean isInteractive() { |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the user has requested quiet output. The default implementation returns {@code false}. |
| | | * |
| | | * @return {@code true} if the user has requested quiet output. |
| | | */ |
| | | public boolean isQuiet() { |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the user has requested script-friendly output. The default implementation returns |
| | | * {@code false}. |
| | | * |
| | | * @return {@code true} if the user has requested script-friendly output. |
| | | */ |
| | | public boolean isScriptFriendly() { |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the user has requested verbose output. The default implementation returns {@code false}. |
| | | * |
| | | * @return {@code true} if the user has requested verbose output. |
| | | */ |
| | | public boolean isVerbose() { |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the user has requested advanced mode. |
| | | * |
| | | * @return Returns <code>true</code> if the user has requested advanced mode. |
| | | */ |
| | | public boolean isAdvancedMode() { |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not this console application is running in its menu-driven mode. This can be used to dictate |
| | | * whether output should go to the error stream or not. In addition, it may also dictate whether or not sub-menus |
| | | * should display a cancel option as well as a quit option. |
| | | * |
| | | * @return Returns <code>true</code> if this console application is running in its menu-driven mode. |
| | | */ |
| | | public boolean isMenuDrivenMode() { |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Interactively prompts the user to press return to continue. This method should be called in situations where a |
| | | * user needs to be given a chance to read some documentation before continuing (continuing may cause the |
| | | * documentation to be scrolled out of view). |
| | | */ |
| | | public final void pressReturnToContinue() { |
| | | try { |
| | | readLineOfInput(INFO_MENU_PROMPT_RETURN_TO_CONTINUE.get()); |
| | | } catch (final ClientException e) { |
| | | // Ignore the exception - applications don't care. |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Displays a message to the error stream. |
| | | * |
| | | * @param msg |
| | | * The message. |
| | | */ |
| | | public final void errPrint(final LocalizableMessage msg) { |
| | | getErrStream().print(wrap(msg)); |
| | | } |
| | | |
| | | /** |
| | | * Displays a blank line to the error stream. |
| | | */ |
| | | public final void errPrintln() { |
| | | getErrStream().println(); |
| | | } |
| | | |
| | | /** |
| | | * Displays a message to the error stream. |
| | | * |
| | | * @param msg |
| | | * The message. |
| | | */ |
| | | public final void errPrintln(final LocalizableMessage msg) { |
| | | getErrStream().println(wrap(msg)); |
| | | } |
| | | |
| | | /** |
| | | * Displays a message to the error stream indented by the specified number of columns. |
| | | * |
| | | * @param msg |
| | | * The message. |
| | | * @param indent |
| | | * The number of columns to indent. |
| | | */ |
| | | public final void errPrintln(final LocalizableMessage msg, final int indent) { |
| | | getErrStream().println(wrapText(msg, MAX_LINE_WIDTH, indent)); |
| | | } |
| | | |
| | | /** |
| | | * Displays a message to the error stream if verbose mode is enabled. |
| | | * |
| | | * @param msg |
| | | * The verbose message. |
| | | */ |
| | | public final void errPrintVerboseMessage(final LocalizableMessage msg) { |
| | | if (isVerbose()) { |
| | | getErrStream().println(wrap(msg)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Displays a message to the output stream. |
| | | * |
| | | * @param msg |
| | | * The message. |
| | | */ |
| | | public final void print(final LocalizableMessage msg) { |
| | | if (!isQuiet()) { |
| | | out.print(wrap(msg)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Displays a blank line to the output stream. |
| | | */ |
| | | public final void println() { |
| | | if (!isQuiet()) { |
| | | out.println(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Displays a message to the output stream. |
| | | * |
| | | * @param msg |
| | | * The message. |
| | | */ |
| | | public final void println(final LocalizableMessage msg) { |
| | | if (!isQuiet()) { |
| | | out.println(wrap(msg)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Displays a message to the output stream indented by the specified number of columns. |
| | | * |
| | | * @param msg |
| | | * The message. |
| | | * @param indent |
| | | * The number of columns to indent. |
| | | */ |
| | | public final void println(final LocalizableMessage msg, final int indent) { |
| | | if (!isQuiet()) { |
| | | out.println(wrapText(msg, MAX_LINE_WIDTH, indent)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Prints a progress bar on the same output stream line if not in quiet mode. |
| | | * |
| | | * <pre> |
| | | * Like |
| | | * msg...... 50% |
| | | * if progress is up to 100 : |
| | | * msg..................... 100% |
| | | * if progress is < 0 : |
| | | * msg.... FAIL |
| | | * msg..................... FAIL |
| | | * </pre> |
| | | * |
| | | * @param linePos |
| | | * The progress bar starts at this position on the line. |
| | | * @param progress |
| | | * The current percentage progress to print. |
| | | */ |
| | | private final void printProgressBar(final int linePos, final int progress) { |
| | | if (!isQuiet()) { |
| | | final int spacesLeft = MAX_LINE_WIDTH - linePos - 10; |
| | | StringBuilder bar = new StringBuilder(); |
| | | if (progress != 0) { |
| | | for (int i = 0; i < PROGRESS_LINE; i++) { |
| | | if (i < (Math.abs(progress) * spacesLeft) / 100 && bar.length() < spacesLeft) { |
| | | bar.append("."); |
| | | } |
| | | } |
| | | } |
| | | bar.append(". "); |
| | | if (progress >= 0) { |
| | | bar.append(progress).append("% "); |
| | | } else { |
| | | bar.append("FAIL"); |
| | | isProgressSuite = false; |
| | | } |
| | | final int endBuilder = linePos + bar.length(); |
| | | for (int i = 0; i < endBuilder; i++) { |
| | | bar.append("\b"); |
| | | } |
| | | if (progress >= 100 || progress < 0) { |
| | | bar.append(EOL); |
| | | isProgressSuite = false; |
| | | } |
| | | out.print(bar); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Prints a progress bar on the same output stream line if not in quiet mode. |
| | | * If the line's length is upper than the limit, the message is wrapped and the progress |
| | | * bar is affected to the last one. |
| | | * e.g. |
| | | * <pre> |
| | | * Changing matching rule for 'userCertificate' and 'caCertificate' to |
| | | * CertificateExactMatch............................................... 100% |
| | | * </pre> |
| | | * |
| | | * @param msg |
| | | * The message to display before the progress line. |
| | | * @param progress |
| | | * The current percentage progress to print. |
| | | * @param indent |
| | | * Indentation of the message. |
| | | */ |
| | | public final void printProgressBar(String msg, final int progress, final int indent) { |
| | | if (!isQuiet()) { |
| | | String msgToDisplay = wrapText(msg, PROGRESS_LINE, indent); |
| | | if (msgToDisplay.length() > PROGRESS_LINE) { |
| | | final String[] msgWrapped = msgToDisplay.split(LINE_SEPARATOR); |
| | | if (!isProgressSuite) { |
| | | for (int pos = 0; pos < msgWrapped.length - 1; pos++) { |
| | | println(LocalizableMessage.raw(msgWrapped[pos])); |
| | | } |
| | | isProgressSuite = true; |
| | | } |
| | | msgToDisplay = msgWrapped[msgWrapped.length - 1]; |
| | | } |
| | | print(LocalizableMessage.raw(msgToDisplay)); |
| | | printProgressBar(msgToDisplay.length(), progress); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Print a line with EOL in the output stream. |
| | | * |
| | | * @param msgStyle |
| | | * The type of formatted output desired. |
| | | * @param msg |
| | | * The message to display in normal mode. |
| | | * @param indent |
| | | * The indentation. |
| | | */ |
| | | public final void println(final Style msgStyle, final LocalizableMessage msg, final int indent) { |
| | | if (!isQuiet()) { |
| | | switch (msgStyle) { |
| | | case TITLE: |
| | | out.println(); |
| | | out.println(">>>> " + wrapText(msg, MAX_LINE_WIDTH, indent)); |
| | | out.println(); |
| | | break; |
| | | case SUBTITLE: |
| | | out.println(wrapText(msg, MAX_LINE_WIDTH, indent)); |
| | | out.println(); |
| | | break; |
| | | case NOTICE: |
| | | out.println(wrapText("* " + msg, MAX_LINE_WIDTH, indent)); |
| | | break; |
| | | case ERROR: |
| | | out.println(); |
| | | out.println(wrapText("** " + msg, MAX_LINE_WIDTH, indent)); |
| | | out.println(); |
| | | break; |
| | | case WARNING: |
| | | out.println(wrapText("[!] " + msg, MAX_LINE_WIDTH, indent)); |
| | | break; |
| | | default: |
| | | out.println(wrapText(msg, MAX_LINE_WIDTH, indent)); |
| | | break; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Displays a message to the output stream if verbose mode is enabled. |
| | | * |
| | | * @param msg |
| | | * The verbose message. |
| | | */ |
| | | public final void printVerboseMessage(final LocalizableMessage msg) { |
| | | if (isVerbose()) { |
| | | out.println(wrap(msg)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Interactively prompts (on error output) the user to provide a string value. Any non-empty string will be allowed |
| | | * (the empty string will indicate that the default should be used, if there is one). |
| | | * |
| | | * @param prompt |
| | | * The prompt to present to the user. |
| | | * @param defaultValue |
| | | * The default value to assume if the user presses ENTER without typing anything, or {@code null} if |
| | | * there should not be a default and the user must explicitly provide a value. |
| | | * @throws ClientException |
| | | * If the line of input could not be retrieved for some reason. |
| | | * @return The string value read from the user. |
| | | */ |
| | | public final String readInput(LocalizableMessage prompt, final String defaultValue) throws ClientException { |
| | | return readInput(prompt, defaultValue, null); |
| | | } |
| | | |
| | | /** |
| | | * Interactively prompts (on error output) the user to provide a string value. Any non-empty string will be allowed |
| | | * (the empty string will indicate that the default should be used, if there is one). |
| | | * |
| | | * @param prompt |
| | | * The prompt to present to the user. |
| | | * @param defaultValue |
| | | * The default value to assume if the user presses ENTER without typing anything, or {@code null} if |
| | | * there should not be a default and the user must explicitly provide a value. |
| | | * @param msgStyle |
| | | * The formatted style chosen. |
| | | * @throws ClientException |
| | | * If the line of input could not be retrieved for some reason. |
| | | * @return The string value read from the user. |
| | | */ |
| | | public final String readInput(LocalizableMessage prompt, final String defaultValue, final Style msgStyle) |
| | | throws ClientException { |
| | | if (msgStyle != null && msgStyle == Style.TITLE) { |
| | | println(); |
| | | } |
| | | while (true) { |
| | | if (defaultValue != null) { |
| | | prompt = INFO_PROMPT_SINGLE_DEFAULT.get(prompt, defaultValue); |
| | | } |
| | | final String response = readLineOfInput(prompt); |
| | | |
| | | if (msgStyle != null && (msgStyle == Style.TITLE || msgStyle == Style.SUBTITLE)) { |
| | | println(); |
| | | } |
| | | |
| | | if ("".equals(response)) { |
| | | if (defaultValue != null) { |
| | | return defaultValue; |
| | | } |
| | | println(INFO_ERROR_EMPTY_RESPONSE.get()); |
| | | } |
| | | return response; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Interactively reads a password from the console. |
| | | * |
| | | * @param prompt |
| | | * The password prompt. |
| | | * @return The password. |
| | | * @throws ClientException |
| | | * If the password could not be retrieved for some reason. |
| | | */ |
| | | public final char[] readPassword(final LocalizableMessage prompt) throws ClientException { |
| | | if (console != null) { |
| | | if (prompt != null) { |
| | | out.print(wrap(prompt)); |
| | | out.print(" "); |
| | | } |
| | | try { |
| | | final char[] password = console.readPassword(); |
| | | if (password == null) { |
| | | throw new EOFException("End of input"); |
| | | } |
| | | return password; |
| | | } catch (final Throwable e) { |
| | | throw ClientException.adaptInputException(e); |
| | | } |
| | | } else { |
| | | // FIXME: should go direct to char[] and avoid the String. |
| | | return readLineOfInput(prompt).toCharArray(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Reads a password from the console without echoing it to the client. |
| | | * FIXME This method should disappear when all |
| | | * the tools will extend to ConsoleApplication. |
| | | * |
| | | * @return The password as an array of characters. |
| | | * @throws ClientException |
| | | * If an error occurs when reading the password. |
| | | */ |
| | | public static char[] readPassword() throws ClientException { |
| | | try { |
| | | return System.console().readPassword(); |
| | | } catch (IOError e) { |
| | | throw ClientException.adaptInputException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Interactively retrieves a line of input from the console. |
| | | * |
| | | * @param prompt |
| | | * The prompt. |
| | | * @return The line of input. |
| | | * @throws ClientException |
| | | * If the line of input could not be retrieved for some reason. |
| | | */ |
| | | public final String readLineOfInput(final LocalizableMessage prompt) throws ClientException { |
| | | if (prompt != null) { |
| | | out.print(wrap(prompt)); |
| | | out.print(" "); |
| | | } |
| | | try { |
| | | final String s = reader.readLine(); |
| | | if (s == null) { |
| | | throw ClientException.adaptInputException(new EOFException("End of input")); |
| | | } |
| | | return s; |
| | | } catch (final IOException e) { |
| | | throw ClientException.adaptInputException(e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Interactively retrieves a port value from the console. |
| | | * |
| | | * @param prompt |
| | | * The port prompt. |
| | | * @param defaultValue |
| | | * The port default value. |
| | | * @return Returns the port. |
| | | * @throws ClientException |
| | | * If the port could not be retrieved for some reason. |
| | | */ |
| | | public final int readPort(LocalizableMessage prompt, final int defaultValue) throws ClientException { |
| | | if (defaultValue != -1) { |
| | | prompt = INFO_PROMPT_SINGLE_DEFAULT.get(prompt, defaultValue); |
| | | } |
| | | |
| | | return readValidatedInput(prompt, Utils.portValidationCallback(defaultValue), CONFIRMATION_MAX_TRIES); |
| | | } |
| | | |
| | | /** |
| | | * Interactively prompts for user input and continues until valid input is provided. |
| | | * |
| | | * @param <T> |
| | | * The type of decoded user input. |
| | | * @param prompt |
| | | * The interactive prompt which should be displayed on each input attempt. |
| | | * @param validator |
| | | * An input validator responsible for validating and decoding the user's response. |
| | | * @return Returns the decoded user's response. |
| | | * @throws ClientException |
| | | * If an unexpected error occurred which prevented validation. |
| | | */ |
| | | public final <T> T readValidatedInput(final LocalizableMessage prompt, final ValidationCallback<T> validator) |
| | | throws ClientException { |
| | | while (true) { |
| | | final String response = readLineOfInput(prompt); |
| | | final T value = validator.validate(this, response); |
| | | if (value != null) { |
| | | return value; |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Interactively prompts for user input and continues until valid input is provided. |
| | | * |
| | | * @param <T> |
| | | * The type of decoded user input. |
| | | * @param prompt |
| | | * The interactive prompt which should be displayed on each input attempt. |
| | | * @param validator |
| | | * An input validator responsible for validating and decoding the user's response. |
| | | * @param maxTries |
| | | * The maximum number of tries that we can make. |
| | | * @return Returns the decoded user's response. |
| | | * @throws ClientException |
| | | * If an unexpected error occurred which prevented validation or if the maximum number of tries was |
| | | * reached. |
| | | */ |
| | | public final <T> T readValidatedInput(final LocalizableMessage prompt, final ValidationCallback<T> validator, |
| | | final int maxTries) throws ClientException { |
| | | int nTries = 0; |
| | | while (nTries < maxTries) { |
| | | final String response = readLineOfInput(prompt); |
| | | final T value = validator.validate(this, response); |
| | | if (value != null) { |
| | | return value; |
| | | } |
| | | nTries++; |
| | | } |
| | | throw new ClientException(ReturnCode.ERROR_USER_DATA, ERR_TRIES_LIMIT_REACHED.get(maxTries)); |
| | | } |
| | | |
| | | /** |
| | | * Inserts line breaks into the provided buffer to wrap text at no more than the specified column width (80). |
| | | * |
| | | * @param msg |
| | | * The message to wrap. |
| | | * @return The wrapped message. |
| | | */ |
| | | private String wrap(final LocalizableMessage msg) { |
| | | return wrapText(msg, MAX_LINE_WIDTH); |
| | | } |
| | | |
| | | /** |
| | | * Returns the error stream. Effectively, when an application is in "interactive mode" all the informations should |
| | | * be written in the STDout. |
| | | * |
| | | * @return The error stream that should be used with this application. |
| | | */ |
| | | protected PrintStream getErrStream() { |
| | | if (isInteractive()) { |
| | | return out; |
| | | } |
| | | return err; |
| | | } |
| | | |
| | | /** |
| | | * Commodity method that interactively confirms whether a user wishes to perform an action. If |
| | | * the application is non-interactive, then the provided default is returned automatically. If there is an error an |
| | | * error message is logged to the provided Logger and the default value is returned. |
| | | * |
| | | * @param prompt |
| | | * The prompt describing the action. |
| | | * @param defaultValue |
| | | * The default value for the confirmation message. This will be returned if the application is |
| | | * non-interactive or if the user just presses return. |
| | | * @param logger |
| | | * the Logger to be used to log the error message. |
| | | * @return Returns <code>true</code> if the user wishes the action to be performed, or <code>false</code> if they |
| | | * refused. |
| | | * @throws ClientException |
| | | * if the user did not provide valid answer after a certain number of tries |
| | | * (ConsoleApplication.CONFIRMATION_MAX_TRIES) |
| | | */ |
| | | protected final boolean askConfirmation(LocalizableMessage prompt, boolean defaultValue, LocalizedLogger logger) |
| | | throws ClientException { |
| | | int nTries = 0; |
| | | while (nTries < CONFIRMATION_MAX_TRIES) { |
| | | nTries++; |
| | | try { |
| | | return confirmAction(prompt, defaultValue); |
| | | } catch (ClientException ce) { |
| | | if (ce.getMessageObject().toString().contains(ERR_CONFIRMATION_TRIES_LIMIT_REACHED.get(nTries))) { |
| | | throw ce; |
| | | } |
| | | logger.warn(LocalizableMessage.raw("Error reading input: " + ce, ce)); |
| | | // Try again... |
| | | println(); |
| | | } |
| | | } |
| | | |
| | | throw new ClientException(ReturnCode.ERROR_USER_DATA, |
| | | ERR_CONFIRMATION_TRIES_LIMIT_REACHED.get(CONFIRMATION_MAX_TRIES)); |
| | | } |
| | | |
| | | /** |
| | | * Interactively confirms whether a user wishes to perform an action. |
| | | * If the application is non-interactive, then the provided default is returned automatically. |
| | | * |
| | | * @param prompt |
| | | * The prompt describing the action. |
| | | * @param defaultValue |
| | | * The default value for the confirmation message. This will be returned if the application is |
| | | * non-interactive or if the user just presses return. |
| | | * @return Returns <code>true</code> if the user wishes the action to be performed, or <code>false</code> if they |
| | | * refused, or if an exception occurred. |
| | | * @throws ClientException |
| | | * If the user's response could not be read from the console for some reason. |
| | | */ |
| | | public final boolean confirmAction(LocalizableMessage prompt, final boolean defaultValue) throws ClientException { |
| | | if (!isInteractive()) { |
| | | return defaultValue; |
| | | } |
| | | |
| | | final LocalizableMessage yes = INFO_GENERAL_YES.get(); |
| | | final LocalizableMessage no = INFO_GENERAL_NO.get(); |
| | | final LocalizableMessage errMsg = ERR_CONSOLE_APP_CONFIRM.get(yes, no); |
| | | prompt = INFO_MENU_PROMPT_CONFIRM.get(prompt, yes, no, defaultValue ? yes : no); |
| | | |
| | | ValidationCallback<Boolean> validator = new ValidationCallback<Boolean>() { |
| | | |
| | | @Override |
| | | public Boolean validate(ConsoleApplication app, String input) { |
| | | String ninput = input.toLowerCase().trim(); |
| | | if (ninput.length() == 0) { |
| | | return defaultValue; |
| | | } else if (no.toString().toLowerCase().startsWith(ninput)) { |
| | | return false; |
| | | } else if (yes.toString().toLowerCase().startsWith(ninput)) { |
| | | return true; |
| | | } else { |
| | | // Try again... |
| | | app.println(); |
| | | app.println(errMsg); |
| | | app.println(); |
| | | return null; |
| | | } |
| | | } |
| | | }; |
| | | |
| | | return readValidatedInput(prompt, validator, CONFIRMATION_MAX_TRIES); |
| | | } |
| | | |
| | | /** |
| | | * Commodity method used to repeatedly ask the user to provide a port value. |
| | | * |
| | | * @param prompt |
| | | * the prompt message. |
| | | * @param defaultValue |
| | | * the default value of the port to be proposed to the user. |
| | | * @param logger |
| | | * the logger where the errors will be written. |
| | | * @return the port value provided by the user. |
| | | */ |
| | | protected int askPort(LocalizableMessage prompt, int defaultValue, LocalizedLogger logger) { |
| | | while (true) { |
| | | try { |
| | | int port = readPort(prompt, defaultValue); |
| | | if (port != -1) { |
| | | return port; |
| | | } |
| | | } catch (ClientException ce) { |
| | | logger.warn(LocalizableMessage.raw("Error reading input: " + ce, ce)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Prints a header in the console application. |
| | | * |
| | | * @param header |
| | | * The message to display as a header. |
| | | */ |
| | | void printHeader(final LocalizableMessage header) { |
| | | println(); |
| | | println(); |
| | | println(header); |
| | | println(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2015-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * Documentation that supplements generated descriptions. |
| | | */ |
| | | public interface DocDescriptionSupplement { |
| | | |
| | | /** |
| | | * Retrieves a supplement to the description intended for use in generated reference documentation. |
| | | * |
| | | * @return The supplement to the description for use in generated reference documentation, |
| | | * or LocalizableMessage.EMPTY if there is no supplement. |
| | | */ |
| | | LocalizableMessage getDocDescriptionSupplement(); |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2015 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import freemarker.template.Configuration; |
| | | import freemarker.template.Template; |
| | | import freemarker.template.TemplateExceptionHandler; |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.OutputStreamWriter; |
| | | import java.io.Writer; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * This class provides utility functions to help generate reference documentation. |
| | | */ |
| | | public final class DocGenerationHelper { |
| | | |
| | | /** Prevent instantiation. */ |
| | | private DocGenerationHelper() { |
| | | // Do nothing. |
| | | } |
| | | |
| | | /** FreeMarker template configuration. */ |
| | | private static Configuration configuration; |
| | | |
| | | /** |
| | | * Gets a FreeMarker configuration for applying templates. |
| | | * |
| | | * @return A FreeMarker configuration. |
| | | */ |
| | | private static Configuration getConfiguration() { |
| | | if (configuration == null) { |
| | | configuration = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS); |
| | | configuration.setClassForTemplateLoading(DocGenerationHelper.class, "/templates"); |
| | | configuration.setDefaultEncoding("UTF-8"); |
| | | configuration.setTemplateExceptionHandler(TemplateExceptionHandler.DEBUG_HANDLER); |
| | | } |
| | | return configuration; |
| | | } |
| | | |
| | | /** |
| | | * Appends the String result from applying a FreeMarker template. |
| | | * |
| | | * @param builder Append the result to this. |
| | | * @param template The name of a template file found in {@code resources/templates/}. |
| | | * @param map The map holding the data to use in the template. |
| | | */ |
| | | public static void applyTemplate(StringBuilder builder, final String template, final Map<String, Object> map) { |
| | | // FixMe: This method is public so it can be used by the SubCommandUsageHandler |
| | | // in org.forgerock.opendj.config.dsconfig.DSConfig. |
| | | |
| | | // FreeMarker requires a configuration to find the template. |
| | | configuration = getConfiguration(); |
| | | |
| | | // FreeMarker takes the data and a Writer to process the template. |
| | | try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); |
| | | Writer writer = new OutputStreamWriter(outputStream)) { |
| | | Template configurationTemplate = configuration.getTemplate(template); |
| | | configurationTemplate.process(map, writer); |
| | | builder.append(outputStream.toString()); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns an option synopsis. |
| | | * |
| | | * <br> |
| | | * |
| | | * Note: The synopsis might contain characters that must be escaped in XML. |
| | | * |
| | | * @param argument The argument option. |
| | | * @return A synopsis. |
| | | */ |
| | | static String getOptionSynopsis(final Argument argument) { |
| | | StringBuilder builder = new StringBuilder(); |
| | | |
| | | final Character shortID = argument.getShortIdentifier(); |
| | | if (shortID != null) { |
| | | builder.append("-").append(shortID.charValue()); |
| | | } |
| | | final String longID = argument.getLongIdentifier(); |
| | | if (shortID != null && longID != null) { |
| | | builder.append(" | "); |
| | | } |
| | | if (longID != null) { |
| | | builder.append("--").append(longID); |
| | | } |
| | | if (argument.needsValue()) { |
| | | builder.append(" ").append(argument.getValuePlaceholder()); |
| | | } |
| | | |
| | | return builder.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Returns true when the argument handles properties. |
| | | * |
| | | * @param argument The argument. |
| | | * @return True if the argument handles properties. |
| | | */ |
| | | public static boolean doesHandleProperties(final Argument argument) { |
| | | // FixMe: This method is public so it can be used by the SubCommandUsageHandler |
| | | // in org.forgerock.opendj.config.dsconfig.DSConfig. |
| | | |
| | | final String id = argument.getLongIdentifier(); |
| | | return ("add".equals(id) || "remove".equals(id) || "reset".equals(id) || "set".equals(id)); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | import static com.forgerock.opendj.util.StaticUtils.getExceptionMessage; |
| | | |
| | | import java.io.BufferedReader; |
| | | import java.io.File; |
| | | import java.io.FileNotFoundException; |
| | | import java.io.FileReader; |
| | | import java.io.IOException; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.Map; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | |
| | | /** |
| | | * This class defines an argument whose value will be read from a file rather |
| | | * than actually specified on the command-line. When a value is specified on the |
| | | * command line, it will be treated as the path to the file containing the |
| | | * actual value rather than the value itself. <BR> |
| | | * <BR> |
| | | * Note that if no filename is provided on the command line but a default |
| | | * value is specified programmatically or if the default value is read from a |
| | | * specified property, then that default value will be taken as the actual value |
| | | * rather than a filename. <BR> |
| | | * <BR> |
| | | * Also note that this argument type assumes that the entire value for the |
| | | * argument is on a single line in the specified file. If the file contains |
| | | * multiple lines, then only the first line will be read. |
| | | */ |
| | | public final class FileBasedArgument extends Argument { |
| | | |
| | | /** |
| | | * Returns a builder which can be used for incrementally constructing a new |
| | | * {@link FileBasedArgument}. |
| | | * |
| | | * @param longIdentifier |
| | | * The generic long identifier that will be used to refer to this argument. |
| | | * @return A builder to continue building the {@link FileBasedArgument}. |
| | | */ |
| | | public static Builder builder(final String longIdentifier) { |
| | | return new Builder(longIdentifier); |
| | | } |
| | | |
| | | /** A fluent API for incrementally constructing {@link FileBasedArgument}. */ |
| | | public static final class Builder extends ArgumentBuilder<Builder, String, FileBasedArgument> { |
| | | private Builder(final String longIdentifier) { |
| | | super(longIdentifier); |
| | | } |
| | | |
| | | @Override |
| | | Builder getThis() { |
| | | return this; |
| | | } |
| | | |
| | | @Override |
| | | public FileBasedArgument buildArgument() throws ArgumentException { |
| | | return new FileBasedArgument(this); |
| | | } |
| | | } |
| | | |
| | | /** The mapping between filenames specified and the first lines read from those files. */ |
| | | private final Map<String, String> namesToValues = new LinkedHashMap<>(); |
| | | |
| | | private FileBasedArgument(final Builder builder) throws ArgumentException { |
| | | super(builder); |
| | | } |
| | | |
| | | /** |
| | | * Adds a value to the set of values for this argument. This should only be |
| | | * called if the value is allowed by the <CODE>valueIsAcceptable</CODE> |
| | | * method. Note that in this case, correct behavior depends on a previous |
| | | * successful call to <CODE>valueIsAcceptable</CODE> so that the value read |
| | | * from the file may be stored in the name-to-value hash and used in place |
| | | * of the filename here. |
| | | * |
| | | * @param valueString |
| | | * The string representation of the value to add to this |
| | | * argument. |
| | | */ |
| | | @Override |
| | | public void addValue(final String valueString) { |
| | | final String actualValue = namesToValues.get(valueString); |
| | | if (actualValue != null) { |
| | | super.addValue(actualValue); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a map between the filenames specified on the command line and |
| | | * the first lines read from those files. |
| | | * |
| | | * @return A map between the filenames specified on the command line and the |
| | | * first lines read from those files. |
| | | */ |
| | | public Map<String, String> getNameToValueMap() { |
| | | return namesToValues; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether the provided value is acceptable for use in this |
| | | * argument. |
| | | * |
| | | * @param valueString |
| | | * The value for which to make the determination. |
| | | * @param invalidReason |
| | | * A buffer into which the invalid reason may be written if the |
| | | * value is not acceptable. |
| | | * @return <CODE>true</CODE> if the value is acceptable, or |
| | | * <CODE>false</CODE> if it is not. |
| | | */ |
| | | @Override |
| | | public boolean valueIsAcceptable(final String valueString, |
| | | final LocalizableMessageBuilder invalidReason) { |
| | | // First, make sure that the specified file exists. |
| | | File valueFile; |
| | | try { |
| | | valueFile = new File(valueString); |
| | | if (!valueFile.exists()) { |
| | | invalidReason.append(ERR_FILEARG_NO_SUCH_FILE.get(valueString, longIdentifier)); |
| | | return false; |
| | | } |
| | | } catch (final Exception e) { |
| | | invalidReason.append(ERR_FILEARG_CANNOT_VERIFY_FILE_EXISTENCE.get( |
| | | valueString, longIdentifier, getExceptionMessage(e))); |
| | | return false; |
| | | } |
| | | |
| | | // Open the file, read the first line and close the file. |
| | | String line; |
| | | try (BufferedReader reader = new BufferedReader(new FileReader(valueFile))) { |
| | | line = reader.readLine(); |
| | | } catch (final FileNotFoundException e) { |
| | | invalidReason.append(ERR_FILEARG_CANNOT_OPEN_FILE.get(valueString, longIdentifier, getExceptionMessage(e))); |
| | | return false; |
| | | } catch (final IOException e) { |
| | | invalidReason.append(ERR_FILEARG_CANNOT_READ_FILE.get(valueString, longIdentifier, getExceptionMessage(e))); |
| | | return false; |
| | | } |
| | | |
| | | // If the line read is null, then that means the file was empty. |
| | | if (line == null) { |
| | | invalidReason.append(ERR_FILEARG_EMPTY_FILE.get(valueString, longIdentifier)); |
| | | return false; |
| | | } |
| | | |
| | | // Store the value in the hash so it will be available for addValue. |
| | | // We won't do any validation on the value itself, so anything that we |
| | | // read will be considered acceptable. |
| | | namesToValues.put(valueString, line); |
| | | return true; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | /** |
| | | * An interface for displaying help interactively. |
| | | */ |
| | | public interface HelpCallback { |
| | | |
| | | /** |
| | | * Displays help to the provided application console. |
| | | * |
| | | * @param app |
| | | * The console application. |
| | | */ |
| | | void display(ConsoleApplication app); |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | |
| | | /** |
| | | * This class defines an argument type that will only accept integer values, and |
| | | * potentially only those in a given range. |
| | | */ |
| | | public final class IntegerArgument extends Argument { |
| | | |
| | | /** |
| | | * Returns a builder which can be used for incrementally constructing a new |
| | | * {@link IntegerArgument}. |
| | | * |
| | | * @param name |
| | | * The generic name that will be used to refer to this argument. |
| | | * @return A builder to continue building the {@link IntegerArgument}. |
| | | */ |
| | | public static Builder builder(final String name) { |
| | | return new Builder(name); |
| | | } |
| | | |
| | | /** A fluent API for incrementally constructing {@link IntegerArgument}. */ |
| | | public static final class Builder extends ArgumentBuilder<Builder, Integer, IntegerArgument> { |
| | | private int lowerBound = Integer.MIN_VALUE; |
| | | private int upperBound = Integer.MAX_VALUE; |
| | | |
| | | private Builder(final String name) { |
| | | super(name); |
| | | } |
| | | |
| | | @Override |
| | | Builder getThis() { |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Sets the lower bound of this {@link IntegerArgument}. |
| | | * |
| | | * @param lowerBound |
| | | * The lower bound value. |
| | | * @return This builder. |
| | | */ |
| | | public Builder lowerBound(final int lowerBound) { |
| | | this.lowerBound = lowerBound; |
| | | return getThis(); |
| | | } |
| | | |
| | | /** |
| | | * Sets the range of this {@link IntegerArgument}. |
| | | * |
| | | * @param lowerBound |
| | | * The range lower bound value. |
| | | * @param upperBound |
| | | * The range upper bound value. |
| | | * @return This builder. |
| | | */ |
| | | public Builder range(final int lowerBound, final int upperBound) { |
| | | this.lowerBound = lowerBound; |
| | | this.upperBound = upperBound; |
| | | return getThis(); |
| | | } |
| | | |
| | | @Override |
| | | public IntegerArgument buildArgument() throws ArgumentException { |
| | | return new IntegerArgument(this, lowerBound, upperBound); |
| | | } |
| | | } |
| | | |
| | | /** The lower bound that will be enforced for this argument. */ |
| | | private final int lowerBound; |
| | | /** The upper bound that will be enforced for this argument. */ |
| | | private final int upperBound; |
| | | |
| | | private IntegerArgument(final Builder builder, final int lowerBound, final int upperBound) |
| | | throws ArgumentException { |
| | | super(builder); |
| | | this.lowerBound = lowerBound; |
| | | this.upperBound = upperBound; |
| | | |
| | | if (lowerBound > upperBound) { |
| | | final LocalizableMessage message = |
| | | ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND.get(builder.longIdentifier, lowerBound, upperBound); |
| | | throw new ArgumentException(message); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether the provided value is acceptable for use in this |
| | | * argument. |
| | | * |
| | | * @param valueString |
| | | * The value for which to make the determination. |
| | | * @param invalidReason |
| | | * A buffer into which the invalid reason may be written if the |
| | | * value is not acceptable. |
| | | * @return <CODE>true</CODE> if the value is acceptable, or |
| | | * <CODE>false</CODE> if it is not. |
| | | */ |
| | | @Override |
| | | public boolean valueIsAcceptable(final String valueString, final LocalizableMessageBuilder invalidReason) { |
| | | try { |
| | | final int intValue = Integer.parseInt(valueString); |
| | | if (intValue < lowerBound) { |
| | | invalidReason.append(ERR_INTARG_VALUE_BELOW_LOWER_BOUND.get(longIdentifier, intValue, lowerBound)); |
| | | return false; |
| | | } |
| | | |
| | | if (intValue > upperBound) { |
| | | invalidReason.append(ERR_INTARG_VALUE_ABOVE_UPPER_BOUND.get(longIdentifier, intValue, upperBound)); |
| | | return false; |
| | | } |
| | | |
| | | return true; |
| | | } catch (final NumberFormatException e) { |
| | | invalidReason.append(ERR_ARG_CANNOT_DECODE_AS_INT.get(valueString, longIdentifier)); |
| | | return false; |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | /** |
| | | * An interactive console-based menu. |
| | | * |
| | | * @param <T> |
| | | * The type of success result value(s) returned by the |
| | | * call-back. Use <code>Void</code> if the call-backs do |
| | | * not return any values. |
| | | */ |
| | | public interface Menu<T> { |
| | | |
| | | /** |
| | | * Displays the menu and waits for the user to select a valid option. When the user selects an option, the call-back |
| | | * associated with the option will be invoked and its result returned. |
| | | * |
| | | * @return Returns the result of invoking the chosen menu call-back. |
| | | * @throws ClientException |
| | | * If an I/O exception occurred or if one of the menu option call-backs failed for some reason. |
| | | */ |
| | | MenuResult<T> run() throws ClientException; |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2007-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Collection; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * An interface for incrementally building a command-line menu. |
| | | * |
| | | * @param <T> |
| | | * The type of value returned by the call-backs. Use <code>Void</code> if the call-backs do not return a |
| | | * value. |
| | | */ |
| | | public final class MenuBuilder<T> { |
| | | |
| | | /** |
| | | * A simple menu option call-back which is a composite of zero or more underlying call-backs. |
| | | * |
| | | * @param <T> |
| | | * The type of value returned by the call-back. |
| | | */ |
| | | private static final class CompositeCallback<T> implements MenuCallback<T> { |
| | | |
| | | /** The list of underlying call-backs. */ |
| | | private final Collection<MenuCallback<T>> callbacks; |
| | | |
| | | /** |
| | | * Creates a new composite call-back with the specified set of call-backs. |
| | | * |
| | | * @param callbacks |
| | | * The set of call-backs. |
| | | */ |
| | | public CompositeCallback(Collection<MenuCallback<T>> callbacks) { |
| | | this.callbacks = callbacks; |
| | | } |
| | | |
| | | @Override |
| | | public MenuResult<T> invoke(ConsoleApplication app) throws ClientException { |
| | | List<T> values = new ArrayList<>(); |
| | | for (MenuCallback<T> callback : callbacks) { |
| | | MenuResult<T> result = callback.invoke(app); |
| | | if (!result.isSuccess()) { |
| | | // Throw away all the other results. |
| | | return result; |
| | | } |
| | | values.addAll(result.getValues()); |
| | | } |
| | | return MenuResult.success(values); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Underlying menu implementation generated by this menu builder. |
| | | * |
| | | * @param <T> |
| | | * The type of value returned by the call-backs. Use <code>Void</code> if the call-backs do not return a |
| | | * value. |
| | | */ |
| | | private static final class MenuImpl<T> implements Menu<T> { |
| | | |
| | | /** Indicates whether the menu will allow selection of multiple numeric options. */ |
| | | private final boolean allowMultiSelect; |
| | | |
| | | /** The application console. */ |
| | | private final ConsoleApplication app; |
| | | |
| | | /** The call-back lookup table. */ |
| | | private final Map<String, MenuCallback<T>> callbacks; |
| | | |
| | | /** The char options table builder. */ |
| | | private final TableBuilder cbuilder; |
| | | |
| | | /** The call-back for the optional default action. */ |
| | | private final MenuCallback<T> defaultCallback; |
| | | /** The description of the optional default action. */ |
| | | private final LocalizableMessage defaultDescription; |
| | | |
| | | /** The numeric options table builder. */ |
| | | private final TableBuilder nbuilder; |
| | | |
| | | /** The table printer. */ |
| | | private final TablePrinter printer; |
| | | |
| | | /** The menu prompt. */ |
| | | private final LocalizableMessage prompt; |
| | | |
| | | /** The menu title. */ |
| | | private final LocalizableMessage title; |
| | | |
| | | /** |
| | | * The maximum number of times we display the menu if the user provides |
| | | * bad input (-1 for unlimited). |
| | | */ |
| | | private int nMaxTries; |
| | | |
| | | /** Private constructor. */ |
| | | private MenuImpl(ConsoleApplication app, LocalizableMessage title, LocalizableMessage prompt, |
| | | TableBuilder ntable, TableBuilder ctable, TablePrinter printer, Map<String, MenuCallback<T>> callbacks, |
| | | boolean allowMultiSelect, MenuCallback<T> defaultCallback, LocalizableMessage defaultDescription, |
| | | int nMaxTries) { |
| | | this.app = app; |
| | | this.title = title; |
| | | this.prompt = prompt; |
| | | this.nbuilder = ntable; |
| | | this.cbuilder = ctable; |
| | | this.printer = printer; |
| | | this.callbacks = callbacks; |
| | | this.allowMultiSelect = allowMultiSelect; |
| | | this.defaultCallback = defaultCallback; |
| | | this.defaultDescription = defaultDescription; |
| | | this.nMaxTries = nMaxTries; |
| | | } |
| | | |
| | | @Override |
| | | public MenuResult<T> run() throws ClientException { |
| | | // The validation call-back which will be used to determine the |
| | | // action call-back. |
| | | ValidationCallback<MenuCallback<T>> validator = new ValidationCallback<MenuCallback<T>>() { |
| | | |
| | | @Override |
| | | public MenuCallback<T> validate(ConsoleApplication app, String input) { |
| | | String ninput = input.trim(); |
| | | |
| | | if (ninput.length() == 0) { |
| | | if (defaultCallback != null) { |
| | | return defaultCallback; |
| | | } else if (allowMultiSelect) { |
| | | app.println(); |
| | | app.println(ERR_MENU_BAD_CHOICE_MULTI.get()); |
| | | app.println(); |
| | | return null; |
| | | } else { |
| | | app.println(); |
| | | app.println(ERR_MENU_BAD_CHOICE_SINGLE.get()); |
| | | app.println(); |
| | | return null; |
| | | } |
| | | } else if (allowMultiSelect) { |
| | | // Use a composite call-back to collect all the results. |
| | | List<MenuCallback<T>> cl = new ArrayList<>(); |
| | | for (String value : ninput.split(",")) { |
| | | // Make sure that there are no duplicates. |
| | | String nvalue = value.trim(); |
| | | Set<String> choices = new HashSet<>(); |
| | | |
| | | if (choices.contains(nvalue)) { |
| | | app.println(); |
| | | app.println(ERR_MENU_BAD_CHOICE_MULTI_DUPE.get(value)); |
| | | app.println(); |
| | | return null; |
| | | } else if (!callbacks.containsKey(nvalue)) { |
| | | app.println(); |
| | | app.println(ERR_MENU_BAD_CHOICE_MULTI.get()); |
| | | app.println(); |
| | | return null; |
| | | } else { |
| | | cl.add(callbacks.get(nvalue)); |
| | | choices.add(nvalue); |
| | | } |
| | | } |
| | | |
| | | return new CompositeCallback<>(cl); |
| | | } else if (!callbacks.containsKey(ninput)) { |
| | | app.println(); |
| | | app.println(ERR_MENU_BAD_CHOICE_SINGLE.get()); |
| | | app.println(); |
| | | return null; |
| | | } else { |
| | | return callbacks.get(ninput); |
| | | } |
| | | } |
| | | }; |
| | | |
| | | // Determine the correct choice prompt. |
| | | LocalizableMessage promptMsg; |
| | | if (allowMultiSelect) { |
| | | if (defaultDescription != null) { |
| | | promptMsg = INFO_MENU_PROMPT_MULTI_DEFAULT.get(defaultDescription); |
| | | } else { |
| | | promptMsg = INFO_MENU_PROMPT_MULTI.get(); |
| | | } |
| | | } else { |
| | | if (defaultDescription != null) { |
| | | promptMsg = INFO_MENU_PROMPT_SINGLE_DEFAULT.get(defaultDescription); |
| | | } else { |
| | | promptMsg = INFO_MENU_PROMPT_SINGLE.get(); |
| | | } |
| | | } |
| | | |
| | | // If the user selects help then we need to loop around and |
| | | // display the menu again. |
| | | while (true) { |
| | | // Display the menu. |
| | | if (title != null) { |
| | | app.println(title); |
| | | app.println(); |
| | | } |
| | | |
| | | if (prompt != null) { |
| | | app.println(prompt); |
| | | app.println(); |
| | | } |
| | | |
| | | if (nbuilder.getTableHeight() > 0) { |
| | | nbuilder.print(printer); |
| | | app.println(); |
| | | } |
| | | |
| | | if (cbuilder.getTableHeight() > 0) { |
| | | TextTablePrinter cprinter = new TextTablePrinter(app.getErrorStream()); |
| | | cprinter.setDisplayHeadings(false); |
| | | int sz = String.valueOf(nbuilder.getTableHeight()).length() + 1; |
| | | cprinter.setIndentWidth(4); |
| | | cprinter.setColumnWidth(0, sz); |
| | | cprinter.setColumnWidth(1, 0); |
| | | cbuilder.print(cprinter); |
| | | app.println(); |
| | | } |
| | | |
| | | // Get the user's choice. |
| | | MenuCallback<T> choice; |
| | | if (nMaxTries != -1) { |
| | | choice = app.readValidatedInput(promptMsg, validator, nMaxTries); |
| | | } else { |
| | | choice = app.readValidatedInput(promptMsg, validator); |
| | | } |
| | | |
| | | // Invoke the user's selected choice. |
| | | MenuResult<T> result = choice.invoke(app); |
| | | |
| | | // Determine if the help needs to be displayed, display it and start again. |
| | | if (!result.isAgain()) { |
| | | return result; |
| | | } |
| | | app.println(); |
| | | app.println(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * A simple menu option call-back which does nothing but return the provided menu result. |
| | | * |
| | | * @param <T> |
| | | * The type of result returned by the call-back. |
| | | */ |
| | | private static final class ResultCallback<T> implements MenuCallback<T> { |
| | | |
| | | /** The result to be returned by this call-back. */ |
| | | private final MenuResult<T> result; |
| | | |
| | | /** Private constructor. */ |
| | | private ResultCallback(MenuResult<T> result) { |
| | | this.result = result; |
| | | } |
| | | |
| | | @Override |
| | | public MenuResult<T> invoke(ConsoleApplication app) throws ClientException { |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return getClass().getSimpleName() + "(result=" + result + ")"; |
| | | } |
| | | } |
| | | |
| | | /** The multiple column display threshold. */ |
| | | private int threshold = -1; |
| | | |
| | | /** Indicates whether the menu will allow selection of multiple numeric options. */ |
| | | private boolean allowMultiSelect; |
| | | |
| | | /** The application console. */ |
| | | private final ConsoleApplication app; |
| | | |
| | | /** The char option call-backs. */ |
| | | private final List<MenuCallback<T>> charCallbacks = new ArrayList<>(); |
| | | |
| | | /** The char option keys (must be single-character messages). */ |
| | | private final List<LocalizableMessage> charKeys = new ArrayList<>(); |
| | | /** The synopsis of char options. */ |
| | | private final List<LocalizableMessage> charSynopsis = new ArrayList<>(); |
| | | |
| | | /** Optional column headings. */ |
| | | private final List<LocalizableMessage> columnHeadings = new ArrayList<>(); |
| | | /** Optional column widths. */ |
| | | private final List<Integer> columnWidths = new ArrayList<>(); |
| | | |
| | | /** The call-back for the optional default action. */ |
| | | private MenuCallback<T> defaultCallback; |
| | | /** The description of the optional default action. */ |
| | | private LocalizableMessage defaultDescription; |
| | | |
| | | /** The numeric option call-backs. */ |
| | | private final List<MenuCallback<T>> numericCallbacks = new ArrayList<>(); |
| | | /** The numeric option fields. */ |
| | | private final List<List<LocalizableMessage>> numericFields = new ArrayList<>(); |
| | | |
| | | /** The menu title. */ |
| | | private LocalizableMessage title; |
| | | /** The menu prompt. */ |
| | | private LocalizableMessage prompt; |
| | | |
| | | /** |
| | | * The maximum number of times that we allow the user to provide an invalid |
| | | * answer (-1 if unlimited). |
| | | */ |
| | | private int nMaxTries = -1; |
| | | |
| | | /** |
| | | * Creates a new menu. |
| | | * |
| | | * @param app |
| | | * The application console. |
| | | */ |
| | | public MenuBuilder(ConsoleApplication app) { |
| | | this.app = app; |
| | | } |
| | | |
| | | /** |
| | | * Creates a "back" menu option. When invoked, this option will return a {@code MenuResult.cancel()} result. |
| | | * |
| | | * @param isDefault |
| | | * Indicates whether this option should be made the menu default. |
| | | */ |
| | | public void addBackOption(boolean isDefault) { |
| | | addCharOption(INFO_MENU_OPTION_BACK_KEY.get(), INFO_MENU_OPTION_BACK.get(), MenuResult.<T> cancel()); |
| | | |
| | | if (isDefault) { |
| | | setDefault(INFO_MENU_OPTION_BACK_KEY.get(), MenuResult.<T> cancel()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Creates a "cancel" menu option. When invoked, this option will return a {@code MenuResult.cancel()} result. |
| | | * |
| | | * @param isDefault |
| | | * Indicates whether this option should be made the menu default. |
| | | */ |
| | | public void addCancelOption(boolean isDefault) { |
| | | addCharOption(INFO_MENU_OPTION_CANCEL_KEY.get(), INFO_MENU_OPTION_CANCEL.get(), MenuResult.<T> cancel()); |
| | | |
| | | if (isDefault) { |
| | | setDefault(INFO_MENU_OPTION_CANCEL_KEY.get(), MenuResult.<T> cancel()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Adds a menu choice to the menu which will have a single letter as its key. |
| | | * |
| | | * @param c |
| | | * The single-letter message which will be used as the key for this option. |
| | | * @param description |
| | | * The menu option description. |
| | | * @param callback |
| | | * The call-back associated with this option. |
| | | */ |
| | | public void addCharOption(LocalizableMessage c, LocalizableMessage description, MenuCallback<T> callback) { |
| | | charKeys.add(c); |
| | | charSynopsis.add(description); |
| | | charCallbacks.add(callback); |
| | | } |
| | | |
| | | /** |
| | | * Adds a menu choice to the menu which will have a single letter as its key and which returns the provided result. |
| | | * |
| | | * @param c |
| | | * The single-letter message which will be used as the key for this option. |
| | | * @param description |
| | | * The menu option description. |
| | | * @param result |
| | | * The menu result which should be returned by this menu choice. |
| | | */ |
| | | public void addCharOption(LocalizableMessage c, LocalizableMessage description, MenuResult<T> result) { |
| | | addCharOption(c, description, new ResultCallback<T>(result)); |
| | | } |
| | | |
| | | /** |
| | | * Creates a "help" menu option which will use the provided help call-back to display help relating to the other |
| | | * menu options. When the help menu option is selected help will be displayed and then the user will be shown the |
| | | * menu again and prompted to enter a choice. |
| | | * |
| | | * @param callback |
| | | * The help call-back. |
| | | */ |
| | | public void addHelpOption(final HelpCallback callback) { |
| | | MenuCallback<T> wrapper = new MenuCallback<T>() { |
| | | |
| | | @Override |
| | | public MenuResult<T> invoke(ConsoleApplication app) throws ClientException { |
| | | app.println(); |
| | | callback.display(app); |
| | | return MenuResult.again(); |
| | | } |
| | | |
| | | }; |
| | | |
| | | addCharOption(INFO_MENU_OPTION_HELP_KEY.get(), INFO_MENU_OPTION_HELP.get(), wrapper); |
| | | } |
| | | |
| | | /** |
| | | * Adds a menu choice to the menu which will have a numeric key. |
| | | * |
| | | * @param description |
| | | * The menu option description. |
| | | * @param callback |
| | | * The call-back associated with this option. |
| | | * @param extraFields |
| | | * Any additional fields associated with this menu option. |
| | | * @return Returns the number associated with menu choice. |
| | | */ |
| | | public int addNumberedOption(LocalizableMessage description, MenuCallback<T> callback, |
| | | LocalizableMessage... extraFields) { |
| | | List<LocalizableMessage> fields = new ArrayList<>(); |
| | | fields.add(description); |
| | | if (extraFields != null) { |
| | | fields.addAll(Arrays.asList(extraFields)); |
| | | } |
| | | |
| | | numericFields.add(fields); |
| | | numericCallbacks.add(callback); |
| | | |
| | | return numericCallbacks.size(); |
| | | } |
| | | |
| | | /** |
| | | * Adds a menu choice to the menu which will have a numeric key and which returns the provided result. |
| | | * |
| | | * @param description |
| | | * The menu option description. |
| | | * @param result |
| | | * The menu result which should be returned by this menu choice. |
| | | * @param extraFields |
| | | * Any additional fields associated with this menu option. |
| | | * @return Returns the number associated with menu choice. |
| | | */ |
| | | public int addNumberedOption(LocalizableMessage description, MenuResult<T> result, |
| | | LocalizableMessage... extraFields) { |
| | | return addNumberedOption(description, new ResultCallback<T>(result), extraFields); |
| | | } |
| | | |
| | | /** |
| | | * Creates a "quit" menu option. When invoked, this option will return a {@code MenuResult.quit()} result. |
| | | */ |
| | | public void addQuitOption() { |
| | | addCharOption(INFO_MENU_OPTION_QUIT_KEY.get(), INFO_MENU_OPTION_QUIT.get(), MenuResult.<T> quit()); |
| | | } |
| | | |
| | | /** |
| | | * Sets the flag which indicates whether or not the menu will permit multiple numeric options to be selected at |
| | | * once. Users specify multiple choices by separating them with a comma. The default is <code>false</code>. |
| | | * |
| | | * @param allowMultiSelect |
| | | * Indicates whether or not the menu will permit multiple numeric options to be selected at once. |
| | | */ |
| | | public void setAllowMultiSelect(boolean allowMultiSelect) { |
| | | this.allowMultiSelect = allowMultiSelect; |
| | | } |
| | | |
| | | /** |
| | | * Sets the optional column headings. The column headings will be displayed above the menu options. |
| | | * |
| | | * @param headings |
| | | * The optional column headings. |
| | | */ |
| | | public void setColumnHeadings(LocalizableMessage... headings) { |
| | | this.columnHeadings.clear(); |
| | | if (headings != null) { |
| | | this.columnHeadings.addAll(Arrays.asList(headings)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Sets the optional column widths. A value of zero indicates that the column should be expandable, a value of |
| | | * <code>null</code> indicates that the column should use its default width. |
| | | * |
| | | * @param widths |
| | | * The optional column widths. |
| | | */ |
| | | public void setColumnWidths(Integer... widths) { |
| | | this.columnWidths.clear(); |
| | | if (widths != null) { |
| | | this.columnWidths.addAll(Arrays.asList(widths)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Sets the optional default action for this menu. The default action call-back will be invoked if the user does not |
| | | * specify an option and just presses enter. |
| | | * |
| | | * @param description |
| | | * A short description of the default action. |
| | | * @param callback |
| | | * The call-back associated with the default action. |
| | | */ |
| | | public void setDefault(LocalizableMessage description, MenuCallback<T> callback) { |
| | | defaultCallback = callback; |
| | | defaultDescription = description; |
| | | } |
| | | |
| | | /** |
| | | * Sets the optional default action for this menu. The default action call-back will be invoked if the user does not |
| | | * specify an option and just presses enter. |
| | | * |
| | | * @param description |
| | | * A short description of the default action. |
| | | * @param result |
| | | * The menu result which should be returned by default. |
| | | */ |
| | | public void setDefault(LocalizableMessage description, MenuResult<T> result) { |
| | | setDefault(description, new ResultCallback<T>(result)); |
| | | } |
| | | |
| | | /** |
| | | * Sets the number of numeric options required to trigger multiple-column display. A negative value (the default) |
| | | * indicates that the numeric options will always be displayed in a single column. A value of 0 indicates that |
| | | * numeric options will always be displayed in multiple columns. |
| | | * |
| | | * @param threshold |
| | | * The number of numeric options required to trigger multiple-column display. |
| | | */ |
| | | public void setMultipleColumnThreshold(int threshold) { |
| | | this.threshold = threshold; |
| | | } |
| | | |
| | | /** |
| | | * Sets the optional menu prompt. The prompt will be displayed above the menu. Menus do not have a prompt by |
| | | * default. |
| | | * |
| | | * @param prompt |
| | | * The menu prompt, or <code>null</code> if there is not prompt. |
| | | */ |
| | | public void setPrompt(LocalizableMessage prompt) { |
| | | this.prompt = prompt; |
| | | } |
| | | |
| | | /** |
| | | * Sets the optional menu title. The title will be displayed above the menu prompt. Menus do not have a title by |
| | | * default. |
| | | * |
| | | * @param title |
| | | * The menu title, or <code>null</code> if there is not title. |
| | | */ |
| | | public void setTitle(LocalizableMessage title) { |
| | | this.title = title; |
| | | } |
| | | |
| | | /** |
| | | * Creates a menu from this menu builder. |
| | | * |
| | | * @return Returns the new menu. |
| | | */ |
| | | public Menu<T> toMenu() { |
| | | TableBuilder nbuilder = new TableBuilder(); |
| | | Map<String, MenuCallback<T>> callbacks = new HashMap<>(); |
| | | |
| | | // Determine whether multiple columns should be used for numeric options |
| | | boolean useMultipleColumns = threshold >= 0 && numericCallbacks.size() >= threshold; |
| | | |
| | | // Create optional column headers. |
| | | if (!columnHeadings.isEmpty()) { |
| | | appendHeadings(nbuilder); |
| | | |
| | | if (useMultipleColumns) { |
| | | appendHeadings(nbuilder); |
| | | } |
| | | } |
| | | |
| | | // Add the numeric options first. |
| | | int sz = numericCallbacks.size(); |
| | | int rows = sz; |
| | | |
| | | if (useMultipleColumns) { |
| | | // Display in two columns the first column should contain half |
| | | // the options. If there are an odd number of columns then the |
| | | // first column should contain an additional option (e.g. if |
| | | // there are 23 options, the first column should contain 12 |
| | | // options and the second column 11 options). |
| | | rows /= 2; |
| | | rows += sz % 2; |
| | | } |
| | | |
| | | for (int i = 0, j = rows; i < rows; i++, j++) { |
| | | nbuilder.startRow(); |
| | | appendCells(nbuilder, i); |
| | | |
| | | callbacks.put(String.valueOf(i + 1), numericCallbacks.get(i)); |
| | | |
| | | // Second column. |
| | | if (useMultipleColumns && j < sz) { |
| | | appendCells(nbuilder, j); |
| | | |
| | | callbacks.put(String.valueOf(j + 1), numericCallbacks.get(j)); |
| | | } |
| | | } |
| | | |
| | | // Add the char options last. |
| | | TableBuilder cbuilder = new TableBuilder(); |
| | | for (int i = 0; i < charCallbacks.size(); i++) { |
| | | char c = charKeys.get(i).charAt(0); |
| | | LocalizableMessage option = INFO_MENU_CHAR_OPTION.get(c); |
| | | |
| | | cbuilder.startRow(); |
| | | cbuilder.appendCell(option); |
| | | cbuilder.appendCell(charSynopsis.get(i)); |
| | | |
| | | callbacks.put(String.valueOf(c), charCallbacks.get(i)); |
| | | } |
| | | |
| | | // Configure the table printer. |
| | | TextTablePrinter printer = new TextTablePrinter(app.getErrorStream()); |
| | | |
| | | boolean hasHeadings = !columnHeadings.isEmpty(); |
| | | printer.setDisplayHeadings(hasHeadings); |
| | | if (hasHeadings) { |
| | | printer.setHeadingSeparatorStartColumn(1); |
| | | } |
| | | |
| | | printer.setIndentWidth(4); |
| | | if (columnWidths.isEmpty()) { |
| | | printer.setColumnWidth(1, 0); |
| | | if (useMultipleColumns) { |
| | | printer.setColumnWidth(3, 0); |
| | | } |
| | | } else { |
| | | for (int i = 0; i < columnWidths.size(); i++) { |
| | | Integer j = columnWidths.get(i); |
| | | if (j != null) { |
| | | // Skip the option key column. |
| | | printer.setColumnWidth(i + 1, j); |
| | | |
| | | if (useMultipleColumns) { |
| | | printer.setColumnWidth(i + 2 + columnWidths.size(), j); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | return new MenuImpl<>(app, title, prompt, nbuilder, cbuilder, printer, callbacks, allowMultiSelect, |
| | | defaultCallback, defaultDescription, nMaxTries); |
| | | } |
| | | |
| | | private void appendCells(TableBuilder nbuilder, int i) { |
| | | nbuilder.appendCell(INFO_MENU_NUMERIC_OPTION.get(i + 1)); |
| | | for (LocalizableMessage field : numericFields.get(i)) { |
| | | if (field != null) { |
| | | nbuilder.appendCell(field); |
| | | } else { |
| | | nbuilder.appendCell(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private void appendHeadings(TableBuilder nbuilder) { |
| | | nbuilder.appendHeading(); |
| | | for (LocalizableMessage heading : columnHeadings) { |
| | | if (heading != null) { |
| | | nbuilder.appendHeading(heading); |
| | | } else { |
| | | nbuilder.appendHeading(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Sets the maximum number of tries that the user can provide an invalid value in the menu. -1 for unlimited tries |
| | | * (the default). If this limit is reached a ClientException will be thrown. |
| | | * |
| | | * @param nTries |
| | | * the maximum number of tries. |
| | | */ |
| | | public void setMaxTries(int nTries) { |
| | | nMaxTries = nTries; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems |
| | | * Portions Copyright 2014 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | |
| | | /** |
| | | * A menu call-back which should be associated with each menu option. |
| | | * When an option is selected the call-back is invoked. |
| | | * |
| | | * @param <T> |
| | | * The type of success result value(s) returned by the |
| | | * call-back. Use <code>Void</code> if the call-backs do |
| | | * not return any values. |
| | | */ |
| | | public interface MenuCallback<T> { |
| | | |
| | | /** |
| | | * Invoke the menu call-back. |
| | | * |
| | | * @param app |
| | | * The application console. |
| | | * @return Returns the result of invoking the menu call-back. |
| | | * @throws ClientException |
| | | * If the menu call-back fails for some reason. |
| | | */ |
| | | MenuResult<T> invoke(ConsoleApplication app) throws ClientException; |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2015 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | |
| | | /** |
| | | * The result of running a {@link Menu}. The result indicates to the |
| | | * application how it should proceed: |
| | | * <ul> |
| | | * <li>{@link #again()} - the menu should be displayed again. A good |
| | | * example of this is when a user chooses to view some help. Normally, |
| | | * after the help is displayed, the user is allowed to select another |
| | | * option |
| | | * <li>{@link #cancel()} - the user chose to cancel any task |
| | | * currently in progress and go back to the previous main menu if |
| | | * applicable |
| | | * <li>{@link #success()} - the user chose to apply any task |
| | | * currently in progress and go back to the previous menu if |
| | | * applicable. Any result values applicable to the chosen option can |
| | | * be retrieved using {@link #getValue()} or {@link #getValues()} |
| | | * <li>{@link #quit()} - the user chose to quit the application and |
| | | * cancel all outstanding tasks. |
| | | * </ul> |
| | | * |
| | | * @param <T> |
| | | * The type of result value(s) contained in success results. Use <code>Void</code> if success results should |
| | | * not contain values. |
| | | */ |
| | | public final class MenuResult<T> { |
| | | |
| | | /** The type of result returned from the menu. */ |
| | | private static enum Type { |
| | | /** |
| | | * The user selected an option which did not return a result, |
| | | * so the menu should be displayed again. |
| | | */ |
| | | AGAIN, |
| | | |
| | | /** |
| | | * The user did not select an option and instead |
| | | * chose to cancel the current task. |
| | | */ |
| | | CANCEL, |
| | | |
| | | /** |
| | | * The user did not select an option and instead |
| | | * chose to quit the entire application. |
| | | */ |
| | | QUIT, |
| | | |
| | | /** |
| | | * The user selected an option which succeeded |
| | | * and returned one or more result values. |
| | | */ |
| | | SUCCESS |
| | | } |
| | | |
| | | /** |
| | | * Creates a new menu result indicating that the menu should be displayed again. A good example of this is when a |
| | | * user chooses to view some help. Normally, after the help is displayed, the user is allowed to select another |
| | | * option. |
| | | * |
| | | * @param <T> |
| | | * The type of result value(s) contained in success results. Use <code>Void</code> if success results |
| | | * should not contain values. |
| | | * @return Returns a new menu result indicating that the menu should be displayed again. |
| | | */ |
| | | public static <T> MenuResult<T> again() { |
| | | return new MenuResult<>(Type.AGAIN, Collections.<T> emptyList()); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new menu result indicating that the user chose to cancel any task currently in progress and go back to |
| | | * the previous main menu if applicable. |
| | | * |
| | | * @param <T> |
| | | * The type of result value(s) contained in success results. Use <code>Void</code> if success results |
| | | * should not contain values. |
| | | * @return Returns a new menu result indicating that the user chose to cancel any task currently in progress and go |
| | | * back to the previous main menu if applicable. |
| | | */ |
| | | public static <T> MenuResult<T> cancel() { |
| | | return new MenuResult<>(Type.CANCEL, Collections.<T> emptyList()); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new menu result indicating that the user chose to quit the application and cancel all outstanding |
| | | * tasks. |
| | | * |
| | | * @param <T> |
| | | * The type of result value(s) contained in success results. Use <code>Void</code> if success results |
| | | * should not contain values. |
| | | * @return Returns a new menu result indicating that the user chose to quit the application and cancel all |
| | | * outstanding tasks. |
| | | */ |
| | | public static <T> MenuResult<T> quit() { |
| | | return new MenuResult<>(Type.QUIT, Collections.<T> emptyList()); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new menu result indicating that the user chose to apply any task currently in progress and go back to |
| | | * the previous menu if applicable. The menu result will not contain any result values. |
| | | * |
| | | * @param <T> |
| | | * The type of result value(s) contained in success results. Use <code>Void</code> if success results |
| | | * should not contain values. |
| | | * @return Returns a new menu result indicating that the user chose to apply any task currently in progress and go |
| | | * back to the previous menu if applicable.The menu result will not contain any result values. |
| | | */ |
| | | public static <T> MenuResult<T> success() { |
| | | return success(Collections.<T> emptySet()); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new menu result indicating that the user chose to apply any task currently in progress and go back to |
| | | * the previous menu if applicable. The menu result will contain the provided values, which can be retrieved using |
| | | * {@link #getValue()} or {@link #getValues()}. |
| | | * |
| | | * @param <T> |
| | | * The type of the result values. |
| | | * @param values |
| | | * The result values. |
| | | * @return Returns a new menu result indicating that the user chose to apply any task currently in progress and go |
| | | * back to the previous menu if applicable. The menu result will contain the provided values, which can be |
| | | * retrieved using {@link #getValue()} or {@link #getValues()}. |
| | | */ |
| | | public static <T> MenuResult<T> success(Collection<T> values) { |
| | | return new MenuResult<>(Type.SUCCESS, new ArrayList<>(values)); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new menu result indicating that the user chose to apply any task currently in progress and go back to |
| | | * the previous menu if applicable. The menu result will contain the provided value, which can be retrieved using |
| | | * {@link #getValue()} or {@link #getValues()}. |
| | | * |
| | | * @param <T> |
| | | * The type of the result value. |
| | | * @param value |
| | | * The result value. |
| | | * @return Returns a new menu result indicating that the user chose to apply any task currently in progress and go |
| | | * back to the previous menu if applicable. The menu result will contain the provided value, which can be |
| | | * retrieved using {@link #getValue()} or {@link #getValues()}. |
| | | */ |
| | | public static <T> MenuResult<T> success(T value) { |
| | | return success(Collections.singleton(value)); |
| | | } |
| | | |
| | | /** The type of result returned from the menu. */ |
| | | private final Type type; |
| | | |
| | | /** The menu result value(s). */ |
| | | private final Collection<T> values; |
| | | |
| | | /** Private constructor. */ |
| | | private MenuResult(Type type, Collection<T> values) { |
| | | this.type = type; |
| | | this.values = values; |
| | | } |
| | | |
| | | /** |
| | | * Gets the menu result value if this is a menu result indicating success. |
| | | * |
| | | * @return Returns the menu result value, or <code>null</code> if there was no result value or if this is not a |
| | | * success menu result. |
| | | * @see #isSuccess() |
| | | */ |
| | | public T getValue() { |
| | | if (!values.isEmpty()) { |
| | | return values.iterator().next(); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * Gets the menu result values if this is a menu result indicating success. |
| | | * |
| | | * @return Returns the menu result values, which may be empty if there were no result values or if this is not a |
| | | * success menu result. |
| | | * @see #isSuccess() |
| | | */ |
| | | public Collection<T> getValues() { |
| | | return new ArrayList<>(values); |
| | | } |
| | | |
| | | /** |
| | | * Determines if this menu result indicates that the menu should be displayed again. A good example of this is when |
| | | * a user chooses to view some help. Normally, after the help is displayed, the user is allowed to select another |
| | | * option. |
| | | * |
| | | * @return Returns <code>true</code> if this menu result indicates that the menu should be displayed again. |
| | | */ |
| | | public boolean isAgain() { |
| | | return type == Type.AGAIN; |
| | | } |
| | | |
| | | /** |
| | | * Determines if this menu result indicates that the user chose to cancel any task currently in progress and go back |
| | | * to the previous main menu if applicable. |
| | | * |
| | | * @return Returns <code>true</code> if this menu result indicates that the user chose to cancel any task currently |
| | | * in progress and go back to the previous main menu if applicable. |
| | | */ |
| | | public boolean isCancel() { |
| | | return type == Type.CANCEL; |
| | | } |
| | | |
| | | /** |
| | | * Determines if this menu result indicates that the user chose to quit the application and cancel all outstanding |
| | | * tasks. |
| | | * |
| | | * @return Returns <code>true</code> if this menu result indicates that the user chose to quit the application and |
| | | * cancel all outstanding tasks. |
| | | */ |
| | | public boolean isQuit() { |
| | | return type == Type.QUIT; |
| | | } |
| | | |
| | | /** |
| | | * Determines if this menu result indicates that the user chose to apply any task currently in progress and go back |
| | | * to the previous menu if applicable. Any result values can be retrieved using the {@link #getValue()} or |
| | | * {@link #getValues()} methods. |
| | | * |
| | | * @return Returns <code>true</code> if this menu result indicates that the user chose to apply any task currently |
| | | * in progress and go back to the previous menu if applicable. |
| | | * @see #getValue() |
| | | * @see #getValues() |
| | | */ |
| | | public boolean isSuccess() { |
| | | return type == Type.SUCCESS; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return getClass().getSimpleName() + "(type=" + type + ", values=" + values + ")"; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.ERR_MCARG_VALUE_NOT_ALLOWED; |
| | | |
| | | import java.util.Arrays; |
| | | import java.util.Collection; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | |
| | | /** |
| | | * This class defines an argument type that will only accept one or more of a |
| | | * specific set of string values. |
| | | * |
| | | * @param <V> |
| | | * The type of values returned by this argument. |
| | | */ |
| | | public final class MultiChoiceArgument<V> extends Argument { |
| | | |
| | | /** |
| | | * Returns a builder which can be used for incrementally constructing a new |
| | | * {@link MultiChoiceArgument<V>}. |
| | | * |
| | | * @param <V> |
| | | * The type of values returned by this argument. |
| | | * @param longIdentifier |
| | | * The generic long identifier that will be used to refer to this argument. |
| | | * @return A builder to continue building the {@link MultiChoiceArgument}. |
| | | */ |
| | | public static <V> Builder<V> builder(final String longIdentifier) { |
| | | return new Builder<>(longIdentifier); |
| | | } |
| | | |
| | | /** A fluent API for incrementally constructing {@link MultiChoiceArgument<V>}. */ |
| | | public static final class Builder<V> extends ArgumentBuilder<Builder<V>, V, MultiChoiceArgument<V>> { |
| | | private final List<V> allowedValues = new LinkedList<>(); |
| | | |
| | | private Builder(final String longIdentifier) { |
| | | super(longIdentifier); |
| | | } |
| | | |
| | | @Override |
| | | Builder<V> getThis() { |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Specifies the set of values that are allowed for the {@link MultiChoiceArgument<V>}. |
| | | * |
| | | * @param allowedValues |
| | | * The {@link MultiChoiceArgument<V>} allowed values. |
| | | * @return This builder. |
| | | */ |
| | | public Builder<V> allowedValues(final Collection<V> allowedValues) { |
| | | this.allowedValues.addAll(allowedValues); |
| | | return getThis(); |
| | | } |
| | | |
| | | /** |
| | | * Specifies the set of values that are allowed for the {@link MultiChoiceArgument<V>}. |
| | | * |
| | | * @param allowedValues |
| | | * The {@link MultiChoiceArgument<V>} allowed values. |
| | | * @return This builder. |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public final Builder<V> allowedValues(final V... allowedValues) { |
| | | this.allowedValues.addAll(Arrays.asList(allowedValues)); |
| | | return getThis(); |
| | | } |
| | | |
| | | @Override |
| | | public MultiChoiceArgument<V> buildArgument() throws ArgumentException { |
| | | return new MultiChoiceArgument<>(this, allowedValues); |
| | | } |
| | | } |
| | | |
| | | /** The set of values that will be allowed for use with this argument. */ |
| | | private final Collection<V> allowedValues; |
| | | |
| | | private <V1> MultiChoiceArgument(final Builder<V1> builder, final Collection<V> allowedValues) |
| | | throws ArgumentException { |
| | | super(builder); |
| | | this.allowedValues = allowedValues; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the string value for this argument. If it has multiple values, |
| | | * then the first will be returned. If it does not have any values, then the |
| | | * default value will be returned. |
| | | * |
| | | * @return The string value for this argument, or <CODE>null</CODE> if there |
| | | * are no values and no default value has been given. |
| | | * @throws ArgumentException |
| | | * The value cannot be parsed. |
| | | */ |
| | | public V getTypedValue() throws ArgumentException { |
| | | final String v = super.getValue(); |
| | | if (v == null) { |
| | | return null; |
| | | } |
| | | for (final V allowedValue : allowedValues) { |
| | | if (allowedValue.toString().equalsIgnoreCase(v)) { |
| | | return allowedValue; |
| | | } |
| | | } |
| | | throw new IllegalStateException("This MultiChoiceArgument value is not part of the allowed values."); |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether the provided value is acceptable for use in this |
| | | * argument. |
| | | * |
| | | * @param valueString |
| | | * The value for which to make the determination. |
| | | * @param invalidReason |
| | | * A buffer into which the invalid reason may be written if the |
| | | * value is not acceptable. |
| | | * @return <CODE>true</CODE> if the value is acceptable, or |
| | | * <CODE>false</CODE> if it is not. |
| | | */ |
| | | @Override |
| | | public boolean valueIsAcceptable(final String valueString, final LocalizableMessageBuilder invalidReason) { |
| | | for (final V allowedValue : allowedValues) { |
| | | if (allowedValue.toString().equalsIgnoreCase(valueString)) { |
| | | return true; |
| | | } |
| | | } |
| | | invalidReason.append(ERR_MCARG_VALUE_NOT_ALLOWED.get(longIdentifier, valueString)); |
| | | |
| | | return false; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2012-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.Utils.repeat; |
| | | |
| | | import java.io.PrintStream; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | import java.util.Locale; |
| | | |
| | | import org.forgerock.util.Reject; |
| | | |
| | | /** |
| | | * Utility class for printing columns of data. |
| | | * <p> |
| | | * This printer can be used to print data in formatted table or in csv format. |
| | | * <p> |
| | | * Regarding the formatting table feature, this class allows you to specify for each {@link Column}s: |
| | | * <ul> |
| | | * <li>A unique identifier</li> |
| | | * <li>The column title which will be printed by a call to {@link MultiColumnPrinter#printTitleLine()}</li> |
| | | * <li>The size (if a cell's data is bigger than the predefined size, then the data will not be truncated, |
| | | * i.e. it will overflow)</li> |
| | | * <li>The number of digits to keep (for {@link Double} data)</li> |
| | | * </ul> |
| | | * <p> |
| | | * Code to write data is independent of the {@link MultiColumnPrinter} configuration: |
| | | * <pre> |
| | | * void printData(final MultiColumnPrinter printer) { |
| | | * String[][] myData = new String[][] { |
| | | * new String[]{"U.S.A", "34.2", "40.8", ".us"}, |
| | | * new String[]{"United Kingdom", "261.1", "31.6", ".uk"}, |
| | | * new String[]{"France", "98.8", "30.1", ".fr"} |
| | | * }; |
| | | * |
| | | * int i; |
| | | * for (String[] countryData : myData) { |
| | | * i = 0; |
| | | * for (final MultiColumnPrinter.Column column : printer.getColumns()) { |
| | | * printer.printData(countryData[i++]); |
| | | * } |
| | | * } |
| | | * } |
| | | * </pre> |
| | | * <p> |
| | | * The following code sample presents how to create a {@link MultiColumnPrinter} to write CSV data: |
| | | * <pre> |
| | | * final List<MultiColumnPrinter.Column> columns = new ArrayList<>(); |
| | | * columns.add(MultiColumnPrinter.column("CountryNameColumnId", "country_name", 0)); |
| | | * columns.add(MultiColumnPrinter.column("populationDensityId", "population_density", 1)); |
| | | * columns.add(MultiColumnPrinter.column("GiniId", "gini", 1)); |
| | | * columns.add(MultiColumnPrinter.column("internetTLDId", "internet_tld", 0)); |
| | | * MultiColumnPrinter myCsvPrinter = MultiColumnPrinter.builder(System.out, columns) |
| | | * .columnSeparator(",") |
| | | * .build(); |
| | | * printData(myCsvPrinter); |
| | | * </pre> |
| | | * <p> |
| | | * The code above would print: |
| | | * <pre> |
| | | * country_name,population_density,gini,internet_tld |
| | | * U.S.A,34.2,40.8,.us |
| | | * United Kingdom,261.1,31.6,.uk |
| | | * France,98.8,30.1,.fr |
| | | * </pre> |
| | | * <p> |
| | | * The following code sample presents how to configure a {@link MultiColumnPrinter} |
| | | * to print the same data on console with some title headers. |
| | | * <pre> |
| | | * final List<MultiColumnPrinter.Column> columns = new ArrayList<>(); |
| | | * columns.add(MultiColumnPrinter.separatorColumn()); |
| | | * columns.add(MultiColumnPrinter.column("CountryNameColumnId", "Country Name", 15, 0)); |
| | | * columns.add(MultiColumnPrinter.column("populationDensityId", "Density", 10, 1)); |
| | | * columns.add(MultiColumnPrinter.separatorColumn()); |
| | | * columns.add(MultiColumnPrinter.column("GiniID", "GINI", 5, 1)); |
| | | * columns.add(MultiColumnPrinter.column("internetTLDID", "TLD", 5, 0)); |
| | | * columns.add(MultiColumnPrinter.separatorColumn()); |
| | | * MultiColumnPrinter myPrinter = MultiColumnPrinter.builder(System.out, columns) |
| | | * .format(true) |
| | | * .columnSeparator(" ") |
| | | * .titleAlignment(MultiColumnPrinter.Alignment.CENTER) |
| | | * .build(); |
| | | * myPrinter.printDashedLine(); |
| | | * myPrinter.printTitleSection("General Information", 2); |
| | | * myPrinter.printTitleSection("Data", 2); |
| | | * myPrinter.printTitleLine(); |
| | | * myPrinter.printDashedLine(); |
| | | * printData(myPrinter); |
| | | * myPrinter.printDashedLine(); |
| | | * </pre> |
| | | * <p> |
| | | * The code above would print: |
| | | * <pre> |
| | | * -------------------------------------------------- |
| | | * | General Information | Data | |
| | | * | Country Name Density | GINI TLD | |
| | | * -------------------------------------------------- |
| | | * | U.S.A 34.2 | 40.8 .us | |
| | | * | United Kingdom 261.1 | 31.6 .uk | |
| | | * | France 98.8 | 30.1 .fr | |
| | | * -------------------------------------------------- |
| | | * </pre> |
| | | */ |
| | | public final class MultiColumnPrinter { |
| | | |
| | | /** The data alignment. */ |
| | | public enum Alignment { |
| | | /** Data will be left-aligned. */ |
| | | LEFT, |
| | | /** Data will be centered. */ |
| | | CENTER, |
| | | /** Data will be right-aligned. */ |
| | | RIGHT |
| | | } |
| | | |
| | | private static final String SEPARATOR_ID = "separator"; |
| | | private static int separatorIdNumber; |
| | | |
| | | /** |
| | | * Returns a new separator {@link Column}. |
| | | * <p> |
| | | * This kind of {@link Column} can be used to separate data sections. |
| | | * |
| | | * @return A new separator {@link Column}. |
| | | */ |
| | | public static Column separatorColumn() { |
| | | return new Column(SEPARATOR_ID + separatorIdNumber++, "", 1, 0); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new {@link Column} with the provided arguments. |
| | | * |
| | | * @param id |
| | | * The column identifier. |
| | | * @param title |
| | | * The column title. |
| | | * @param doublePrecision |
| | | * The double precision used to print {@link Double} data for this column. |
| | | * See {@link MultiColumnPrinter#printData(Double)}. |
| | | * @return |
| | | * A new Column with the provided arguments. |
| | | */ |
| | | public static Column column(final String id, final String title, final int doublePrecision) { |
| | | return new Column(id, title, 1, doublePrecision); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new Column with the provided arguments. |
| | | * |
| | | * @param id |
| | | * The column identifier. |
| | | * @param title |
| | | * The column title. |
| | | * @param width |
| | | * The column width. |
| | | * This information will only be used if the associated |
| | | * {@link MultiColumnPrinter} is configured to apply formatting. |
| | | * See {@link Builder#format(boolean)}. |
| | | * @param doublePrecision |
| | | * The double precision to use to print data for this column. |
| | | * @return |
| | | * A new Column with the provided arguments. |
| | | */ |
| | | public static Column column(final String id, final String title, final int width, final int doublePrecision) { |
| | | return new Column(id, title, Math.max(width, title.length()), doublePrecision); |
| | | } |
| | | |
| | | /** |
| | | * This class describes a Column of data used in the {@link MultiColumnPrinter}. |
| | | * <p> |
| | | * A column consists in the following fields: |
| | | * <ul> |
| | | * <li>An identifier for the associated data. |
| | | * <li>A title which is printed when {@link MultiColumnPrinter#printTitleLine()} is called. |
| | | * <li>A width which is the max width for this column's data. |
| | | * This information will only be used if the associated {@link MultiColumnPrinter} |
| | | * is configure to apply formatting.See {@link Builder#format(boolean)}. |
| | | * <li>A double precision which is the number of decimal to print for numeric data. |
| | | * See {@link MultiColumnPrinter#printData(Double)}. |
| | | * </ul> |
| | | */ |
| | | public static final class Column { |
| | | private final String id; |
| | | private final String title; |
| | | private final int width; |
| | | private final int doublePrecision; |
| | | |
| | | private Column(final String id, final String title, final int width, final int doublePrecision) { |
| | | this.id = id; |
| | | this.title = title; |
| | | this.width = Math.max(width, title.length()); |
| | | this.doublePrecision = doublePrecision; |
| | | } |
| | | |
| | | /** |
| | | * Returns this {@link Column} identifier. |
| | | * |
| | | * @return This {@link Column} identifier. |
| | | */ |
| | | public String getId() { |
| | | return id; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Creates a new {@link Builder} to build a {@link MultiColumnPrinter}. |
| | | * |
| | | * @param stream |
| | | * The {@link PrintStream} to use to print data. |
| | | * @param columns |
| | | * The {@link List} of {@link Column} data to print. |
| | | * @return |
| | | * A new {@link Builder} to build a {@link MultiColumnPrinter}. |
| | | */ |
| | | public static Builder builder(final PrintStream stream, final List<Column> columns) { |
| | | return new Builder(stream, columns); |
| | | } |
| | | |
| | | /** A fluent API for incrementally constructing {@link MultiColumnPrinter}. */ |
| | | public static final class Builder { |
| | | private final PrintStream stream; |
| | | private final List<Column> columns; |
| | | |
| | | private Alignment titleAlignment = Alignment.RIGHT; |
| | | private String columnSeparator = " "; |
| | | private boolean format; |
| | | |
| | | private Builder(final PrintStream stream, final List<Column> columns) { |
| | | Reject.ifNull(stream); |
| | | this.stream = stream; |
| | | this.columns = columns; |
| | | } |
| | | |
| | | /** |
| | | * Sets whether the {@link MultiColumnPrinter} needs to apply formatting. |
| | | * <br> |
| | | * Default value is {@code false}. |
| | | * |
| | | * @param format |
| | | * {@code true} if the {@link MultiColumnPrinter} needs to apply formatting. |
| | | * @return This builder. |
| | | */ |
| | | public Builder format(final boolean format) { |
| | | this.format = format; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Sets the alignment for title elements which will be printed by the {@link MultiColumnPrinter}. |
| | | * <p> |
| | | * This is used only if the printer is configured to |
| | | * apply formatting, see {@link Builder#format(boolean)}. |
| | | * <br> |
| | | * Default value is {@link Alignment#RIGHT}. |
| | | * |
| | | * @param titleAlignment |
| | | * The title alignment. |
| | | * @return This builder. |
| | | */ |
| | | public Builder titleAlignment(final Alignment titleAlignment) { |
| | | this.titleAlignment = titleAlignment; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Sets the sequence to use to separate column. |
| | | * <p> |
| | | * Default value is {@code " "}. |
| | | * |
| | | * @param separator |
| | | * The sequence {@link String}. |
| | | * @return This builder. |
| | | */ |
| | | public Builder columnSeparator(final String separator) { |
| | | this.columnSeparator = separator; |
| | | return this; |
| | | } |
| | | |
| | | /** |
| | | * Creates a new {@link MultiColumnPrinter} as configured in this {@link Builder}. |
| | | * |
| | | * @return A new {@link MultiColumnPrinter} as configured in this {@link Builder}. |
| | | */ |
| | | public MultiColumnPrinter build() { |
| | | return new MultiColumnPrinter(this); |
| | | } |
| | | } |
| | | |
| | | private final PrintStream stream; |
| | | private final List<Column> columns; |
| | | private final boolean format; |
| | | private final Alignment titleAlignment; |
| | | private final String columnSeparator; |
| | | |
| | | private List<Column> printableColumns; |
| | | private final int lineLength; |
| | | private Iterator<Column> columnIterator; |
| | | private Column currentColumn; |
| | | |
| | | private MultiColumnPrinter(final Builder builder) { |
| | | this.stream = builder.stream; |
| | | this.columns = Collections.unmodifiableList(builder.columns); |
| | | this.format = builder.format; |
| | | this.columnSeparator = builder.columnSeparator; |
| | | this.titleAlignment = builder.titleAlignment; |
| | | this.lineLength = computeLineLength(); |
| | | resetIterator(); |
| | | computePrintableColumns(); |
| | | } |
| | | |
| | | /** Prints a dashed line. */ |
| | | public void printDashedLine() { |
| | | startNewLineIfNeeded(); |
| | | for (int i = 0; i < lineLength; i++) { |
| | | stream.print('-'); |
| | | } |
| | | stream.println(); |
| | | } |
| | | |
| | | /** |
| | | * Formats and prints the provided text data. |
| | | * Merge the provided text over the provided number of column. |
| | | * <p> |
| | | * Separator columns between merged columns will not be printed. |
| | | * |
| | | * @param data |
| | | * The section title to print. |
| | | * @param rowSpan |
| | | * Specifies the number of rows a cell should span. |
| | | */ |
| | | public void printTitleSection(final String data, final int rowSpan) { |
| | | consumeSeparatorColumn(); |
| | | int lengthToPad = 0; |
| | | int nbColumnMerged = 0; |
| | | |
| | | while (columnIterator.hasNext() && nbColumnMerged < rowSpan) { |
| | | lengthToPad += currentColumn.width + columnSeparator.length(); |
| | | if (!isSeparatorColumn(currentColumn)) { |
| | | nbColumnMerged++; |
| | | } |
| | | currentColumn = columnIterator.next(); |
| | | } |
| | | stream.print(align(data, titleAlignment, lengthToPad)); |
| | | consumeSeparatorColumn(); |
| | | if (!columnIterator.hasNext()) { |
| | | nextLine(); |
| | | } |
| | | } |
| | | |
| | | /** Prints a line with all column title and separator. */ |
| | | public void printTitleLine() { |
| | | startNewLineIfNeeded(); |
| | | passFirstSeparatorColumn(); |
| | | for (final Column column : this.printableColumns) { |
| | | printCell(column.title, Alignment.RIGHT); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Prints the provided {@link Double} value on the current column. |
| | | * <p> |
| | | * If this {@link MultiColumnPrinter} is configured to apply formatting, |
| | | * the provided value will be truncated according to the decimal |
| | | * precision set in the corresponding {@link Column}. |
| | | * <br> |
| | | * See {@link MultiColumnPrinter#column(String, String, int, int)} for more details. |
| | | * |
| | | * @param value |
| | | * The double value to print. |
| | | */ |
| | | public void printData(final Double value) { |
| | | passFirstSeparatorColumn(); |
| | | printData(value.isNaN() ? "-" |
| | | : String.format(Locale.ENGLISH, "%." + currentColumn.doublePrecision + "f", value)); |
| | | } |
| | | |
| | | /** |
| | | * Prints the provided text data on the current column. |
| | | * |
| | | * @param data |
| | | * The text data to print. |
| | | */ |
| | | public void printData(final String data) { |
| | | passFirstSeparatorColumn(); |
| | | printCell(data, Alignment.RIGHT); |
| | | } |
| | | |
| | | /** |
| | | * Returns the data {@link Column} list of this {@link MultiColumnPrinter}. |
| | | * <p> |
| | | * Separator columns are filtered out. |
| | | * |
| | | * @return The {@link Column} list of this {@link MultiColumnPrinter}. |
| | | */ |
| | | public List<Column> getColumns() { |
| | | return printableColumns; |
| | | } |
| | | |
| | | private void printCell(final String data, final Alignment alignment) { |
| | | String toPrint = format ? align(data, alignment, currentColumn.width) : data; |
| | | if (columnIterator.hasNext()) { |
| | | toPrint += columnSeparator; |
| | | } |
| | | stream.print(toPrint); |
| | | nextLineOnEOLOrNextColumn(); |
| | | } |
| | | |
| | | /** Provided the provided string data according to the provided width and the provided alignment. */ |
| | | private String align(final String data, final Alignment alignment, final int width) { |
| | | final String rawData = data.trim(); |
| | | final int padding = width - rawData.length(); |
| | | |
| | | if (padding <= 0) { |
| | | return rawData; |
| | | } |
| | | |
| | | switch (alignment) { |
| | | case RIGHT: |
| | | return pad(padding, rawData, 0); |
| | | case LEFT: |
| | | return pad(0, rawData, padding); |
| | | case CENTER: |
| | | final int paddingBefore = padding / 2; |
| | | return pad(paddingBefore, rawData, padding - paddingBefore); |
| | | default: |
| | | return ""; |
| | | } |
| | | } |
| | | |
| | | private String pad(final int leftPad, final String s, final int rightPad) { |
| | | return new StringBuilder().append(repeat(' ', leftPad)) |
| | | .append(s) |
| | | .append(repeat(' ', rightPad)) |
| | | .toString(); |
| | | } |
| | | |
| | | private void passFirstSeparatorColumn() { |
| | | if (cursorOnLineStart()) { |
| | | consumeSeparatorColumn(); |
| | | } |
| | | } |
| | | |
| | | private void consumeSeparatorColumn() { |
| | | if (isSeparatorColumn(currentColumn)) { |
| | | stream.print('|' + columnSeparator); |
| | | nextLineOnEOLOrNextColumn(); |
| | | } |
| | | } |
| | | |
| | | private void startNewLineIfNeeded() { |
| | | if (!cursorOnLineStart()) { |
| | | nextLine(); |
| | | } |
| | | } |
| | | |
| | | private void nextLineOnEOLOrNextColumn() { |
| | | if (columnIterator.hasNext()) { |
| | | currentColumn = columnIterator.next(); |
| | | consumeSeparatorColumn(); |
| | | } else { |
| | | nextLine(); |
| | | } |
| | | } |
| | | |
| | | private void nextLine() { |
| | | stream.println(); |
| | | resetIterator(); |
| | | } |
| | | |
| | | private void resetIterator() { |
| | | columnIterator = columns.iterator(); |
| | | currentColumn = columnIterator.next(); |
| | | } |
| | | |
| | | private boolean cursorOnLineStart() { |
| | | return currentColumn == columns.get(0); |
| | | } |
| | | |
| | | private boolean isSeparatorColumn(final Column column) { |
| | | return column.id.startsWith(SEPARATOR_ID); |
| | | } |
| | | |
| | | private void computePrintableColumns() { |
| | | printableColumns = new ArrayList<>(columns); |
| | | final Iterator<Column> it = printableColumns.iterator(); |
| | | |
| | | while (it.hasNext()) { |
| | | if (isSeparatorColumn(it.next())) { |
| | | it.remove(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private int computeLineLength() { |
| | | int lineLength = 0; |
| | | final int separatorLength = this.columnSeparator.length(); |
| | | for (final Column column : this.columns) { |
| | | lineLength += column.width + separatorLength; |
| | | } |
| | | return lineLength - separatorLength; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.FileOutputStream; |
| | | import java.io.IOException; |
| | | import java.security.KeyStore; |
| | | import java.security.KeyStoreException; |
| | | import java.security.NoSuchAlgorithmException; |
| | | import java.security.cert.CertificateException; |
| | | import java.security.cert.X509Certificate; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | import javax.net.ssl.TrustManager; |
| | | import javax.net.ssl.TrustManagerFactory; |
| | | import javax.net.ssl.X509TrustManager; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.util.Reject; |
| | | |
| | | /** |
| | | * A trust manager which prompts the user for the length of time that they would |
| | | * like to trust a server certificate. |
| | | */ |
| | | public final class PromptingTrustManager implements X509TrustManager { |
| | | /** Enumeration description server certificate trust option. */ |
| | | private static enum TrustOption { |
| | | UNTRUSTED(1, INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_NO.get()), |
| | | SESSION(2, INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_SESSION.get()), |
| | | PERMANENT(3, INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_ALWAYS.get()), |
| | | CERTIFICATE_DETAILS(4, INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_DETAILS.get()); |
| | | |
| | | private Integer choice; |
| | | private LocalizableMessage msg; |
| | | |
| | | /** |
| | | * Private constructor. |
| | | * |
| | | * @param i |
| | | * the menu return value. |
| | | * @param msg |
| | | * the message message. |
| | | */ |
| | | private TrustOption(final int i, final LocalizableMessage msg) { |
| | | choice = i; |
| | | this.msg = msg; |
| | | } |
| | | |
| | | /** |
| | | * Returns the choice number. |
| | | * |
| | | * @return the attribute name. |
| | | */ |
| | | Integer getChoice() { |
| | | return choice; |
| | | } |
| | | |
| | | /** |
| | | * Return the menu message. |
| | | * |
| | | * @return the menu message. |
| | | */ |
| | | LocalizableMessage getMenuMessage() { |
| | | return msg; |
| | | } |
| | | } |
| | | |
| | | private static final LocalizedLogger LOG = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | private static final String DEFAULT_PATH = System.getProperty("user.home") + File.separator |
| | | + ".opendj" + File.separator + "keystore"; |
| | | |
| | | private static final char[] DEFAULT_PASSWORD = "OpenDJ".toCharArray(); |
| | | |
| | | private final KeyStore inMemoryTrustStore; |
| | | |
| | | private final KeyStore onDiskTrustStore; |
| | | |
| | | private final X509TrustManager inMemoryTrustManager; |
| | | |
| | | private final X509TrustManager onDiskTrustManager; |
| | | |
| | | private final X509TrustManager nestedTrustManager; |
| | | |
| | | private final ConsoleApplication app; |
| | | |
| | | /** |
| | | * Creates a prompting trust manager based on these arguments. |
| | | * |
| | | * @param app |
| | | * The linked console application. |
| | | * @param acceptedStorePath |
| | | * The store path. |
| | | * @param sourceTrustManager |
| | | * The source of the trust manager. |
| | | * @throws KeyStoreException |
| | | * If no Provider supports a KeyStoreSpi implementation for the specified type. |
| | | * @throws IOException |
| | | * If there is an I/O or format problem with the keystore data, if a password is required but not given, |
| | | * or if the given password was incorrect. If the error is due to a wrong password, the cause of the |
| | | * IOException should be an UnrecoverableKeyException. |
| | | * @throws NoSuchAlgorithmException |
| | | * If no provider supports a trust manager factory spi implementation for the specified algorithm. |
| | | * @throws CertificateException |
| | | * If any of the certificates in the key store could not be loaded |
| | | */ |
| | | public PromptingTrustManager(final ConsoleApplication app, final String acceptedStorePath, |
| | | final X509TrustManager sourceTrustManager) throws KeyStoreException, IOException, |
| | | NoSuchAlgorithmException, CertificateException { |
| | | Reject.ifNull(app, acceptedStorePath); |
| | | this.app = app; |
| | | this.nestedTrustManager = sourceTrustManager; |
| | | inMemoryTrustStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
| | | onDiskTrustStore = KeyStore.getInstance(KeyStore.getDefaultType()); |
| | | |
| | | final File onDiskTrustStorePath = new File(acceptedStorePath); |
| | | inMemoryTrustStore.load(null, null); |
| | | if (!onDiskTrustStorePath.exists()) { |
| | | onDiskTrustStore.load(null, null); |
| | | } else { |
| | | try (final FileInputStream fos = new FileInputStream(onDiskTrustStorePath)) { |
| | | onDiskTrustStore.load(fos, DEFAULT_PASSWORD); |
| | | } |
| | | } |
| | | final TrustManagerFactory tmf = |
| | | TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); |
| | | |
| | | tmf.init(inMemoryTrustStore); |
| | | X509TrustManager x509tm = null; |
| | | for (final TrustManager tm : tmf.getTrustManagers()) { |
| | | if (tm instanceof X509TrustManager) { |
| | | x509tm = (X509TrustManager) tm; |
| | | break; |
| | | } |
| | | } |
| | | if (x509tm == null) { |
| | | throw new NoSuchAlgorithmException(); |
| | | } |
| | | this.inMemoryTrustManager = x509tm; |
| | | |
| | | tmf.init(onDiskTrustStore); |
| | | x509tm = null; |
| | | for (final TrustManager tm : tmf.getTrustManagers()) { |
| | | if (tm instanceof X509TrustManager) { |
| | | x509tm = (X509TrustManager) tm; |
| | | break; |
| | | } |
| | | } |
| | | if (x509tm == null) { |
| | | throw new NoSuchAlgorithmException(); |
| | | } |
| | | this.onDiskTrustManager = x509tm; |
| | | } |
| | | |
| | | /** |
| | | * Creates a prompting trust manager based on these arguments. |
| | | * |
| | | * @param app |
| | | * The linked console application. |
| | | * @param sourceTrustManager |
| | | * The source of the trust manager. |
| | | * @throws KeyStoreException |
| | | * If no Provider supports a KeyStoreSpi implementation for the specified type. |
| | | * @throws IOException |
| | | * If there is an I/O or format problem with the keystore data, if a password is required but not given, |
| | | * or if the given password was incorrect. If the error is due to a wrong password, the cause of the |
| | | * IOException should be an UnrecoverableKeyException. |
| | | * @throws NoSuchAlgorithmException |
| | | * If no provider supports a trust manager factory spi implementation for the specified algorithm. |
| | | * @throws CertificateException |
| | | * If any of the certificates in the key store could not be loaded |
| | | */ |
| | | public PromptingTrustManager(final ConsoleApplication app, final X509TrustManager sourceTrustManager) |
| | | throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException { |
| | | this(app, DEFAULT_PATH, sourceTrustManager); |
| | | } |
| | | |
| | | @Override |
| | | public void checkClientTrusted(final X509Certificate[] x509Certificates, final String s) |
| | | throws CertificateException { |
| | | try { |
| | | inMemoryTrustManager.checkClientTrusted(x509Certificates, s); |
| | | } catch (final Exception ce1) { |
| | | try { |
| | | onDiskTrustManager.checkClientTrusted(x509Certificates, s); |
| | | } catch (final Exception ce2) { |
| | | if (nestedTrustManager != null) { |
| | | try { |
| | | nestedTrustManager.checkClientTrusted(x509Certificates, s); |
| | | } catch (final Exception ce3) { |
| | | checkManuallyTrusted(x509Certificates, ce3); |
| | | } |
| | | } else { |
| | | checkManuallyTrusted(x509Certificates, ce1); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void checkServerTrusted(final X509Certificate[] x509Certificates, final String s) |
| | | throws CertificateException { |
| | | try { |
| | | inMemoryTrustManager.checkServerTrusted(x509Certificates, s); |
| | | } catch (final Exception ce1) { |
| | | try { |
| | | onDiskTrustManager.checkServerTrusted(x509Certificates, s); |
| | | } catch (final Exception ce2) { |
| | | if (nestedTrustManager != null) { |
| | | try { |
| | | nestedTrustManager.checkServerTrusted(x509Certificates, s); |
| | | } catch (final Exception ce3) { |
| | | checkManuallyTrusted(x509Certificates, ce3); |
| | | } |
| | | } else { |
| | | checkManuallyTrusted(x509Certificates, ce1); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public X509Certificate[] getAcceptedIssuers() { |
| | | if (nestedTrustManager != null) { |
| | | return nestedTrustManager.getAcceptedIssuers(); |
| | | } |
| | | return new X509Certificate[0]; |
| | | } |
| | | |
| | | /** |
| | | * This method is called when the user accepted a certificate. |
| | | * |
| | | * @param chain |
| | | * the certificate chain accepted by the user. certificate. |
| | | */ |
| | | private void acceptCertificate(final X509Certificate[] chain, final boolean permanent) { |
| | | if (permanent) { |
| | | LOG.debug(LocalizableMessage.raw("Permanently accepting certificate chain to " + "truststore")); |
| | | } else { |
| | | LOG.debug(LocalizableMessage.raw("Accepting certificate chain for this session")); |
| | | } |
| | | |
| | | for (final X509Certificate aChain : chain) { |
| | | try { |
| | | final String alias = aChain.getSubjectDN().getName(); |
| | | inMemoryTrustStore.setCertificateEntry(alias, aChain); |
| | | if (permanent) { |
| | | onDiskTrustStore.setCertificateEntry(alias, aChain); |
| | | } |
| | | } catch (final Exception e) { |
| | | LOG.warn(LocalizableMessage.raw("Error setting certificate to store: " + e + "\nCert: " + aChain)); |
| | | } |
| | | } |
| | | |
| | | if (permanent) { |
| | | try { |
| | | final File truststoreFile = new File(DEFAULT_PATH); |
| | | if (!truststoreFile.exists()) { |
| | | createFile(truststoreFile); |
| | | } |
| | | try (final FileOutputStream fos = new FileOutputStream(truststoreFile)) { |
| | | onDiskTrustStore.store(fos, DEFAULT_PASSWORD); |
| | | } |
| | | } catch (final Exception e) { |
| | | LOG.warn(LocalizableMessage.raw("Error saving store to disk: " + e)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Indicate if the certificate chain can be trusted. |
| | | * |
| | | * @param chain |
| | | * The certificate chain to validate certificate. |
| | | */ |
| | | private void checkManuallyTrusted(final X509Certificate[] chain, final Exception exception) |
| | | throws CertificateException { |
| | | app.println(); |
| | | app.println(INFO_LDAP_CONN_PROMPT_SECURITY_SERVER_CERTIFICATE.get()); |
| | | app.println(); |
| | | for (final X509Certificate element : chain) { |
| | | // Certificate DN |
| | | app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_USER_DN.get(element |
| | | .getSubjectDN().toString())); |
| | | |
| | | // certificate validity |
| | | app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_VALIDITY.get(element |
| | | .getNotBefore().toString(), element.getNotAfter().toString())); |
| | | |
| | | // certificate Issuer |
| | | app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER.get(element.getIssuerDN() |
| | | .toString())); |
| | | |
| | | app.println(); |
| | | app.println(); |
| | | } |
| | | |
| | | app.println(); |
| | | app.println(INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION.get()); |
| | | app.println(); |
| | | |
| | | final Map<String, TrustOption> menuOptions = new HashMap<>(); |
| | | for (final TrustOption t : TrustOption.values()) { |
| | | menuOptions.put(t.getChoice().toString(), t); |
| | | |
| | | final LocalizableMessageBuilder builder = new LocalizableMessageBuilder(); |
| | | builder.append(t.getChoice()); |
| | | builder.append(") "); |
| | | builder.append(t.getMenuMessage()); |
| | | app.println(builder.toMessage(), 2 /* Indent options */); |
| | | } |
| | | |
| | | final TrustOption defaultTrustMethod = TrustOption.SESSION; |
| | | final LocalizableMessage promptMsg = INFO_MENU_PROMPT_SINGLE.get(); |
| | | |
| | | while (true) { |
| | | app.println(); |
| | | String choice; |
| | | try { |
| | | choice = app.readInput(promptMsg, defaultTrustMethod.getChoice().toString()); |
| | | } catch (final ClientException e) { |
| | | // What can we do here? |
| | | throw new CertificateException(exception); |
| | | } finally { |
| | | app.println(); |
| | | } |
| | | |
| | | final TrustOption option = menuOptions.get(choice.trim()); |
| | | if (option == null) { |
| | | app.println(ERR_MENU_BAD_CHOICE_SINGLE.get()); |
| | | app.println(); |
| | | continue; |
| | | } |
| | | |
| | | switch (option) { |
| | | case UNTRUSTED: |
| | | if (exception instanceof CertificateException) { |
| | | throw (CertificateException) exception; |
| | | } |
| | | throw new CertificateException(exception); |
| | | case CERTIFICATE_DETAILS: |
| | | for (final X509Certificate aChain : chain) { |
| | | app.println(); |
| | | app.println(INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE.get(aChain.toString())); |
| | | app.println(); |
| | | } |
| | | break; |
| | | default: // SESSION / PERMANENT. |
| | | // Update the trust manager with the new certificate |
| | | acceptCertificate(chain, option == TrustOption.PERMANENT); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private boolean createFile(final File f) throws IOException { |
| | | boolean success = false; |
| | | if (f != null) { |
| | | final File parent = f.getParentFile(); |
| | | if (!parent.exists()) { |
| | | parent.mkdirs(); |
| | | } |
| | | success = f.createNewFile(); |
| | | } |
| | | return success; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2014-2015 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * List of return codes used by CLIs. |
| | | */ |
| | | public enum ReturnCode { |
| | | /** |
| | | * Successful setup. |
| | | * <PRE> |
| | | * Code value of 0. |
| | | * </PRE> |
| | | */ |
| | | SUCCESS(0), |
| | | /** |
| | | * Unexpected error (potential bug). |
| | | * <PRE> |
| | | * Code value of 1. |
| | | * </PRE> |
| | | */ |
| | | ERROR_UNEXPECTED(1), |
| | | /** |
| | | * Cannot parse arguments or data provided by user is not valid. |
| | | * <PRE> |
| | | * Code value of 2. |
| | | * </PRE> |
| | | */ |
| | | ERROR_USER_DATA(2), |
| | | /** |
| | | * The LDAP result code for operations that fail due to a protocol error. |
| | | */ |
| | | PROTOCOL_ERROR(2), |
| | | /** |
| | | * Error server already installed. |
| | | * <PRE> |
| | | * Code value of 3. |
| | | * </PRE> |
| | | */ |
| | | ERROR_SERVER_ALREADY_INSTALLED(3), |
| | | /** |
| | | * Error initializing server. |
| | | * <PRE> |
| | | * Code value of 4. |
| | | * </PRE> |
| | | */ |
| | | ERROR_INITIALIZING_SERVER(4), |
| | | /** |
| | | * The user failed providing password (for the key store for instance). |
| | | * <PRE> |
| | | * Code value of 5. |
| | | * </PRE> |
| | | */ |
| | | ERROR_PASSWORD_LIMIT(5), |
| | | /** |
| | | * The user cancelled the process. |
| | | * <PRE> |
| | | * Code value of 6. |
| | | * </PRE> |
| | | */ |
| | | ERROR_USER_CANCELLED(6), |
| | | /** |
| | | * The user doesn't accept the license. |
| | | * <PRE> |
| | | * Code value of 7. |
| | | * </PRE> |
| | | */ |
| | | ERROR_LICENSE_NOT_ACCEPTED(7), |
| | | /** |
| | | * The LDAP result code for operations that fail because the requested |
| | | * authentication method is not supported. |
| | | */ |
| | | AUTH_METHOD_NOT_SUPPORTED(7), |
| | | /** |
| | | * Incompatible java version. |
| | | * <PRE> |
| | | * Code value of 8. |
| | | * </PRE> |
| | | */ |
| | | JAVA_VERSION_INCOMPATIBLE(8), |
| | | /** |
| | | * Application specific error. |
| | | */ |
| | | APPLICATION_ERROR(10), |
| | | /** |
| | | * The LDAP result code used for multi-stage SASL bind operations that are not |
| | | * yet complete. |
| | | */ |
| | | SASL_BIND_IN_PROGRESS(14), |
| | | /** |
| | | * Conflicting command line arguments. |
| | | */ |
| | | CONFLICTING_ARGS(18), |
| | | /** |
| | | * The LDAP result code for operations that fail because a defined constraint |
| | | * has been violated. |
| | | */ |
| | | CONSTRAINT_VIOLATION(19), |
| | | /** |
| | | * The LDAP result code for operations that fail because a targeted entry does |
| | | * not exist. |
| | | */ |
| | | NO_SUCH_OBJECT(32), |
| | | /** |
| | | * The LDAP result code for operations that fail because the user supplied |
| | | * invalid credentials for an authentication attempt. |
| | | */ |
| | | INVALID_CREDENTIALS(49), |
| | | |
| | | /** |
| | | * The LDAP result code for operations that fail because the client does not |
| | | * have permission to perform the requested operation. |
| | | */ |
| | | INSUFFICIENT_ACCESS_RIGHTS(50), |
| | | /** |
| | | * The LDAP result code for operations that fail because the requested |
| | | * operation would have resulted in an entry that conflicts with one that |
| | | * already exists. |
| | | */ |
| | | ENTRY_ALREADY_EXISTS(68), |
| | | /** |
| | | * The LDAP result code for use in cases in which none of the other defined |
| | | * result codes are appropriate. |
| | | */ |
| | | OTHER(80), |
| | | /** |
| | | * The client-side result code that indicates that a previously-established |
| | | * connection to the server was lost. This is for client-side use only and |
| | | * should never be transferred over protocol. |
| | | */ |
| | | CLIENT_SIDE_SERVER_DOWN(81), |
| | | /** |
| | | * The client-side result code that indicates that a local error occurred that |
| | | * had nothing to do with interaction with the server. This is for |
| | | * client-side use only and should never be transferred over protocol. |
| | | */ |
| | | CLIENT_SIDE_LOCAL_ERROR(82), |
| | | /** |
| | | * The client-side result code that indicates that an error occurred while |
| | | * encoding a request to send to the server. This is for client-side use only |
| | | * and should never be transferred over protocol. |
| | | */ |
| | | CLIENT_SIDE_ENCODING_ERROR(83), |
| | | /** |
| | | * The client-side result code that indicates that an error occurred while |
| | | * decoding a response from the server. This is for client-side use only and |
| | | * should never be transferred over protocol. |
| | | */ |
| | | CLIENT_SIDE_DECODING_ERROR(84), |
| | | /** |
| | | * The client-side result code that indicates that the user requested an |
| | | * unknown or unsupported authentication mechanism. This is for client-side |
| | | * use only and should never be transferred over protocol. |
| | | */ |
| | | CLIENT_SIDE_AUTH_UNKNOWN(86), |
| | | /** |
| | | * The client-side result code that indicates that there was a problem with one or more of the parameters provided |
| | | * by the user. |
| | | * <PRE> |
| | | * Code value of 89. |
| | | * </PRE> |
| | | */ |
| | | CLIENT_SIDE_PARAM_ERROR(89), |
| | | /** |
| | | * The client-side result code that indicates that the client was not able to |
| | | * establish a connection to the server. This is for client-side use only and |
| | | * should never be transferred over protocol. |
| | | */ |
| | | CLIENT_SIDE_CONNECT_ERROR(91); |
| | | |
| | | private int returnCode; |
| | | private static final Map<Integer, String> RETURNCODE = new HashMap<>(); |
| | | static { |
| | | for (final ReturnCode rc : ReturnCode.values()) { |
| | | RETURNCODE.put(rc.get(), rc.name()); |
| | | } |
| | | } |
| | | |
| | | private ReturnCode(int returnCode) { |
| | | this.returnCode = returnCode; |
| | | } |
| | | |
| | | /** |
| | | * Get the corresponding return code value. |
| | | * |
| | | * @return The corresponding return code value. |
| | | */ |
| | | public int get() { |
| | | return returnCode; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a string representation of the return code. |
| | | * |
| | | * @param code |
| | | * The code value for which to obtain the string representation. |
| | | * @return The string representation of the return code. |
| | | */ |
| | | public static String get(int code) { |
| | | return RETURNCODE.get(code); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | |
| | | /** This class defines an argument type that will accept any string value. */ |
| | | public final class StringArgument extends Argument { |
| | | /** |
| | | * Returns a builder which can be used for incrementally constructing a new |
| | | * {@link StringArgument}. |
| | | * |
| | | * @param name |
| | | * The generic name that will be used to refer to this argument. |
| | | * @return A builder to continue building the {@link StringArgument}. |
| | | */ |
| | | public static Builder builder(final String name) { |
| | | return new Builder(name); |
| | | } |
| | | |
| | | /** A fluent API for incrementally constructing {@link StringArgument}. */ |
| | | public static final class Builder extends ArgumentBuilder<Builder, String, StringArgument> { |
| | | private Builder(final String name) { |
| | | super(name); |
| | | } |
| | | |
| | | @Override |
| | | Builder getThis() { |
| | | return this; |
| | | } |
| | | |
| | | @Override |
| | | public StringArgument buildArgument() throws ArgumentException { |
| | | return new StringArgument(this); |
| | | } |
| | | } |
| | | |
| | | private StringArgument(final Builder builder) throws ArgumentException { |
| | | super(builder); |
| | | } |
| | | |
| | | @Override |
| | | public boolean valueIsAcceptable(final String valueString, final LocalizableMessageBuilder invalidReason) { |
| | | // All values will be acceptable for this argument. |
| | | return true; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | import static com.forgerock.opendj.util.StaticUtils.*; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedList; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * This class defines a data structure for holding information about a subcommand that may be used with the subcommand |
| | | * argument parser. The subcommand has a name, a description, and a set of arguments. |
| | | */ |
| | | public class SubCommand implements DocDescriptionSupplement { |
| | | /** Indicates whether this subCommand should be hidden in the usage information. */ |
| | | private boolean isHidden; |
| | | |
| | | /** The mapping between the short argument IDs and the arguments for this subcommand. */ |
| | | private final HashMap<Character, Argument> shortIDMap = new HashMap<>(); |
| | | /** The mapping between the long argument IDs and the arguments for this subcommand. */ |
| | | private final HashMap<String, Argument> longIDMap = new HashMap<>(); |
| | | /** The list of arguments associated with this subcommand. */ |
| | | private final LinkedList<Argument> arguments = new LinkedList<>(); |
| | | |
| | | /** The description for this subcommand. */ |
| | | private LocalizableMessage description; |
| | | /** The name of this subcommand. */ |
| | | private String name; |
| | | |
| | | /** The argument parser with which this subcommand is associated. */ |
| | | private SubCommandArgumentParser parser; |
| | | |
| | | /** |
| | | * Indicates whether this parser will allow additional unnamed |
| | | * arguments at the end of the list. |
| | | */ |
| | | private boolean allowsTrailingArguments; |
| | | |
| | | /** The maximum number of unnamed trailing arguments that may be provided. */ |
| | | private int maxTrailingArguments; |
| | | /** The minimum number of unnamed trailing arguments that may be provided. */ |
| | | private int minTrailingArguments; |
| | | |
| | | /** The display name that will be used for the trailing arguments in the usage information. */ |
| | | private String trailingArgsDisplayName; |
| | | |
| | | /** |
| | | * Creates a new subcommand with the provided information. The subcommand will be automatically registered with the |
| | | * associated parser. |
| | | * |
| | | * @param parser |
| | | * The argument parser with which this subcommand is associated. |
| | | * @param name |
| | | * The name of this subcommand. |
| | | * @param description |
| | | * The description of this subcommand. |
| | | * @throws ArgumentException |
| | | * If the associated argument parser already has a subcommand with the same name. |
| | | */ |
| | | public SubCommand(SubCommandArgumentParser parser, String name, LocalizableMessage description) |
| | | throws ArgumentException { |
| | | this(parser, name, false, 0, 0, null, description); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new subcommand with the provided information. The subcommand will be automatically registered with the |
| | | * associated parser. |
| | | * |
| | | * @param parser |
| | | * The argument parser with which this subcommand is associated. |
| | | * @param name |
| | | * The name of this subcommand. |
| | | * @param allowsTrailingArguments |
| | | * 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. |
| | | * @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. |
| | | * @param trailingArgsDisplayName |
| | | * The display name that should be used as a placeholder for unnamed trailing arguments in the generated |
| | | * usage information. |
| | | * @param description |
| | | * The description of this subcommand. |
| | | * @throws ArgumentException |
| | | * If the associated argument parser already has a subcommand with the same name. |
| | | */ |
| | | public SubCommand(SubCommandArgumentParser parser, String name, boolean allowsTrailingArguments, |
| | | int minTrailingArguments, int maxTrailingArguments, String trailingArgsDisplayName, |
| | | LocalizableMessage description) throws ArgumentException { |
| | | this.parser = parser; |
| | | this.name = name; |
| | | this.description = description; |
| | | this.allowsTrailingArguments = allowsTrailingArguments; |
| | | this.minTrailingArguments = minTrailingArguments; |
| | | this.maxTrailingArguments = maxTrailingArguments; |
| | | this.trailingArgsDisplayName = trailingArgsDisplayName; |
| | | this.isHidden = false; |
| | | |
| | | String nameToCheck = name; |
| | | if (parser.longArgumentsCaseSensitive()) { |
| | | nameToCheck = toLowerCase(name); |
| | | } |
| | | |
| | | if (parser.hasSubCommand(nameToCheck)) { |
| | | LocalizableMessage message = ERR_ARG_SUBCOMMAND_DUPLICATE_SUBCOMMAND.get(name); |
| | | throw new ArgumentException(message); |
| | | } |
| | | |
| | | parser.addSubCommand(this); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the name of this subcommand. |
| | | * |
| | | * @return The name of this subcommand. |
| | | */ |
| | | public String getName() { |
| | | return name; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the description for this subcommand. |
| | | * |
| | | * @return The description for this subcommand. |
| | | */ |
| | | public LocalizableMessage getDescription() { |
| | | return description; |
| | | } |
| | | |
| | | /** |
| | | * A supplement to the description for this subcommand |
| | | * intended for use in generated reference documentation. |
| | | */ |
| | | private LocalizableMessage docDescriptionSupplement; |
| | | |
| | | @Override |
| | | public LocalizableMessage getDocDescriptionSupplement() { |
| | | return docDescriptionSupplement != null ? docDescriptionSupplement : LocalizableMessage.EMPTY; |
| | | } |
| | | |
| | | /** |
| | | * Sets a supplement to the description intended for use in generated reference documentation. |
| | | * |
| | | * @param docDescriptionSupplement |
| | | * The supplement to the description for use in generated reference documentation. |
| | | */ |
| | | public void setDocDescriptionSupplement(final LocalizableMessage docDescriptionSupplement) { |
| | | this.docDescriptionSupplement = docDescriptionSupplement; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the set of arguments for this subcommand. |
| | | * |
| | | * @return The set of arguments for this subcommand. |
| | | */ |
| | | public LinkedList<Argument> getArguments() { |
| | | return arguments; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the subcommand argument with the specified short identifier. |
| | | * |
| | | * @param shortID |
| | | * The short identifier of the argument to retrieve. |
| | | * @return The subcommand argument with the specified short identifier, or <CODE>null</CODE> if there is none. |
| | | */ |
| | | public Argument getArgument(Character shortID) { |
| | | return shortIDMap.get(shortID); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the subcommand argument with the specified long identifier. |
| | | * |
| | | * @param longID |
| | | * The long identifier of the argument to retrieve. |
| | | * @return The subcommand argument with the specified long identifier, or <CODE>null</CODE> if there is none. |
| | | */ |
| | | public Argument getArgument(String longID) { |
| | | return longIDMap.get(longID); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the subcommand argument with the specified long identifier. |
| | | * |
| | | * @param longIdentifier |
| | | * The long identifier of the argument to retrieve. |
| | | * @return The subcommand argument with the specified long identifier, |
| | | * or <CODE>null</CODE> if there is no such argument. |
| | | */ |
| | | public Argument getArgumentForLongIdentifier(final String longIdentifier) { |
| | | return longIDMap.get(parser.longArgumentsCaseSensitive() ? longIdentifier : toLowerCase(longIdentifier)); |
| | | } |
| | | |
| | | /** |
| | | * Adds the provided argument for use with this subcommand. |
| | | * |
| | | * @param argument |
| | | * The argument to add for use with this subcommand. |
| | | * @throws ArgumentException |
| | | * If either the short ID or long ID for the argument conflicts with that of another argument already |
| | | * associated with this subcommand. |
| | | */ |
| | | public void addArgument(Argument argument) throws ArgumentException { |
| | | final String argumentLongID = argument.getLongIdentifier(); |
| | | if (getArgumentForLongIdentifier(argumentLongID) != null) { |
| | | throw new ArgumentException(ERR_ARG_SUBCOMMAND_DUPLICATE_ARGUMENT_NAME.get(name, argumentLongID)); |
| | | } |
| | | |
| | | if (parser.hasGlobalArgument(argumentLongID)) { |
| | | throw new ArgumentException(ERR_ARG_SUBCOMMAND_ARGUMENT_GLOBAL_CONFLICT.get(argumentLongID, name)); |
| | | } |
| | | |
| | | Character shortID = argument.getShortIdentifier(); |
| | | if (shortID != null) { |
| | | if (shortIDMap.containsKey(shortID)) { |
| | | throw new ArgumentException(ERR_ARG_SUBCOMMAND_DUPLICATE_SHORT_ID.get( |
| | | argumentLongID, name, String.valueOf(shortID), shortIDMap.get(shortID).getLongIdentifier())); |
| | | } |
| | | |
| | | Argument arg = parser.getGlobalArgumentForShortID(shortID); |
| | | if (arg != null) { |
| | | throw new ArgumentException(ERR_ARG_SUBCOMMAND_ARGUMENT_SHORT_ID_GLOBAL_CONFLICT.get( |
| | | argumentLongID, name, String.valueOf(shortID), arg.getLongIdentifier())); |
| | | } |
| | | } |
| | | |
| | | String longID = argument.getLongIdentifier(); |
| | | if (!parser.longArgumentsCaseSensitive()) { |
| | | longID = toLowerCase(longID); |
| | | if (longIDMap.containsKey(longID)) { |
| | | throw new ArgumentException(ERR_ARG_SUBCOMMAND_DUPLICATE_LONG_ID.get(argumentLongID, name)); |
| | | } |
| | | } |
| | | |
| | | Argument arg = parser.getGlobalArgumentForLongID(longID); |
| | | if (arg != null) { |
| | | throw new ArgumentException(ERR_ARG_SUBCOMMAND_ARGUMENT_LONG_ID_GLOBAL_CONFLICT.get(argumentLongID, name)); |
| | | } |
| | | |
| | | arguments.add(argument); |
| | | |
| | | if (shortID != null) { |
| | | shortIDMap.put(shortID, argument); |
| | | } |
| | | |
| | | if (longID != null) { |
| | | longIDMap.put(longID, argument); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether this sub-command 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 sub-command allows unnamed trailing arguments, or <CODE>false</CODE> if it does |
| | | * not. |
| | | */ |
| | | public 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. |
| | | */ |
| | | public 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. |
| | | */ |
| | | public int getMaxTrailingArguments() { |
| | | return maxTrailingArguments; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the trailing arguments display name. |
| | | * |
| | | * @return Returns the trailing arguments display name. |
| | | */ |
| | | public String getTrailingArgumentsDisplayName() { |
| | | return trailingArgsDisplayName; |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | public ArrayList<String> getTrailingArguments() { |
| | | return parser.getTrailingArguments(); |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether this subcommand should be hidden from the usage information. |
| | | * |
| | | * @return <CODE>true</CODE> if this subcommand should be hidden from the usage information, or <CODE>false</CODE> |
| | | * if not. |
| | | */ |
| | | public boolean isHidden() { |
| | | return isHidden; |
| | | } |
| | | |
| | | /** |
| | | * Specifies whether this subcommand should be hidden from the usage information. |
| | | * |
| | | * @param isHidden |
| | | * Indicates whether this subcommand should be hidden from the usage information. |
| | | */ |
| | | public void setHidden(boolean isHidden) { |
| | | this.isHidden = isHidden; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | final StringBuilder sb = new StringBuilder(); |
| | | sb.append(getClass().getSimpleName()).append("(").append("name=").append(this.name); |
| | | if (!longIDMap.isEmpty()) { |
| | | sb.append(", longIDs=").append(longIDMap.keySet()); |
| | | } |
| | | if (!shortIDMap.isEmpty()) { |
| | | sb.append(", shortIDs=").append(shortIDMap.keySet()); |
| | | } |
| | | sb.append(")"); |
| | | return sb.toString(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.ArgumentConstants.*; |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | import static com.forgerock.opendj.cli.DocGenerationHelper.*; |
| | | import static com.forgerock.opendj.cli.Utils.*; |
| | | import static com.forgerock.opendj.util.StaticUtils.*; |
| | | |
| | | import java.io.OutputStream; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.LinkedList; |
| | | import java.util.List; |
| | | import java.util.Locale; |
| | | import java.util.Map; |
| | | import java.util.Properties; |
| | | import java.util.SortedMap; |
| | | import java.util.TreeMap; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | |
| | | import com.forgerock.opendj.util.OperatingSystem; |
| | | |
| | | /** |
| | | * This class defines a variant of the argument parser that can be used with applications that use subcommands to |
| | | * customize their behavior and that have a different set of options per subcommand (e.g, "cvs checkout" takes different |
| | | * options than "cvs commit"). This parser also has the ability to use global options that will always be applicable |
| | | * regardless of the subcommand in addition to the subcommand-specific arguments. There must not be any conflicts |
| | | * between the global options and the option for any subcommand, but it is allowed to re-use subcommand-specific options |
| | | * for different purposes between different subcommands. |
| | | */ |
| | | public class SubCommandArgumentParser extends ArgumentParser { |
| | | |
| | | private static final String INDENT = " "; |
| | | private static final int COLUMN_ADJUST = OperatingSystem.isWindows() ? 1 : 0; |
| | | |
| | | /** The arguments that will be used to trigger the display of usage information for groups of sub-commands. */ |
| | | private final Map<Argument, Collection<SubCommand>> usageGroupArguments = new HashMap<>(); |
| | | |
| | | /** The set of global arguments defined for this parser, referenced by short ID. */ |
| | | private final Map<Character, Argument> globalShortIDMap = new HashMap<>(); |
| | | /** The set of global arguments defined for this parser, referenced by long ID. */ |
| | | private final Map<String, Argument> globalLongIDMap = new HashMap<>(); |
| | | /** The set of global arguments defined for this parser, referenced by argument name. */ |
| | | private final Map<String, Argument> globalArgumentMap = new HashMap<>(); |
| | | /** The total set of global arguments defined for this parser. */ |
| | | private final List<Argument> globalArgumentList = new LinkedList<>(); |
| | | /** The set of subcommands defined for this parser, referenced by subcommand name. */ |
| | | private final SortedMap<String, SubCommand> subCommands = new TreeMap<>(); |
| | | |
| | | /** The subcommand requested by the user as part of the command-line arguments. */ |
| | | private SubCommand subCommand; |
| | | private SubCommandUsageHandler subCommandUsageHandler; |
| | | |
| | | /** |
| | | * Creates a new instance of this subcommand argument parser with no 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. |
| | | * @param toolDescription |
| | | * A human-readable description for the tool, which will be included when displaying usage information. |
| | | * @param longArgumentsCaseSensitive |
| | | * Indicates whether subcommand and long argument names should be treated in a case-sensitive manner. |
| | | */ |
| | | public SubCommandArgumentParser(String mainClassName, LocalizableMessage toolDescription, |
| | | boolean longArgumentsCaseSensitive) { |
| | | super(mainClassName, toolDescription, longArgumentsCaseSensitive); |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether this argument parser contains a global argument with the specified name. |
| | | * |
| | | * @param argumentName |
| | | * The name for which to make the determination. |
| | | * @return <CODE>true</CODE> if a global argument exists with the specified name, or <CODE>false</CODE> if not. |
| | | */ |
| | | public boolean hasGlobalArgument(String argumentName) { |
| | | return globalArgumentMap.containsKey(argumentName); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the global argument with the specified short identifier. |
| | | * |
| | | * @param shortID |
| | | * The short identifier for the global argument to retrieve. |
| | | * @return The global argument with the specified short identifier, or <CODE>null</CODE> if there is no such |
| | | * argument. |
| | | */ |
| | | public Argument getGlobalArgumentForShortID(Character shortID) { |
| | | return globalShortIDMap.get(shortID); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the global argument with the specified long identifier. |
| | | * |
| | | * @param longID |
| | | * The long identifier for the global argument to retrieve. |
| | | * @return The global argument with the specified long identifier, or <CODE>null</CODE> if there is no such |
| | | * argument. |
| | | */ |
| | | public Argument getGlobalArgumentForLongID(String longID) { |
| | | return globalLongIDMap.get(longID); |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether this argument parser has a subcommand with the specified name. |
| | | * |
| | | * @param name |
| | | * The subcommand name for which to make the determination. |
| | | * @return <CODE>true</CODE> if this argument parser has a subcommand with the specified name, or <CODE>false</CODE> |
| | | * if it does not. |
| | | */ |
| | | public boolean hasSubCommand(String name) { |
| | | return subCommands.containsKey(name); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the subcommand with the specified name. |
| | | * |
| | | * @param name |
| | | * The name of the subcommand to retrieve. |
| | | * @return The subcommand with the specified name, or <CODE>null</CODE> if no such subcommand is defined. |
| | | */ |
| | | public SubCommand getSubCommand(String name) { |
| | | return subCommands.get(name); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the subcommand that was selected in the set of command-line arguments. |
| | | * |
| | | * @return The subcommand that was selected in the set of command-line arguments, or <CODE>null</CODE> if none was |
| | | * selected. |
| | | */ |
| | | public SubCommand getSubCommand() { |
| | | return subCommand; |
| | | } |
| | | |
| | | /** |
| | | * Adds the provided argument to the set of global arguments handled by this parser. |
| | | * |
| | | * @param argument |
| | | * The argument to be added. |
| | | * @throws ArgumentException |
| | | * If the provided argument conflicts with another global or subcommand argument that has already been |
| | | * defined. |
| | | */ |
| | | public void addGlobalArgument(Argument argument) throws ArgumentException { |
| | | addGlobalArgument(argument, null); |
| | | } |
| | | |
| | | /** |
| | | * 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 add to this sub command. |
| | | * @throws ArgumentException |
| | | * If the provided argument conflicts with another global or subcommand argument that has already been |
| | | * defined. |
| | | */ |
| | | @Override |
| | | public void addLdapConnectionArgument(final Argument argument) throws ArgumentException { |
| | | addGlobalArgument(argument, null); |
| | | } |
| | | |
| | | /** |
| | | * Adds the provided argument to the set of global 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 global or subcommand argument that has already been |
| | | * defined. |
| | | */ |
| | | public void addGlobalArgument(Argument argument, ArgumentGroup group) throws ArgumentException { |
| | | String longID = argument.getLongIdentifier(); |
| | | if (globalArgumentMap.containsKey(longID)) { |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_NAME.get(longID)); |
| | | } |
| | | for (SubCommand s : subCommands.values()) { |
| | | if (s.getArgumentForLongIdentifier(longID) != null) { |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_GLOBAL_ARG_NAME_SUBCMD_CONFLICT.get( |
| | | longID, s.getName())); |
| | | } |
| | | } |
| | | |
| | | Character shortID = argument.getShortIdentifier(); |
| | | if (shortID != null) { |
| | | if (globalShortIDMap.containsKey(shortID)) { |
| | | String conflictingLongID = globalShortIDMap.get(shortID).getLongIdentifier(); |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_SHORT_ID.get( |
| | | shortID, longID, conflictingLongID)); |
| | | } |
| | | |
| | | for (SubCommand s : subCommands.values()) { |
| | | if (s.getArgument(shortID) != null) { |
| | | String conflictingLongID = s.getArgument(shortID).getLongIdentifier(); |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_GLOBAL_ARG_SHORT_ID_CONFLICT.get( |
| | | shortID, longID, conflictingLongID, s.getName())); |
| | | } |
| | | } |
| | | } |
| | | |
| | | if (!longArgumentsCaseSensitive()) { |
| | | longID = toLowerCase(longID); |
| | | if (globalLongIDMap.containsKey(longID)) { |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_LONG_ID.get(longID)); |
| | | } |
| | | } |
| | | |
| | | for (SubCommand s : subCommands.values()) { |
| | | if (s.getArgument(longID) != null) { |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_GLOBAL_ARG_LONG_ID_CONFLICT.get(longID, s.getName())); |
| | | } |
| | | } |
| | | |
| | | if (shortID != null) { |
| | | globalShortIDMap.put(shortID, argument); |
| | | } |
| | | |
| | | if (longID != null) { |
| | | globalLongIDMap.put(longID, argument); |
| | | } |
| | | |
| | | globalArgumentList.add(argument); |
| | | |
| | | if (group == null) { |
| | | group = getStandardGroup(argument); |
| | | } |
| | | group.addArgument(argument); |
| | | argumentGroups.add(group); |
| | | } |
| | | |
| | | /** |
| | | * Sets the provided argument as one which will automatically trigger the output of full usage information if it is |
| | | * provided on the command line and no further argument validation will be performed. |
| | | * <p> |
| | | * If sub-command groups are defined using the {@link #setUsageGroupArgument(Argument, Collection)} method, then |
| | | * this usage argument, when specified, will result in usage information being displayed which does not include |
| | | * information on sub-commands. |
| | | * <p> |
| | | * Note that the caller will still need to add this argument to the parser with the |
| | | * {@link #addGlobalArgument(Argument)} 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 |
| | | * {@link #parseArguments(String[])} to know that no further processing will be required. |
| | | * |
| | | * @param argument |
| | | * The argument whose presence should automatically trigger the display of full usage information. |
| | | * @param outputStream |
| | | * The output stream to which the usage information should be written. |
| | | */ |
| | | @Override |
| | | public void setUsageArgument(Argument argument, OutputStream outputStream) { |
| | | super.setUsageArgument(argument, outputStream); |
| | | usageGroupArguments.put(argument, Collections.<SubCommand>emptySet()); |
| | | } |
| | | |
| | | /** |
| | | * Sets the provided argument as one which will automatically trigger the output of partial usage information if it |
| | | * is provided on the command line and no further argument validation will be performed. |
| | | * <p> |
| | | * Partial usage information will include a usage synopsis, a summary of each of the sub-commands listed in the |
| | | * provided sub-commands collection, and a summary of the global options. |
| | | * <p> |
| | | * Note that the caller will still need to add this argument to the parser with the |
| | | * {@link #addGlobalArgument(Argument)} 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 |
| | | * {@link #parseArguments(String[])} to know that no further processing will be required. |
| | | * |
| | | * @param argument |
| | | * The argument whose presence should automatically trigger the display of partial usage information. |
| | | * @param subCommands |
| | | * The list of sub-commands which should have their usage displayed. |
| | | */ |
| | | public void setUsageGroupArgument(Argument argument, Collection<SubCommand> subCommands) { |
| | | usageGroupArguments.put(argument, subCommands); |
| | | } |
| | | |
| | | /** |
| | | * Sets the sub-command usage handler which will be used to display the usage information. |
| | | * |
| | | * @param subCommandUsageHandler the sub-command usage handler |
| | | */ |
| | | public void setUsageHandler(SubCommandUsageHandler subCommandUsageHandler) { |
| | | this.subCommandUsageHandler = subCommandUsageHandler; |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | @Override |
| | | public void parseArguments(String[] rawArguments, Properties argumentProperties) throws ArgumentException { |
| | | this.subCommand = null; |
| | | final ArrayList<String> trailingArguments = getTrailingArguments(); |
| | | trailingArguments.clear(); |
| | | setUsageOrVersionDisplayed(false); |
| | | |
| | | boolean inTrailingArgs = false; |
| | | |
| | | int numArguments = rawArguments.length; |
| | | for (int i = 0; i < numArguments; i++) { |
| | | final String arg = rawArguments[i]; |
| | | |
| | | if (inTrailingArgs) { |
| | | trailingArguments.add(arg); |
| | | |
| | | if (subCommand == null) { |
| | | throw new ArgumentException(ERR_ARG_SUBCOMMAND_INVALID.get()); |
| | | } |
| | | |
| | | if (subCommand.getMaxTrailingArguments() > 0 |
| | | && trailingArguments.size() > subCommand.getMaxTrailingArguments()) { |
| | | throw new ArgumentException(ERR_ARGPARSER_TOO_MANY_TRAILING_ARGS.get( |
| | | subCommand.getMaxTrailingArguments())); |
| | | } |
| | | |
| | | continue; |
| | | } |
| | | |
| | | if (arg.equals("--")) { |
| | | 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. |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_LONG_ARG_WITHOUT_NAME.get(arg)); |
| | | } else { |
| | | // The argument is in the form --name=value, so parse them both out. |
| | | argValue = argName.substring(equalPos + 1); |
| | | argName = argName.substring(0, equalPos); |
| | | } |
| | | |
| | | // If we're not case-sensitive, then convert the name to lowercase. |
| | | String origArgName = argName; |
| | | if (!longArgumentsCaseSensitive()) { |
| | | argName = toLowerCase(argName); |
| | | } |
| | | |
| | | // See if the specified name references a global argument. If not, then |
| | | // see if it references a subcommand argument. |
| | | Argument a = globalLongIDMap.get(argName); |
| | | if (a == null) { |
| | | if (subCommand != null) { |
| | | a = subCommand.getArgument(argName); |
| | | } |
| | | if (a == null) { |
| | | if (OPTION_LONG_HELP.equals(argName)) { |
| | | // "--help" will always be interpreted as requesting usage |
| | | // information. |
| | | writeToUsageOutputStream(getUsage()); |
| | | return; |
| | | } else if (OPTION_LONG_PRODUCT_VERSION.equals(argName)) { |
| | | // "--version" will always be interpreted as requesting usage information. |
| | | printVersion(); |
| | | return; |
| | | } else if (subCommand != null) { |
| | | // There is no such global argument. |
| | | throw new ArgumentException( |
| | | ERR_SUBCMDPARSER_NO_GLOBAL_ARGUMENT_FOR_LONG_ID.get(origArgName)); |
| | | } else { |
| | | // There is no such global or subcommand argument. |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_NO_ARGUMENT_FOR_LONG_ID.get(origArgName)); |
| | | } |
| | | } |
| | | } |
| | | |
| | | a.setPresent(true); |
| | | |
| | | // If this is a usage argument, then immediately stop and print |
| | | // usage information. |
| | | if (usageGroupArguments.containsKey(a)) { |
| | | getUsage(a); |
| | | 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) { |
| | | throw new ArgumentException( |
| | | ERR_SUBCMDPARSER_NO_VALUE_FOR_ARGUMENT_WITH_LONG_ID.get(argName)); |
| | | } |
| | | |
| | | argValue = rawArguments[++i]; |
| | | } |
| | | |
| | | LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder(); |
| | | if (!a.valueIsAcceptable(argValue, invalidReason)) { |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_VALUE_UNACCEPTABLE_FOR_LONG_ID.get( |
| | | argValue, argName, invalidReason)); |
| | | } |
| | | |
| | | // If the argument already has a value, then make sure it is |
| | | // acceptable to have more than one. |
| | | if (a.hasValue() && !a.isMultiValued()) { |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_NOT_MULTIVALUED_FOR_LONG_ID.get(origArgName)); |
| | | } |
| | | |
| | | a.addValue(argValue); |
| | | } else if (argValue != null) { |
| | | throw new ArgumentException( |
| | | ERR_SUBCMDPARSER_ARG_FOR_LONG_ID_DOESNT_TAKE_VALUE.get(origArgName)); |
| | | } |
| | | } else if (arg.equals("-")) { |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_INVALID_DASH_AS_ARGUMENT.get()); |
| | | } 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 |
| | | 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. It may be either a |
| | | // global argument or a subcommand-specific argument. |
| | | Argument a = globalShortIDMap.get(argCharacter); |
| | | if (a == null) { |
| | | if (subCommand == null) { |
| | | if (argCharacter == '?') { |
| | | // "-?" will always be interpreted as requesting usage. |
| | | writeToUsageOutputStream(getUsage()); |
| | | if (getUsageArgument() != null) { |
| | | getUsageArgument().setPresent(true); |
| | | } |
| | | return; |
| | | } else if (argCharacter == OPTION_SHORT_PRODUCT_VERSION) { |
| | | // "-V" will always be interpreted as requesting |
| | | // version information except if it's already defined. |
| | | if (dashVAccepted()) { |
| | | printVersion(); |
| | | return; |
| | | } else { |
| | | // -V is defined in another subcommand, so we cannot |
| | | // accept it as the version information argument |
| | | throw new ArgumentException( |
| | | ERR_SUBCMDPARSER_NO_GLOBAL_ARGUMENT_FOR_SHORT_ID.get(argCharacter)); |
| | | } |
| | | } else { |
| | | // There is no such argument registered. |
| | | throw new ArgumentException( |
| | | ERR_SUBCMDPARSER_NO_GLOBAL_ARGUMENT_FOR_SHORT_ID.get(argCharacter)); |
| | | } |
| | | } else { |
| | | a = subCommand.getArgument(argCharacter); |
| | | if (a == null) { |
| | | if (argCharacter == '?') { |
| | | // "-?" will always be interpreted as requesting usage. |
| | | writeToUsageOutputStream(getUsage()); |
| | | return; |
| | | } else if (argCharacter == OPTION_SHORT_PRODUCT_VERSION) { |
| | | if (dashVAccepted()) { |
| | | printVersion(); |
| | | return; |
| | | } |
| | | } else { |
| | | // There is no such argument registered. |
| | | throw new ArgumentException( |
| | | ERR_SUBCMDPARSER_NO_ARGUMENT_FOR_SHORT_ID.get(argCharacter)); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | a.setPresent(true); |
| | | |
| | | // If this is the usage argument, then immediately stop and print |
| | | // usage information. |
| | | if (usageGroupArguments.containsKey(a)) { |
| | | getUsage(a); |
| | | 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) { |
| | | throw new ArgumentException( |
| | | ERR_SUBCMDPARSER_NO_VALUE_FOR_ARGUMENT_WITH_SHORT_ID.get(argCharacter)); |
| | | } |
| | | |
| | | argValue = rawArguments[++i]; |
| | | } |
| | | |
| | | LocalizableMessageBuilder invalidReason = new LocalizableMessageBuilder(); |
| | | if (!a.valueIsAcceptable(argValue, invalidReason)) { |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_VALUE_UNACCEPTABLE_FOR_SHORT_ID.get(argValue, |
| | | argCharacter, invalidReason)); |
| | | } |
| | | |
| | | // If the argument already has a value, then make sure it is |
| | | // acceptable to have more than one. |
| | | if (a.hasValue() && !a.isMultiValued()) { |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_NOT_MULTIVALUED_FOR_SHORT_ID.get(argCharacter)); |
| | | } |
| | | |
| | | 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 = globalShortIDMap.get(c); |
| | | if (b == null) { |
| | | if (subCommand == null) { |
| | | throw new ArgumentException( |
| | | ERR_SUBCMDPARSER_NO_GLOBAL_ARGUMENT_FOR_SHORT_ID.get(argCharacter)); |
| | | } |
| | | b = subCommand.getArgument(c); |
| | | if (b == null) { |
| | | throw new ArgumentException( |
| | | ERR_SUBCMDPARSER_NO_ARGUMENT_FOR_SHORT_ID.get(argCharacter)); |
| | | } |
| | | } |
| | | |
| | | 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. |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_CANT_MIX_ARGS_WITH_VALUES.get( |
| | | argCharacter, argValue, c)); |
| | | } |
| | | b.setPresent(true); |
| | | |
| | | // If this is the usage argument, then immediately stop and |
| | | // print usage information. |
| | | if (usageGroupArguments.containsKey(b)) { |
| | | getUsage(b); |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | } else if (subCommand != null) { |
| | | // It's not a short or long identifier and the sub-command has |
| | | // already been specified, so it must be the first trailing argument. |
| | | if (subCommand.allowsTrailingArguments()) { |
| | | trailingArguments.add(arg); |
| | | inTrailingArgs = true; |
| | | } else { |
| | | // Trailing arguments are not allowed for this sub-command. |
| | | throw new ArgumentException(ERR_ARGPARSER_DISALLOWED_TRAILING_ARGUMENT.get(arg)); |
| | | } |
| | | } else { |
| | | // It must be the sub-command. |
| | | String nameToCheck = arg; |
| | | if (!longArgumentsCaseSensitive()) { |
| | | nameToCheck = toLowerCase(arg); |
| | | } |
| | | |
| | | SubCommand sc = subCommands.get(nameToCheck); |
| | | if (sc == null) { |
| | | throw new ArgumentException(ERR_SUBCMDPARSER_INVALID_ARGUMENT.get(arg)); |
| | | } |
| | | subCommand = sc; |
| | | } |
| | | } |
| | | |
| | | // If we have a sub-command and it allows trailing arguments and |
| | | // there is a minimum number, then make sure at least that many |
| | | // were provided. |
| | | if (subCommand != null) { |
| | | int minTrailingArguments = subCommand.getMinTrailingArguments(); |
| | | if (subCommand.allowsTrailingArguments() |
| | | && minTrailingArguments > 0 |
| | | && trailingArguments.size() < minTrailingArguments) { |
| | | throw new ArgumentException(ERR_ARGPARSER_TOO_FEW_TRAILING_ARGUMENTS.get(minTrailingArguments)); |
| | | } |
| | | } |
| | | |
| | | // If we don't have the argumentProperties, try to load a properties file. |
| | | if (argumentProperties == null) { |
| | | argumentProperties = checkExternalProperties(); |
| | | } |
| | | |
| | | // Iterate through all the global arguments |
| | | normalizeArguments(argumentProperties, globalArgumentList); |
| | | |
| | | // Iterate through all the subcommand-specific arguments |
| | | if (subCommand != null) { |
| | | normalizeArguments(argumentProperties, subCommand.getArguments()); |
| | | } |
| | | } |
| | | |
| | | private boolean dashVAccepted() { |
| | | if (globalShortIDMap.containsKey(OPTION_SHORT_PRODUCT_VERSION)) { |
| | | return false; |
| | | } |
| | | for (SubCommand subCmd : subCommands.values()) { |
| | | if (subCmd.getArgument(OPTION_SHORT_PRODUCT_VERSION) != null) { |
| | | return false; |
| | | } |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | /** |
| | | * Appends usage information for the specified subcommand to the provided buffer. |
| | | * |
| | | * @param buffer |
| | | * The buffer to which the usage information should be appended. |
| | | * @param subCommand |
| | | * The subcommand for which to display the usage information. |
| | | */ |
| | | public void getSubCommandUsage(StringBuilder buffer, SubCommand subCommand) { |
| | | buffer.append(getLocalizableScriptName()); |
| | | buffer.append(" "); |
| | | buffer.append(subCommand.getName()); |
| | | buffer.append(" ").append(INFO_SUBCMDPARSER_OPTIONS.get()); |
| | | if (subCommand.allowsTrailingArguments()) { |
| | | buffer.append(' '); |
| | | buffer.append(subCommand.getTrailingArgumentsDisplayName()); |
| | | } |
| | | buffer.append(EOL); |
| | | wrap(buffer, subCommand.getDescription()); |
| | | buffer.append(EOL); |
| | | |
| | | if (!globalArgumentList.isEmpty()) { |
| | | buffer.append(EOL); |
| | | buffer.append(INFO_GLOBAL_OPTIONS.get()); |
| | | buffer.append(EOL); |
| | | buffer.append(" "); |
| | | buffer.append(INFO_GLOBAL_OPTIONS_REFERENCE.get(getScriptNameOrJava())); |
| | | buffer.append(EOL); |
| | | } |
| | | |
| | | if (!subCommand.getArguments().isEmpty()) { |
| | | buffer.append(EOL); |
| | | buffer.append(INFO_SUBCMD_OPTIONS.get()); |
| | | buffer.append(EOL); |
| | | } |
| | | |
| | | for (Argument a : subCommand.getArguments()) { |
| | | // If this argument is hidden, then skip it. |
| | | if (a.isHidden()) { |
| | | continue; |
| | | } |
| | | |
| | | printLineForShortLongArgument(a, buffer); |
| | | |
| | | indentAndWrap(buffer, INDENT, a.getDescription()); |
| | | if (a.needsValue() && a.getDefaultValue() != null && a.getDefaultValue().length() > 0) { |
| | | indentAndWrap(buffer, INDENT, INFO_ARGPARSER_USAGE_DEFAULT_VALUE.get(a.getDefaultValue())); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a string containing usage information based on the defined arguments. |
| | | * |
| | | * @return A string containing usage information based on the defined arguments. |
| | | */ |
| | | @Override |
| | | public String getUsage() { |
| | | setUsageOrVersionDisplayed(true); |
| | | |
| | | final StringBuilder buffer = new StringBuilder(); |
| | | if (subCommand == null) { |
| | | if (System.getProperty("org.forgerock.opendj.gendoc") != null) { |
| | | generateReferenceDoc(buffer, subCommands.values()); |
| | | } else if (usageGroupArguments.size() > 1) { |
| | | // We have sub-command groups, so don't display any |
| | | // sub-commands by default. |
| | | getFullUsage(Collections.<SubCommand> emptySet(), true, buffer); |
| | | } else { |
| | | // No grouping, so display all sub-commands. |
| | | getFullUsage(subCommands.values(), true, buffer); |
| | | } |
| | | } else { |
| | | getSubCommandUsage(buffer, subCommand); |
| | | } |
| | | return buffer.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Adds the provided subcommand to this argument parser. This is only intended for use by the |
| | | * <CODE>SubCommand</CODE> constructor and does not do any validation of its own to ensure that there are no |
| | | * conflicts with the subcommand or any of its arguments. |
| | | * |
| | | * @param subCommand |
| | | * The subcommand to add to this argument parser. |
| | | */ |
| | | void addSubCommand(SubCommand subCommand) { |
| | | subCommands.put(toLowerCase(subCommand.getName()), subCommand); |
| | | } |
| | | |
| | | /** Get usage for a specific usage argument. */ |
| | | private void getUsage(Argument a) { |
| | | setUsageOrVersionDisplayed(true); |
| | | |
| | | final StringBuilder buffer = new StringBuilder(); |
| | | final boolean isUsageArgument = isUsageArgument(a); |
| | | if (isUsageArgument && subCommand != null) { |
| | | getSubCommandUsage(buffer, subCommand); |
| | | } else if (isUsageArgument && usageGroupArguments.size() <= 1) { |
| | | // No groups - so display all sub-commands. |
| | | getFullUsage(subCommands.values(), true, buffer); |
| | | } else if (isUsageArgument) { |
| | | // Using groups - so display all sub-commands group help. |
| | | getFullUsage(Collections.<SubCommand> emptySet(), true, buffer); |
| | | } else { |
| | | // Requested help on specific group - don't display global options. |
| | | getFullUsage(usageGroupArguments.get(a), false, buffer); |
| | | } |
| | | writeToUsageOutputStream(buffer); |
| | | } |
| | | |
| | | /** Appends complete usage information for the specified set of sub-commands. */ |
| | | private void getFullUsage(Collection<SubCommand> c, boolean showGlobalOptions, StringBuilder buffer) { |
| | | final LocalizableMessage toolDescription = getToolDescription(); |
| | | if (toolDescription != null && toolDescription.length() > 0) { |
| | | buffer.append(wrapText(toolDescription, MAX_LINE_WIDTH - 1)); |
| | | buffer.append(EOL).append(EOL); |
| | | } |
| | | |
| | | buffer.append(INFO_ARGPARSER_USAGE.get()); |
| | | buffer.append(" "); |
| | | buffer.append(getScriptNameOrJava()); |
| | | |
| | | if (subCommands.isEmpty()) { |
| | | buffer.append(" ").append(INFO_SUBCMDPARSER_OPTIONS.get()); |
| | | } else { |
| | | buffer.append(" ").append(INFO_SUBCMDPARSER_SUBCMD_AND_OPTIONS.get()); |
| | | } |
| | | |
| | | if (!subCommands.isEmpty()) { |
| | | buffer.append(EOL); |
| | | buffer.append(EOL); |
| | | if (c.isEmpty()) { |
| | | buffer.append(INFO_SUBCMDPARSER_SUBCMD_HELP_HEADING.get()); |
| | | } else { |
| | | buffer.append(INFO_SUBCMDPARSER_SUBCMD_HEADING.get()); |
| | | } |
| | | buffer.append(EOL); |
| | | } |
| | | |
| | | if (c.isEmpty()) { |
| | | // Display usage arguments (except the default one). |
| | | for (Argument a : globalArgumentList) { |
| | | if (a.isHidden()) { |
| | | continue; |
| | | } |
| | | |
| | | if (usageGroupArguments.containsKey(a) && !isUsageArgument(a)) { |
| | | printArgumentUsage(a, buffer); |
| | | } |
| | | } |
| | | } else { |
| | | boolean isFirst = true; |
| | | for (SubCommand sc : c) { |
| | | if (sc.isHidden()) { |
| | | continue; |
| | | } |
| | | if (isFirst) { |
| | | buffer.append(EOL); |
| | | } |
| | | buffer.append(sc.getName()); |
| | | buffer.append(EOL); |
| | | indentAndWrap(buffer, INDENT, sc.getDescription()); |
| | | buffer.append(EOL); |
| | | isFirst = false; |
| | | } |
| | | } |
| | | |
| | | buffer.append(EOL); |
| | | |
| | | if (showGlobalOptions) { |
| | | if (subCommands.isEmpty()) { |
| | | buffer.append(INFO_SUBCMDPARSER_WHERE_OPTIONS_INCLUDE.get()); |
| | | } else { |
| | | buffer.append(INFO_SUBCMDPARSER_GLOBAL_HEADING.get()); |
| | | } |
| | | buffer.append(EOL).append(EOL); |
| | | |
| | | boolean printGroupHeaders = printUsageGroupHeaders(); |
| | | |
| | | // Display non-usage arguments. |
| | | for (ArgumentGroup argGroup : argumentGroups) { |
| | | if (argGroup.containsArguments() && printGroupHeaders) { |
| | | // Print the groups description if any |
| | | LocalizableMessage groupDesc = argGroup.getDescription(); |
| | | if (groupDesc != null && !LocalizableMessage.EMPTY.equals(groupDesc)) { |
| | | buffer.append(EOL); |
| | | buffer.append(wrapText(groupDesc.toString(), MAX_LINE_WIDTH - 1)); |
| | | buffer.append(EOL).append(EOL); |
| | | } |
| | | } |
| | | |
| | | for (Argument a : argGroup.getArguments()) { |
| | | if (a.isHidden()) { |
| | | continue; |
| | | } |
| | | |
| | | if (!usageGroupArguments.containsKey(a)) { |
| | | printArgumentUsage(a, buffer); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // Finally print default usage argument. |
| | | final Argument usageArgument = getUsageArgument(); |
| | | if (usageArgument != null) { |
| | | printArgumentUsage(usageArgument, buffer); |
| | | } else { |
| | | buffer.append("-?"); |
| | | } |
| | | buffer.append(EOL); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | */ |
| | | private void printArgumentUsage(Argument a, StringBuilder buffer) { |
| | | String value; |
| | | if (a.needsValue()) { |
| | | LocalizableMessage pHolder = a.getValuePlaceholder(); |
| | | if (pHolder != null) { |
| | | value = " " + pHolder; |
| | | } else { |
| | | value = " {value}"; |
| | | } |
| | | } else { |
| | | value = ""; |
| | | } |
| | | |
| | | final Argument usageArgument = getUsageArgument(); |
| | | Character shortIDChar = a.getShortIdentifier(); |
| | | if (shortIDChar != null) { |
| | | if (a.equals(usageArgument)) { |
| | | buffer.append("-?, "); |
| | | } |
| | | buffer.append("-"); |
| | | buffer.append(shortIDChar); |
| | | |
| | | String longIDString = a.getLongIdentifier(); |
| | | if (longIDString != null) { |
| | | buffer.append(", --"); |
| | | buffer.append(longIDString); |
| | | } |
| | | buffer.append(value); |
| | | } else { |
| | | String longIDString = a.getLongIdentifier(); |
| | | if (longIDString != null) { |
| | | if (a.equals(usageArgument)) { |
| | | buffer.append("-?, "); |
| | | } |
| | | buffer.append("--"); |
| | | buffer.append(longIDString); |
| | | buffer.append(value); |
| | | } |
| | | } |
| | | |
| | | buffer.append(EOL); |
| | | |
| | | indentAndWrap(buffer, INDENT, a.getDescription()); |
| | | if (a.needsValue() && a.getDefaultValue() != null && a.getDefaultValue().length() > 0) { |
| | | indentAndWrap(buffer, INDENT, INFO_ARGPARSER_USAGE_DEFAULT_VALUE.get(a.getDefaultValue())); |
| | | } |
| | | } |
| | | |
| | | /** Wraps long lines without indentation. */ |
| | | private void wrap(StringBuilder buffer, LocalizableMessage text) { |
| | | indentAndWrap(buffer, "", text); |
| | | } |
| | | |
| | | /** |
| | | * Write one or more lines with the description of the argument. We will 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. |
| | | * <p> |
| | | * FIXME consider merging with com.forgerock.opendj.cli.Utils#wrapText(String, int, int) |
| | | */ |
| | | private void indentAndWrap(StringBuilder buffer, String indent, LocalizableMessage text) { |
| | | int actualSize = MAX_LINE_WIDTH - indent.length() - COLUMN_ADJUST; |
| | | indentAndWrap(indent, buffer, actualSize, text); |
| | | } |
| | | |
| | | static void indentAndWrap(String indent, StringBuilder buffer, int actualSize, LocalizableMessage text) { |
| | | if (text.length() <= actualSize) { |
| | | buffer.append(indent); |
| | | buffer.append(text); |
| | | buffer.append(EOL); |
| | | } else { |
| | | String s = text.toString(); |
| | | while (s.length() > actualSize) { |
| | | int spacePos = s.lastIndexOf(' ', actualSize); |
| | | if (spacePos == -1) { |
| | | // There are no spaces in the first actualSize -1 columns. |
| | | // See if there is one after that point. |
| | | // If so, then break there. If not, then don't break at all. |
| | | spacePos = s.indexOf(' '); |
| | | } |
| | | if (spacePos == -1) { |
| | | buffer.append(indent).append(s).append(EOL); |
| | | return; |
| | | } |
| | | buffer.append(indent); |
| | | buffer.append(s.substring(0, spacePos).trim()); |
| | | s = s.substring(spacePos + 1).trim(); |
| | | buffer.append(EOL); |
| | | } |
| | | |
| | | if (s.length() > 0) { |
| | | buffer.append(indent).append(s).append(EOL); |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Appends a generated DocBook XML RefEntry element for this command to the StringBuilder. |
| | | * |
| | | * @param builder Append the RefEntry element to this. |
| | | * @param subCommands SubCommands containing reference information. |
| | | */ |
| | | private void generateReferenceDoc(final StringBuilder builder, Collection<SubCommand> subCommands) { |
| | | toRefEntry(builder, subCommands); |
| | | } |
| | | |
| | | @Override |
| | | String getSynopsisArgs() { |
| | | if (subCommands.isEmpty()) { |
| | | return INFO_SUBCMDPARSER_OPTIONS.get().toString(); |
| | | } else { |
| | | return INFO_SUBCMDPARSER_SUBCMD_AND_OPTIONS.get().toString(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Appends one or more generated DocBook XML RefEntry elements (man pages) to the StringBuilder. |
| | | * <br> |
| | | * If the result contains more than one RefEntry, |
| | | * then the RefEntry elements are separated with a marker: |
| | | * {@code @@@scriptName + "-" + subCommand.getName() + @@@}. |
| | | * |
| | | * @param builder Append the RefEntry element to this. |
| | | * @param subCommands Collection of subcommands for this tool. |
| | | */ |
| | | void toRefEntry(StringBuilder builder, Collection<SubCommand> subCommands) { |
| | | final String scriptName = getScriptName(); |
| | | if (scriptName == null) { |
| | | throw new RuntimeException("The script name should have been set via the environment property '" |
| | | + PROPERTY_SCRIPT_NAME + "'."); |
| | | } |
| | | |
| | | // Model for a FreeMarker template. |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("locale", Locale.getDefault().getLanguage()); |
| | | map.put("year", new SimpleDateFormat("yyyy").format(new Date())); |
| | | map.put("name", scriptName); |
| | | map.put("shortDesc", getShortToolDescription()); |
| | | map.put("descTitle", REF_TITLE_DESCRIPTION.get()); |
| | | map.put("args", getSynopsisArgs()); |
| | | map.put("description", eolToNewPara(getToolDescription())); |
| | | map.put("info", getDocToolDescriptionSupplement()); |
| | | if (!globalArgumentList.isEmpty()) { |
| | | map.put("optionSection", getOptionsRefSect1(scriptName)); |
| | | } |
| | | map.put("subcommands", toRefSect1(scriptName, subCommands)); |
| | | map.put("trailingSectionString", System.getProperty("org.forgerock.opendj.gendoc.trailing")); |
| | | applyTemplate(builder, "refEntry.ftl", map); |
| | | |
| | | // For dsconfig, generate one page per subcommand. |
| | | if (scriptName.equals("dsconfig")) { |
| | | appendSubCommandPages(builder, scriptName, subCommands); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns a generated DocBook XML RefSect1 element for all subcommands. |
| | | * @param scriptName The name of this script. |
| | | * @param subCommands The SubCommands containing the reference information. |
| | | * @return The RefSect1 element as a String. |
| | | */ |
| | | private String toRefSect1(String scriptName, Collection<SubCommand> subCommands) { |
| | | if (subCommands.isEmpty()) { |
| | | return ""; |
| | | } |
| | | |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("name", scriptName); |
| | | map.put("title", REF_TITLE_SUBCOMMANDS.get()); |
| | | map.put("info", getDocSubcommandsDescriptionSupplement()); |
| | | map.put("intro", REF_INTRO_SUBCOMMANDS.get(scriptName)); |
| | | if (scriptName.equals("dsconfig")) { |
| | | // Break dsconfig into multiple pages, so use only the list here. |
| | | map.put("isItemizedList", true); |
| | | } |
| | | List<String> scUsageList = new ArrayList<>(); |
| | | for (SubCommand subCommand : subCommands) { |
| | | if (subCommand.isHidden()) { |
| | | continue; |
| | | } |
| | | if (scriptName.equals("dsconfig")) { |
| | | scUsageList.add(getSubCommandListItem(scriptName, subCommand)); |
| | | } else { |
| | | scUsageList.add(toRefSect2(scriptName, subCommand)); |
| | | } |
| | | } |
| | | map.put("subcommands", scUsageList); |
| | | |
| | | StringBuilder sb = new StringBuilder(); |
| | | applyTemplate(sb, "refSect1.ftl", map); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Returns a DocBook XML ListItem element linking to the subcommand page. |
| | | * @param scriptName The name of this script. |
| | | * @param subCommand The SubCommand to reference. |
| | | * @return A DocBook XML ListItem element linking to the subcommand page. |
| | | */ |
| | | private String getSubCommandListItem(String scriptName, SubCommand subCommand) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("id", scriptName + "-" + subCommand.getName()); |
| | | map.put("name", scriptName + " " + subCommand.getName()); |
| | | map.put("description", eolToNewPara(subCommand.getDescription())); |
| | | StringBuilder sb = new StringBuilder(); |
| | | applyTemplate(sb, "dscfgListItem.ftl", map); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Returns a generated DocBook XML RefSect2 element for a single subcommand to the StringBuilder. |
| | | * |
| | | * @param scriptName The name of this script. |
| | | * @param subCommand The SubCommand containing reference information. |
| | | * @return The RefSect2 element as a String. |
| | | */ |
| | | private String toRefSect2(String scriptName, SubCommand subCommand) { |
| | | // Model for a FreeMarker template. |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("id", scriptName + "-" + subCommand.getName()); |
| | | final String name = scriptName + " " + subCommand.getName(); |
| | | map.put("name", name); |
| | | map.put("description", eolToNewPara(subCommand.getDescription())); |
| | | map.put("optionsTitle", REF_TITLE_OPTIONS.get()); |
| | | map.put("optionsIntro", REF_INTRO_OPTIONS.get(name)); |
| | | |
| | | // If there is a supplement to the description for this subcommand, |
| | | // then it is already DocBook XML, so use it as is. |
| | | map.put("info", subCommand.getDocDescriptionSupplement()); |
| | | setSubCommandOptionsInfo(map, subCommand); |
| | | |
| | | StringBuilder sb = new StringBuilder(); |
| | | applyTemplate(sb, "refSect2.ftl", map); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Sets information for the subcommand options in the map. |
| | | * <br> |
| | | * The map is expected to be used in a FreeMarker template to generate docs. |
| | | * |
| | | * @param map The map in which to set the information. |
| | | * @param subCommand The subcommand containing the information. |
| | | */ |
| | | private void setSubCommandOptionsInfo(Map<String, Object> map, SubCommand subCommand) { |
| | | if (!subCommand.getArguments().isEmpty()) { |
| | | List<Map<String, Object>> options = new LinkedList<>(); |
| | | String nameOption = null; |
| | | for (Argument a : subCommand.getArguments()) { |
| | | if (a.isHidden()) { |
| | | continue; |
| | | } |
| | | |
| | | Map<String, Object> option = new HashMap<>(); |
| | | String optionSynopsis = getOptionSynopsis(a); |
| | | option.put("synopsis", optionSynopsis); |
| | | option.put("description", eolToNewPara(a.getDescription())); |
| | | Map<String, Object> info = new HashMap<>(); |
| | | if (subCommandUsageHandler != null) { |
| | | if (!doesHandleProperties(a)) { |
| | | nameOption = "<option>" + optionSynopsis + "</option>"; |
| | | } |
| | | |
| | | // Let this build its own arbitrarily formatted additional info. |
| | | info.put("usage", subCommandUsageHandler.getArgumentAdditionalInfo(subCommand, a, nameOption)); |
| | | } else { |
| | | // Return a generic FQDN for localhost as the default hostname in reference documentation. |
| | | final String defaultValue = isHostNameArgument(a) ? "localhost.localdomain" : a.getDefaultValue(); |
| | | info.put("default", defaultValue != null ? REF_DEFAULT.get(defaultValue) : null); |
| | | |
| | | // If there is a supplement to the description for this argument, |
| | | // then it is already DocBook XML, so use it as is. |
| | | info.put("doc", a.getDocDescriptionSupplement()); |
| | | } |
| | | option.put("info", info); |
| | | options.add(option); |
| | | } |
| | | map.put("options", options); |
| | | } |
| | | |
| | | if (subCommandUsageHandler != null) { |
| | | map.put("propertiesInfo", subCommandUsageHandler.getProperties(subCommand)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Appends a generated DocBook XML RefEntry element for each subcommand to the StringBuilder. |
| | | * <br> |
| | | * The RefEntry elements are separated with a marker: |
| | | * {@code @@@scriptName + "-" + subCommand.getName() + @@@}. |
| | | * |
| | | * @param builder Append the RefEntry elements to this. |
| | | * @param scriptName The name of the tool with subcommands. |
| | | * @param subCommands SubCommands containing reference information. |
| | | */ |
| | | private void appendSubCommandPages(StringBuilder builder, String scriptName, Collection<SubCommand> subCommands) { |
| | | for (SubCommand subCommand : subCommands) { |
| | | if (subCommand.isHidden()) { |
| | | continue; |
| | | } |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("marker", "@@@" + scriptName + "-" + subCommand.getName() + "@@@"); |
| | | map.put("locale", Locale.getDefault().getLanguage()); |
| | | map.put("year", new SimpleDateFormat("yyyy").format(new Date())); |
| | | map.put("id", scriptName + "-" + subCommand.getName()); |
| | | map.put("name", scriptName + " " + subCommand.getName()); |
| | | map.put("purpose", eolToNewPara(subCommand.getDescription())); |
| | | map.put("args", INFO_SUBCMDPARSER_OPTIONS.get()); |
| | | map.put("descTitle", REF_TITLE_DESCRIPTION.get()); |
| | | map.put("description", eolToNewPara(subCommand.getDescription())); |
| | | map.put("info", subCommand.getDocDescriptionSupplement()); |
| | | map.put("optionsTitle", REF_TITLE_OPTIONS.get()); |
| | | map.put("optionsIntro", REF_INTRO_OPTIONS.get(scriptName + " " + subCommand.getName())); |
| | | setSubCommandOptionsInfo(map, subCommand); |
| | | applyTemplate(builder, "dscfgSubcommand.ftl", map); |
| | | } |
| | | appendSubCommandReference(builder, scriptName, subCommands); |
| | | } |
| | | |
| | | /** |
| | | * Appends a generated DocBook XML Reference element XIncluding subcommands. |
| | | * |
| | | * @param builder Append the Reference element to this. |
| | | * @param scriptName The name of the tool with subcommands. |
| | | * @param subCommands SubCommands containing reference information. |
| | | */ |
| | | private void appendSubCommandReference(StringBuilder builder, |
| | | String scriptName, |
| | | Collection<SubCommand> subCommands) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | map.put("marker", "@@@" + scriptName + "-subcommands-ref" + "@@@"); |
| | | map.put("name", scriptName); |
| | | map.put("locale", Locale.getDefault().getLanguage()); |
| | | map.put("title", REF_PART_TITLE_SUBCOMMANDS.get(scriptName)); |
| | | map.put("partintro", REF_PART_INTRO_SUBCOMMANDS.get(scriptName)); |
| | | List<Map<String, Object>> commands = new LinkedList<>(); |
| | | for (SubCommand subCommand : subCommands) { |
| | | Map<String, Object> scMap = new HashMap<>(); |
| | | scMap.put("id", scriptName + "-" + subCommand.getName()); |
| | | commands.add(scMap); |
| | | } |
| | | map.put("subcommands", commands); |
| | | applyTemplate(builder, "dscfgReference.ftl", map); |
| | | } |
| | | |
| | | @Override |
| | | public void replaceArgument(final Argument argument) { |
| | | replaceArgumentInCollections(globalLongIDMap, globalShortIDMap, globalArgumentList, argument); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2015 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | /** |
| | | * A handler for printing sub-command usage information. |
| | | */ |
| | | //@FunctionalInterface |
| | | public interface SubCommandUsageHandler { |
| | | |
| | | /** |
| | | * Returns properties information for the sub-command. |
| | | * |
| | | * @param subCommand |
| | | * the sub command for which to print usage information |
| | | * @return The properties information for the sub-command. |
| | | */ |
| | | String getProperties(SubCommand subCommand); |
| | | |
| | | /** |
| | | * Returns additional information for the provided sub-command argument. |
| | | * |
| | | * @param subCommand |
| | | * the sub command for which to print usage information |
| | | * @param arg |
| | | * the argument for which to append additional information |
| | | * @param nameOption |
| | | * the string representing the name option |
| | | * @return The additional information for the sub-command argument. |
| | | */ |
| | | String getArgumentAdditionalInfo(SubCommand subCommand, Argument arg, String nameOption); |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.io.BufferedWriter; |
| | | import java.io.OutputStream; |
| | | import java.io.OutputStreamWriter; |
| | | import java.io.PrintWriter; |
| | | import java.io.Writer; |
| | | |
| | | /** |
| | | * An interface for creating a tab-separated formatted table. |
| | | * <p> |
| | | * This table printer will replace any tab, line-feeds, or carriage return control characters encountered in a cell with |
| | | * a single space. |
| | | */ |
| | | public final class TabSeparatedTablePrinter extends TablePrinter { |
| | | /** Table serializer implementation. */ |
| | | private final class Serializer extends TableSerializer { |
| | | /** |
| | | * Counts the number of separators that should be output the next time a non-empty cell is displayed. The tab |
| | | * separators are not displayed immediately so that we can avoid displaying unnecessary trailing separators. |
| | | */ |
| | | private int requiredSeparators; |
| | | |
| | | /** Private constructor. */ |
| | | private Serializer() { |
| | | // No implementation required. |
| | | } |
| | | |
| | | @Override |
| | | public void addCell(String s) { |
| | | // Avoid printing tab separators for trailing empty cells. |
| | | if (s.length() == 0) { |
| | | requiredSeparators++; |
| | | } else { |
| | | for (int i = 0; i < requiredSeparators; i++) { |
| | | writer.print('\t'); |
| | | } |
| | | requiredSeparators = 1; |
| | | } |
| | | |
| | | // Replace all new-lines and tabs with a single space. |
| | | writer.print(s.replaceAll("[\\t\\n\\r]", " ")); |
| | | } |
| | | |
| | | @Override |
| | | public void addHeading(String s) { |
| | | if (displayHeadings) { |
| | | addCell(s); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void endHeader() { |
| | | if (displayHeadings) { |
| | | writer.println(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void endRow() { |
| | | writer.println(); |
| | | } |
| | | |
| | | @Override |
| | | public void endTable() { |
| | | writer.flush(); |
| | | } |
| | | |
| | | @Override |
| | | public void startHeader() { |
| | | requiredSeparators = 0; |
| | | } |
| | | |
| | | @Override |
| | | public void startRow() { |
| | | requiredSeparators = 0; |
| | | } |
| | | } |
| | | |
| | | /** Indicates whether or not the headings should be output. */ |
| | | private boolean displayHeadings; |
| | | |
| | | /** The output destination. */ |
| | | private PrintWriter writer; |
| | | |
| | | /** |
| | | * Creates a new tab separated table printer for the specified output stream. Headings will not be displayed by |
| | | * default. |
| | | * |
| | | * @param stream |
| | | * The stream to output tables to. |
| | | */ |
| | | public TabSeparatedTablePrinter(OutputStream stream) { |
| | | this(new BufferedWriter(new OutputStreamWriter(stream))); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new tab separated table printer for the specified writer. Headings will not be displayed by default. |
| | | * |
| | | * @param writer |
| | | * The writer to output tables to. |
| | | */ |
| | | public TabSeparatedTablePrinter(Writer writer) { |
| | | this.writer = new PrintWriter(writer); |
| | | } |
| | | |
| | | /** |
| | | * Specify whether or not table headings should be displayed. |
| | | * |
| | | * @param displayHeadings |
| | | * <code>true</code> if table headings should be displayed. |
| | | */ |
| | | public void setDisplayHeadings(boolean displayHeadings) { |
| | | this.displayHeadings = displayHeadings; |
| | | } |
| | | |
| | | @Override |
| | | protected TableSerializer getSerializer() { |
| | | return new Serializer(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.Comparator; |
| | | import java.util.List; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * A class which can be used to construct tables of information to be displayed in a terminal. |
| | | * Once built the table can be output using a {@link TableSerializer}. |
| | | */ |
| | | public final class TableBuilder { |
| | | |
| | | /** |
| | | * The current column number in the current row where 0 represents |
| | | * the left-most column in the table. |
| | | */ |
| | | private int column; |
| | | |
| | | /** The current with of each column. */ |
| | | private List<Integer> columnWidths = new ArrayList<>(); |
| | | |
| | | /** The list of column headings. */ |
| | | private List<LocalizableMessage> header = new ArrayList<>(); |
| | | |
| | | /** The current number of rows in the table. */ |
| | | private int height; |
| | | |
| | | /** The list of table rows. */ |
| | | private List<List<String>> rows = new ArrayList<>(); |
| | | |
| | | /** The linked list of sort keys comparators. */ |
| | | private List<Comparator<String>> sortComparators = new ArrayList<>(); |
| | | |
| | | /** The linked list of sort keys. */ |
| | | private List<Integer> sortKeys = new ArrayList<>(); |
| | | |
| | | /** The current number of columns in the table. */ |
| | | private int width; |
| | | |
| | | /** |
| | | * Creates a new table printer. |
| | | */ |
| | | public TableBuilder() { |
| | | // No implementation required. |
| | | } |
| | | |
| | | /** |
| | | * Adds a table sort key. The table will be sorted according to the case-insensitive string ordering of the cells in |
| | | * the specified column. |
| | | * |
| | | * @param column |
| | | * The column which will be used as a sort key. |
| | | */ |
| | | public void addSortKey(int column) { |
| | | addSortKey(column, String.CASE_INSENSITIVE_ORDER); |
| | | } |
| | | |
| | | /** |
| | | * Adds a table sort key. The table will be sorted according to the provided string comparator. |
| | | * |
| | | * @param column |
| | | * The column which will be used as a sort key. |
| | | * @param comparator |
| | | * The string comparator. |
| | | */ |
| | | public void addSortKey(int column, Comparator<String> comparator) { |
| | | sortKeys.add(column); |
| | | sortComparators.add(comparator); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new blank cell to the current row. |
| | | */ |
| | | public void appendCell() { |
| | | appendCell(""); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new cell to the current row containing the provided boolean value. |
| | | * |
| | | * @param value |
| | | * The boolean value. |
| | | */ |
| | | public void appendCell(boolean value) { |
| | | appendCell(String.valueOf(value)); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new cell to the current row containing the provided byte value. |
| | | * |
| | | * @param value |
| | | * The byte value. |
| | | */ |
| | | public void appendCell(byte value) { |
| | | appendCell(String.valueOf(value)); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new cell to the current row containing the provided char value. |
| | | * |
| | | * @param value |
| | | * The char value. |
| | | */ |
| | | public void appendCell(char value) { |
| | | appendCell(String.valueOf(value)); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new cell to the current row containing the provided double value. |
| | | * |
| | | * @param value |
| | | * The double value. |
| | | */ |
| | | public void appendCell(double value) { |
| | | appendCell(String.valueOf(value)); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new cell to the current row containing the provided float value. |
| | | * |
| | | * @param value |
| | | * The float value. |
| | | */ |
| | | public void appendCell(float value) { |
| | | appendCell(String.valueOf(value)); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new cell to the current row containing the provided integer value. |
| | | * |
| | | * @param value |
| | | * The boolean value. |
| | | */ |
| | | public void appendCell(int value) { |
| | | appendCell(String.valueOf(value)); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new cell to the current row containing the provided long value. |
| | | * |
| | | * @param value |
| | | * The long value. |
| | | */ |
| | | public void appendCell(long value) { |
| | | appendCell(String.valueOf(value)); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new cell to the current row containing the provided object value. |
| | | * |
| | | * @param value |
| | | * The object value. |
| | | */ |
| | | public void appendCell(Object value) { |
| | | // Make sure that the first row has been created. |
| | | if (height == 0) { |
| | | startRow(); |
| | | } |
| | | |
| | | // Create the cell. |
| | | String s = String.valueOf(value); |
| | | rows.get(height - 1).add(s); |
| | | column++; |
| | | |
| | | // Update statistics. |
| | | if (column > width) { |
| | | width = column; |
| | | columnWidths.add(s.length()); |
| | | } else if (columnWidths.get(column - 1) < s.length()) { |
| | | columnWidths.set(column - 1, s.length()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Appends a new blank column heading to the header row. |
| | | */ |
| | | public void appendHeading() { |
| | | appendHeading(LocalizableMessage.EMPTY); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new column heading to the header row. |
| | | * |
| | | * @param value |
| | | * The column heading value. |
| | | */ |
| | | public void appendHeading(LocalizableMessage value) { |
| | | header.add(value); |
| | | |
| | | // Update statistics. |
| | | if (header.size() > width) { |
| | | width = header.size(); |
| | | columnWidths.add(value.length()); |
| | | } else if (columnWidths.get(header.size() - 1) < value.length()) { |
| | | columnWidths.set(header.size() - 1, value.length()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Gets the width of the current row. |
| | | * |
| | | * @return Returns the width of the current row. |
| | | */ |
| | | public int getRowWidth() { |
| | | return column; |
| | | } |
| | | |
| | | /** |
| | | * Gets the number of rows in table. |
| | | * |
| | | * @return Returns the number of rows in table. |
| | | */ |
| | | public int getTableHeight() { |
| | | return height; |
| | | } |
| | | |
| | | /** |
| | | * Gets the number of columns in table. |
| | | * |
| | | * @return Returns the number of columns in table. |
| | | */ |
| | | public int getTableWidth() { |
| | | return width; |
| | | } |
| | | |
| | | /** |
| | | * Prints the table in its current state using the provided table printer. |
| | | * |
| | | * @param printer |
| | | * The table printer. |
| | | */ |
| | | public void print(TablePrinter printer) { |
| | | // Create a new printer instance. |
| | | TableSerializer serializer = printer.getSerializer(); |
| | | |
| | | // First sort the table. |
| | | List<List<String>> sortedRows = new ArrayList<>(rows); |
| | | |
| | | Comparator<List<String>> comparator = new Comparator<List<String>>() { |
| | | @Override |
| | | public int compare(List<String> row1, List<String> row2) { |
| | | for (int i = 0; i < sortKeys.size(); i++) { |
| | | String cell1 = row1.get(sortKeys.get(i)); |
| | | String cell2 = row2.get(sortKeys.get(i)); |
| | | |
| | | int rc = sortComparators.get(i).compare(cell1, cell2); |
| | | if (rc != 0) { |
| | | return rc; |
| | | } |
| | | } |
| | | |
| | | // Both rows are equal. |
| | | return 0; |
| | | } |
| | | }; |
| | | |
| | | Collections.sort(sortedRows, comparator); |
| | | |
| | | // Now output the table. |
| | | serializer.startTable(height, width); |
| | | for (int i = 0; i < width; i++) { |
| | | serializer.addColumn(columnWidths.get(i)); |
| | | } |
| | | |
| | | // Column headings. |
| | | serializer.startHeader(); |
| | | for (LocalizableMessage s : header) { |
| | | serializer.addHeading(s.toString()); |
| | | } |
| | | serializer.endHeader(); |
| | | |
| | | // Table contents. |
| | | serializer.startContent(); |
| | | for (List<String> row : sortedRows) { |
| | | serializer.startRow(); |
| | | |
| | | // Print each cell in the row, padding missing trailing cells. |
| | | for (int i = 0; i < width; i++) { |
| | | if (i < row.size()) { |
| | | serializer.addCell(row.get(i)); |
| | | } else { |
| | | serializer.addCell(""); |
| | | } |
| | | } |
| | | |
| | | serializer.endRow(); |
| | | } |
| | | serializer.endContent(); |
| | | serializer.endTable(); |
| | | } |
| | | |
| | | /** |
| | | * Appends a new row to the table. |
| | | */ |
| | | public void startRow() { |
| | | rows.add(new ArrayList<String>()); |
| | | height++; |
| | | column = 0; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | /** |
| | | * An interface for incrementally configuring a table serializer. Once |
| | | * configured, the table printer can be used to create a new |
| | | * {@link TableSerializer} instance using the {@link #getSerializer()} |
| | | * method. |
| | | */ |
| | | public abstract class TablePrinter { |
| | | |
| | | /** |
| | | * Creates a new abstract table printer. |
| | | */ |
| | | protected TablePrinter() { |
| | | // No implementation required. |
| | | } |
| | | |
| | | /** |
| | | * Creates a new table serializer based on the configuration of this table printer. |
| | | * |
| | | * @return Returns a new table serializer based on the configuration of this table printer. |
| | | */ |
| | | protected abstract TableSerializer getSerializer(); |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | /** |
| | | * An interface for serializing tables. |
| | | * <p> |
| | | * The default implementation for each method is to do nothing. |
| | | * Implementations must override methods as required. |
| | | */ |
| | | public abstract class TableSerializer { |
| | | |
| | | /** |
| | | * Create a new table serializer. |
| | | */ |
| | | protected TableSerializer() { |
| | | // No implementation required. |
| | | } |
| | | |
| | | /** |
| | | * Prints a table cell. |
| | | * |
| | | * @param s |
| | | * The cell contents. |
| | | */ |
| | | public void addCell(String s) { |
| | | // Default implementation. |
| | | } |
| | | |
| | | /** |
| | | * Defines a column in the table. |
| | | * |
| | | * @param width |
| | | * The width of the column in characters. |
| | | */ |
| | | public void addColumn(int width) { |
| | | // Default implementation. |
| | | } |
| | | |
| | | /** |
| | | * Prints a column heading. |
| | | * |
| | | * @param s |
| | | * The column heading. |
| | | */ |
| | | public void addHeading(String s) { |
| | | // Default implementation. |
| | | } |
| | | |
| | | /** |
| | | * Finish printing the table contents. |
| | | */ |
| | | public void endContent() { |
| | | // Default implementation. |
| | | } |
| | | |
| | | /** |
| | | * Finish printing the column headings. |
| | | */ |
| | | public void endHeader() { |
| | | // Default implementation. |
| | | } |
| | | |
| | | /** |
| | | * Finish printing the current row of the table. |
| | | */ |
| | | public void endRow() { |
| | | // Default implementation. |
| | | } |
| | | |
| | | /** |
| | | * Finish printing the table. |
| | | */ |
| | | public void endTable() { |
| | | // Default implementation. |
| | | } |
| | | |
| | | /** |
| | | * Prepare to start printing the table contents. |
| | | */ |
| | | public void startContent() { |
| | | // Default implementation. |
| | | } |
| | | |
| | | /** |
| | | * Prepare to start printing the column headings. |
| | | */ |
| | | public void startHeader() { |
| | | // Default implementation. |
| | | } |
| | | |
| | | /** |
| | | * Prepare to start printing a new row of the table. |
| | | */ |
| | | public void startRow() { |
| | | // Default implementation. |
| | | } |
| | | |
| | | /** |
| | | * Start a new table having the specified number of rows and columns. |
| | | * |
| | | * @param height |
| | | * The number of rows in the table. |
| | | * @param width |
| | | * The number of columns in the table. |
| | | */ |
| | | public void startTable(int height, int width) { |
| | | // Default implementation. |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2007-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.Utils.MAX_LINE_WIDTH; |
| | | import java.io.BufferedWriter; |
| | | import java.io.OutputStream; |
| | | import java.io.OutputStreamWriter; |
| | | import java.io.PrintWriter; |
| | | import java.io.Writer; |
| | | import java.util.ArrayList; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * An interface for creating a text based table. |
| | | * Tables have configurable column widths, padding, and column separators. |
| | | */ |
| | | public final class TextTablePrinter extends TablePrinter { |
| | | /** Table serializer implementation. */ |
| | | private final class Serializer extends TableSerializer { |
| | | /**The real column widths taking into account size constraints but |
| | | not including padding or separators.*/ |
| | | private final List<Integer> columnWidths = new ArrayList<>(); |
| | | |
| | | /** The cells in the current row. */ |
| | | private final List<String> currentRow = new ArrayList<>(); |
| | | |
| | | /** Width of the table in columns. */ |
| | | private int totalColumns; |
| | | |
| | | /** The padding to use for indenting the table. */ |
| | | private final String indentPadding; |
| | | |
| | | /** Private constructor. */ |
| | | private Serializer() { |
| | | // Compute the indentation padding. |
| | | final StringBuilder builder = new StringBuilder(); |
| | | for (int i = 0; i < indentWidth; i++) { |
| | | builder.append(' '); |
| | | } |
| | | this.indentPadding = builder.toString(); |
| | | } |
| | | |
| | | @Override |
| | | public void addCell(String s) { |
| | | currentRow.add(s); |
| | | } |
| | | |
| | | @Override |
| | | public void addColumn(int width) { |
| | | columnWidths.add(width); |
| | | totalColumns++; |
| | | } |
| | | |
| | | @Override |
| | | public void addHeading(String s) { |
| | | if (displayHeadings) { |
| | | addCell(s); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void endHeader() { |
| | | if (displayHeadings) { |
| | | endRow(); |
| | | |
| | | // Print the header separator. |
| | | final StringBuilder builder = new StringBuilder(indentPadding); |
| | | for (int i = 0; i < totalColumns; i++) { |
| | | int width = columnWidths.get(i); |
| | | if (totalColumns > 1) { |
| | | if (i == 0 || i == (totalColumns - 1)) { |
| | | // Only one lot of padding for first and last columns. |
| | | width += padding; |
| | | } else { |
| | | width += padding * 2; |
| | | } |
| | | } |
| | | |
| | | for (int j = 0; j < width; j++) { |
| | | if (headingSeparatorStartColumn > 0) { |
| | | if (i < headingSeparatorStartColumn) { |
| | | builder.append(' '); |
| | | } else if (i == headingSeparatorStartColumn && j < padding) { |
| | | builder.append(' '); |
| | | } else { |
| | | builder.append(headingSeparator); |
| | | } |
| | | } else { |
| | | builder.append(headingSeparator); |
| | | } |
| | | } |
| | | |
| | | if ((i >= headingSeparatorStartColumn) && i < (totalColumns - 1)) { |
| | | builder.append(columnSeparator); |
| | | } |
| | | } |
| | | writer.println(builder.toString()); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void endRow() { |
| | | boolean isRemainingText; |
| | | do { |
| | | StringBuilder builder = new StringBuilder(indentPadding); |
| | | isRemainingText = false; |
| | | for (int i = 0; i < currentRow.size(); i++) { |
| | | int width = columnWidths.get(i); |
| | | String contents = currentRow.get(i); |
| | | |
| | | // Determine what parts of contents can be displayed on this line. |
| | | String head; |
| | | String tail = null; |
| | | |
| | | if (contents == null) { |
| | | // This cell has been displayed fully. |
| | | head = ""; |
| | | } else if (contents.length() > width) { |
| | | // We're going to have to split the cell on next word boundary. |
| | | int endIndex = contents.lastIndexOf(' ', width); |
| | | if (endIndex == -1) { |
| | | endIndex = width; |
| | | head = contents.substring(0, endIndex); |
| | | tail = contents.substring(endIndex); |
| | | } else { |
| | | head = contents.substring(0, endIndex); |
| | | tail = contents.substring(endIndex + 1); |
| | | } |
| | | } else { |
| | | // The contents fits ok. |
| | | head = contents; |
| | | } |
| | | |
| | | // Add this cell's contents to the current line. |
| | | if (i > 0) { |
| | | // Add right padding for previous cell. |
| | | for (int j = 0; j < padding; j++) { |
| | | builder.append(' '); |
| | | } |
| | | |
| | | // Add separator. |
| | | builder.append(columnSeparator); |
| | | |
| | | // Add left padding for this cell. |
| | | for (int j = 0; j < padding; j++) { |
| | | builder.append(' '); |
| | | } |
| | | } |
| | | |
| | | // Add cell contents. |
| | | builder.append(head); |
| | | |
| | | // Now pad with extra space to make up the width. |
| | | // Only if it's not the last cell (see issue #3210) |
| | | if (i != currentRow.size() - 1) { |
| | | for (int j = head.length(); j < width; j++) { |
| | | builder.append(' '); |
| | | } |
| | | } |
| | | |
| | | // Update the row contents. |
| | | currentRow.set(i, tail); |
| | | if (tail != null) { |
| | | isRemainingText = true; |
| | | } |
| | | } |
| | | |
| | | // Output the line. |
| | | writer.println(builder.toString()); |
| | | } while (isRemainingText); |
| | | } |
| | | |
| | | @Override |
| | | public void endTable() { |
| | | writer.flush(); |
| | | } |
| | | |
| | | @Override |
| | | public void startHeader() { |
| | | determineColumnWidths(); |
| | | currentRow.clear(); |
| | | } |
| | | |
| | | @Override |
| | | public void startRow() { |
| | | currentRow.clear(); |
| | | } |
| | | |
| | | /** We need to calculate the effective width of each column. */ |
| | | private void determineColumnWidths() { |
| | | // First calculate the minimum width so that we know how much |
| | | // expandable columns can expand. |
| | | int minWidth = indentWidth; |
| | | int expandableColumnSize = 0; |
| | | |
| | | for (int i = 0; i < totalColumns; i++) { |
| | | int actualSize = columnWidths.get(i); |
| | | |
| | | if (fixedColumns.containsKey(i)) { |
| | | int requestedSize = fixedColumns.get(i); |
| | | |
| | | if (requestedSize == 0) { |
| | | expandableColumnSize += actualSize; |
| | | } else { |
| | | columnWidths.set(i, requestedSize); |
| | | minWidth += requestedSize; |
| | | } |
| | | } else { |
| | | minWidth += actualSize; |
| | | } |
| | | |
| | | // Must also include padding and separators. |
| | | if (i > 0) { |
| | | minWidth += padding * 2 + columnSeparator.length(); |
| | | } |
| | | } |
| | | |
| | | if (minWidth > totalWidth) { |
| | | // The table is too big: leave expandable columns at their |
| | | // requested width, as there's not much else that can be done. |
| | | } else { |
| | | int available = totalWidth - minWidth; |
| | | |
| | | if (expandableColumnSize > available) { |
| | | // Only modify column sizes if necessary. |
| | | for (int i = 0; i < totalColumns; i++) { |
| | | int actualSize = columnWidths.get(i); |
| | | |
| | | if (fixedColumns.containsKey(i)) { |
| | | int requestedSize = fixedColumns.get(i); |
| | | if (requestedSize == 0) { |
| | | // Calculate size based on requested actual size as a |
| | | // proportion of the total. |
| | | requestedSize = (actualSize * available) / expandableColumnSize; |
| | | columnWidths.set(i, requestedSize); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * The default string which should be used to separate one column from the next (not including padding). |
| | | */ |
| | | private static final String DEFAULT_COLUMN_SEPARATOR = ""; |
| | | |
| | | /** |
| | | * The default character which should be used to separate the table heading row from the rows beneath. |
| | | */ |
| | | private static final char DEFAULT_HEADING_SEPARATOR = '-'; |
| | | |
| | | /** |
| | | * The default padding which will be used to separate a cell's contents from its adjacent column separators. |
| | | */ |
| | | private static final int DEFAULT_PADDING = 1; |
| | | |
| | | /** |
| | | * The string which should be used to separate one column |
| | | * from the next (not including padding). |
| | | */ |
| | | private String columnSeparator = DEFAULT_COLUMN_SEPARATOR; |
| | | |
| | | /** Indicates whether or not the headings should be output. */ |
| | | private boolean displayHeadings = true; |
| | | |
| | | /** Table indicating whether or not a column is fixed width. */ |
| | | private final Map<Integer, Integer> fixedColumns = new HashMap<>(); |
| | | |
| | | /** The number of characters the table should be indented. */ |
| | | private int indentWidth; |
| | | |
| | | /** The character which should be used to separate the table heading row from the rows beneath. */ |
| | | private char headingSeparator = DEFAULT_HEADING_SEPARATOR; |
| | | |
| | | /** The column where the heading separator should begin. */ |
| | | private int headingSeparatorStartColumn; |
| | | |
| | | /** |
| | | * The padding which will be used to separate a cell's |
| | | * contents from its adjacent column separators. |
| | | */ |
| | | private int padding = DEFAULT_PADDING; |
| | | |
| | | /** Total permitted width for the table which expandable columns can use up. */ |
| | | private int totalWidth = MAX_LINE_WIDTH; |
| | | |
| | | /** The output destination. */ |
| | | private PrintWriter writer; |
| | | |
| | | /** |
| | | * Creates a new text table printer for the specified output stream. The text table printer will have the following |
| | | * initial settings: |
| | | * <ul> |
| | | * <li>headings will be displayed |
| | | * <li>no separators between columns |
| | | * <li>columns are padded by one character |
| | | * </ul> |
| | | * |
| | | * @param stream |
| | | * The stream to output tables to. |
| | | */ |
| | | public TextTablePrinter(OutputStream stream) { |
| | | this(new BufferedWriter(new OutputStreamWriter(stream))); |
| | | } |
| | | |
| | | /** |
| | | * Creates a new text table printer for the specified writer. The text table printer will have the following initial |
| | | * settings: |
| | | * <ul> |
| | | * <li>headings will be displayed |
| | | * <li>no separators between columns |
| | | * <li>columns are padded by one character |
| | | * </ul> |
| | | * |
| | | * @param writer |
| | | * The writer to output tables to. |
| | | */ |
| | | public TextTablePrinter(Writer writer) { |
| | | this.writer = new PrintWriter(writer); |
| | | } |
| | | |
| | | /** |
| | | * Sets the column separator which should be used to separate one column from the next (not including padding). |
| | | * |
| | | * @param columnSeparator |
| | | * The column separator. |
| | | */ |
| | | public void setColumnSeparator(String columnSeparator) { |
| | | this.columnSeparator = columnSeparator; |
| | | } |
| | | |
| | | /** |
| | | * Set the maximum width for a column. If a cell is too big to fit in its column then it will be wrapped. |
| | | * |
| | | * @param column |
| | | * The column to make fixed width (0 is the first column). |
| | | * @param width |
| | | * The width of the column (this should not include column separators or padding), or <code>0</code> to |
| | | * indicate that this column should be expandable. |
| | | * @throws IllegalArgumentException |
| | | * If column is less than 0. |
| | | */ |
| | | public void setColumnWidth(int column, int width) { |
| | | if (column < 0) { |
| | | throw new IllegalArgumentException("Negative column " + column); |
| | | } |
| | | |
| | | if (width < 0) { |
| | | throw new IllegalArgumentException("Negative width " + width); |
| | | } |
| | | |
| | | fixedColumns.put(column, width); |
| | | } |
| | | |
| | | /** |
| | | * Specify whether the column headings should be displayed or not. |
| | | * |
| | | * @param displayHeadings |
| | | * <code>true</code> if column headings should be displayed. |
| | | */ |
| | | public void setDisplayHeadings(boolean displayHeadings) { |
| | | this.displayHeadings = displayHeadings; |
| | | } |
| | | |
| | | /** |
| | | * Sets the heading separator which should be used to separate the table heading row from the rows beneath. |
| | | * |
| | | * @param headingSeparator |
| | | * The heading separator. |
| | | */ |
| | | public void setHeadingSeparator(char headingSeparator) { |
| | | this.headingSeparator = headingSeparator; |
| | | } |
| | | |
| | | /** |
| | | * Sets the heading separator start column. The heading separator will only be display in the specified column and |
| | | * all subsequent columns. Usually this should be left at zero (the default) but sometimes it useful to indent the |
| | | * heading separate in order to provide additional emphasis (for example in menus). |
| | | * |
| | | * @param startColumn |
| | | * The heading separator start column. |
| | | */ |
| | | public void setHeadingSeparatorStartColumn(int startColumn) { |
| | | if (startColumn < 0) { |
| | | throw new IllegalArgumentException("Negative start column " + startColumn); |
| | | } |
| | | this.headingSeparatorStartColumn = startColumn; |
| | | } |
| | | |
| | | /** |
| | | * Sets the amount of characters that the table should be indented. By default the table is not indented. |
| | | * |
| | | * @param indentWidth |
| | | * The number of characters the table should be indented. |
| | | * @throws IllegalArgumentException |
| | | * If indentWidth is less than 0. |
| | | */ |
| | | public void setIndentWidth(int indentWidth) { |
| | | if (indentWidth < 0) { |
| | | throw new IllegalArgumentException("Negative indentation width " + indentWidth); |
| | | } |
| | | |
| | | this.indentWidth = indentWidth; |
| | | } |
| | | |
| | | /** |
| | | * Sets the padding which will be used to separate a cell's contents from its adjacent column separators. |
| | | * |
| | | * @param padding |
| | | * The padding. |
| | | */ |
| | | public void setPadding(int padding) { |
| | | this.padding = padding; |
| | | } |
| | | |
| | | /** |
| | | * Sets the total permitted width for the table which expandable columns can use up. |
| | | * |
| | | * @param totalWidth |
| | | * The total width. |
| | | */ |
| | | public void setTotalWidth(int totalWidth) { |
| | | this.totalWidth = totalWidth; |
| | | } |
| | | |
| | | @Override |
| | | protected TableSerializer getSerializer() { |
| | | return new Serializer(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2015 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | /** |
| | | * An interface for an object that holds reference documentation for a command-line tool. |
| | | */ |
| | | public interface ToolRefDocContainer { |
| | | |
| | | /** |
| | | * Gets a short description for this tool, suitable in a man page summary line. |
| | | * |
| | | * @return A short description for this tool, |
| | | * suitable in a man page summary line, |
| | | * or LocalizableMessage.EMPTY if there is no short description. |
| | | */ |
| | | LocalizableMessage getShortToolDescription(); |
| | | |
| | | /** |
| | | * Sets a short description for this tool, suitable in a man page summary line. |
| | | * |
| | | * @param shortDescription The short description for this tool, |
| | | * suitable in a man page summary line. |
| | | */ |
| | | void setShortToolDescription(final LocalizableMessage shortDescription); |
| | | |
| | | /** |
| | | * Retrieves a supplement to the description for this tool, |
| | | * intended for use in generated reference documentation. |
| | | * |
| | | * @return A supplement to the description for this tool |
| | | * intended for use in generated reference documentation, |
| | | * or LocalizableMessage.EMPTY if there is no supplement. |
| | | */ |
| | | LocalizableMessage getDocToolDescriptionSupplement(); |
| | | |
| | | /** |
| | | * Sets a supplement to the description for this tool, |
| | | * intended for use in generated reference documentation. |
| | | * |
| | | * @param docToolDescriptionSupplement The supplement to the description for this tool |
| | | * intended for use in generated reference documentation. |
| | | */ |
| | | void setDocToolDescriptionSupplement(final LocalizableMessage docToolDescriptionSupplement); |
| | | |
| | | /** |
| | | * Retrieves a supplement to the description for all subcommands of this tool, |
| | | * intended for use in generated reference documentation. |
| | | * |
| | | * @return A supplement to the description for all subcommands of this tool |
| | | * intended for use in generated reference documentation, |
| | | * or LocalizableMessage.EMPTY if there is no supplement. |
| | | */ |
| | | LocalizableMessage getDocSubcommandsDescriptionSupplement(); |
| | | |
| | | /** |
| | | * Sets a supplement to the description for all subcommands of this tool, |
| | | * intended for use in generated reference documentation. |
| | | * |
| | | * @param docSubcommandsDescriptionSupplement |
| | | * The supplement to the description for all subcommands of this tool |
| | | * intended for use in generated reference documentation. |
| | | */ |
| | | void setDocSubcommandsDescriptionSupplement(final LocalizableMessage docSubcommandsDescriptionSupplement); |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2015-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.net.URL; |
| | | import java.util.Enumeration; |
| | | import java.util.jar.Attributes; |
| | | import java.util.jar.Manifest; |
| | | |
| | | /** Class that prints the version of the SDK to System.out. */ |
| | | public final class ToolVersionHandler implements VersionHandler { |
| | | |
| | | /** |
| | | * Returns a {@link VersionHandler} which should be used by OpenDJ SDK tools. |
| | | * <p> |
| | | * The printed version and SCM revision will be the one of the opendj-core module. |
| | | * @return A {@link VersionHandler} which should be used by OpenDJ SDK tools. |
| | | */ |
| | | public static VersionHandler newSdkVersionHandler() { |
| | | return newToolVersionHandler("opendj-core"); |
| | | } |
| | | |
| | | /** |
| | | * Returns a {@link VersionHandler} which should be used to print version and SCM revision of a module. |
| | | * <p> |
| | | * The printed version and SCM revision will be read from the module MANIFEST.MF‌ file. |
| | | * @param moduleName |
| | | * Name of the module which uniquely identify the URL of the MANIFEST‌.MF file. |
| | | * @return A {@link VersionHandler} which should be used by OpenDJ SDK tools. |
| | | */ |
| | | public static VersionHandler newToolVersionHandler(final String moduleName) { |
| | | return new ToolVersionHandler(moduleName); |
| | | } |
| | | |
| | | private final String moduleName; |
| | | |
| | | private ToolVersionHandler(final String moduleName) { |
| | | this.moduleName = moduleName; |
| | | } |
| | | |
| | | @Override |
| | | public void printVersion() { |
| | | System.out.println(getVersion()); |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return getClass().getSimpleName() + "(" + getVersion() + ")"; |
| | | } |
| | | |
| | | private String getVersion() { |
| | | try { |
| | | final Enumeration<URL> manifests = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF"); |
| | | while (manifests.hasMoreElements()) { |
| | | final URL manifestUrl = manifests.nextElement(); |
| | | if (manifestUrl.toString().contains(moduleName)) { |
| | | try (InputStream manifestStream = manifestUrl.openStream()) { |
| | | final Attributes attrs = new Manifest(manifestStream).getMainAttributes(); |
| | | return attrs.getValue("Bundle-Version") + " (revision " + attrs.getValue("SCM-Revision") + ")"; |
| | | } |
| | | } |
| | | } |
| | | return null; |
| | | } catch (IOException e) { |
| | | throw new RuntimeException("IOException while determining opendj tool version", e); |
| | | } |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import static com.forgerock.opendj.cli.CliMessages.*; |
| | | |
| | | import com.forgerock.opendj.util.OperatingSystem; |
| | | |
| | | import static com.forgerock.opendj.util.StaticUtils.EOL; |
| | | |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.IOException; |
| | | import java.io.PrintStream; |
| | | import java.net.InetAddress; |
| | | import java.net.UnknownHostException; |
| | | import java.security.GeneralSecurityException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Arrays; |
| | | import java.util.Collection; |
| | | import java.util.Date; |
| | | import java.util.StringTokenizer; |
| | | import java.util.TimeZone; |
| | | |
| | | import javax.naming.AuthenticationException; |
| | | import javax.naming.CommunicationException; |
| | | import javax.naming.NamingException; |
| | | import javax.naming.NamingSecurityException; |
| | | import javax.naming.NoPermissionException; |
| | | import javax.net.ssl.SSLHandshakeException; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.LocalizableMessageBuilder; |
| | | import org.forgerock.i18n.LocalizableMessageDescriptor; |
| | | import org.forgerock.opendj.ldap.DN; |
| | | import org.forgerock.opendj.ldap.RDN; |
| | | |
| | | /** This class provides utility functions for all the client side tools. */ |
| | | public final class Utils { |
| | | |
| | | /** Platform appropriate line separator. */ |
| | | public static final String LINE_SEPARATOR = System.getProperty("line.separator"); |
| | | |
| | | /** |
| | | * The value used to display arguments that must be obfuscated (such as passwords). This does not require |
| | | * localization (since the output of command builder by its nature is not localized). |
| | | */ |
| | | public static final String OBFUSCATED_VALUE = "******"; |
| | | |
| | | /** The maximum number of times we try to confirm. */ |
| | | public static final int CONFIRMATION_MAX_TRIES = 5; |
| | | |
| | | /** |
| | | * The date format string that will be used to construct and parse dates represented using generalized time. It is |
| | | * assumed that the provided date formatter will be set to UTC. |
| | | */ |
| | | public static final String DATE_FORMAT_LOCAL_TIME = "dd/MMM/yyyy:HH:mm:ss Z"; |
| | | |
| | | /** |
| | | * Returns the message to be displayed in the file with the equivalent command-line with information about the |
| | | * current time. |
| | | * |
| | | * @return the message to be displayed in the file with the equivalent command-line with information about the |
| | | * current time. |
| | | */ |
| | | public static String getCurrentOperationDateMessage() { |
| | | String date = formatDateTimeStringForEquivalentCommand(new Date()); |
| | | return INFO_OPERATION_START_TIME_MESSAGE.get(date).toString(); |
| | | } |
| | | |
| | | private static final String COMMENT_SHELL_UNIX = "# "; |
| | | private static final String COMMENT_BATCH_WINDOWS = "rem "; |
| | | |
| | | /** The String used to write comments in a shell (or batch) script. */ |
| | | public static final String SHELL_COMMENT_SEPARATOR = OperatingSystem.isWindows() ? COMMENT_BATCH_WINDOWS |
| | | : COMMENT_SHELL_UNIX; |
| | | |
| | | /** The column at which to wrap long lines of output in the command-line tools. */ |
| | | public static final int MAX_LINE_WIDTH; |
| | | static { |
| | | int columns = 80; |
| | | try { |
| | | final String s = System.getenv("COLUMNS"); |
| | | if (s != null) { |
| | | columns = Integer.parseInt(s); |
| | | } |
| | | } catch (final Exception e) { |
| | | // Do nothing. |
| | | } |
| | | MAX_LINE_WIDTH = columns - 1; |
| | | } |
| | | |
| | | /** |
| | | * Formats a Date to String representation in "dd/MMM/yyyy:HH:mm:ss Z". |
| | | * |
| | | * @param date |
| | | * The date to format; null if <code>date</code> is null. |
| | | * @return A string representation of the date. |
| | | */ |
| | | public static String formatDateTimeStringForEquivalentCommand(final Date date) { |
| | | if (date != null) { |
| | | final SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT_LOCAL_TIME); |
| | | dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); |
| | | return dateFormat.format(date); |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** |
| | | * Filters the provided value to ensure that it is appropriate for use as an |
| | | * exit code. Exit code values are generally only allowed to be between 0 |
| | | * and 255, so any value outside of this range will be converted to 255, |
| | | * which is the typical exit code used to indicate an overflow value. |
| | | * |
| | | * @param exitCode |
| | | * The exit code value to be processed. |
| | | * @return An integer value between 0 and 255, inclusive. If the provided |
| | | * exit code was already between 0 and 255, then the original value |
| | | * will be returned. If the provided value was out of this range, |
| | | * then 255 will be returned. |
| | | */ |
| | | public static int filterExitCode(final int exitCode) { |
| | | if (exitCode < 0) { |
| | | return 255; |
| | | } else if (exitCode > 255) { |
| | | return 255; |
| | | } else { |
| | | return exitCode; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Read the data from the specified file and return it in a byte array. |
| | | * |
| | | * @param filePath |
| | | * The path to the file that should be read. |
| | | * @return A byte array containing the contents of the requested file. |
| | | * @throws IOException |
| | | * If a problem occurs while trying to read the specified file. |
| | | */ |
| | | public static byte[] readBytesFromFile(final String filePath) throws IOException { |
| | | final File file = new File(filePath); |
| | | final long length = file.length(); |
| | | try (FileInputStream fis = new FileInputStream(file)) { |
| | | byte[] val = new byte[(int) length]; |
| | | // Read in the bytes |
| | | int offset = 0; |
| | | int numRead = 0; |
| | | while (offset < val.length |
| | | && (numRead = fis.read(val, offset, val.length - offset)) >= 0) { |
| | | offset += numRead; |
| | | } |
| | | |
| | | // Ensure all the bytes have been read in |
| | | if (offset < val.length) { |
| | | throw new IOException("Could not completely read file " + filePath); |
| | | } |
| | | |
| | | return val; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Retrieves a user-friendly string that indicates the length of time (in |
| | | * days, hours, minutes, and seconds) in the specified number of seconds. |
| | | * |
| | | * @param numSeconds |
| | | * The number of seconds to be converted to a more user-friendly |
| | | * value. |
| | | * @return The user-friendly representation of the specified number of |
| | | * seconds. |
| | | */ |
| | | public static LocalizableMessage secondsToTimeString(final int numSeconds) { |
| | | if (numSeconds < 60) { |
| | | // We can express it in seconds. |
| | | return INFO_TIME_IN_SECONDS.get(numSeconds); |
| | | } else if (numSeconds < 3600) { |
| | | // We can express it in minutes and seconds. |
| | | final int m = numSeconds / 60; |
| | | final int s = numSeconds % 60; |
| | | return INFO_TIME_IN_MINUTES_SECONDS.get(m, s); |
| | | } else if (numSeconds < 86400) { |
| | | // We can express it in hours, minutes, and seconds. |
| | | final int h = numSeconds / 3600; |
| | | final int m = (numSeconds % 3600) / 60; |
| | | final int s = numSeconds % 3600 % 60; |
| | | return INFO_TIME_IN_HOURS_MINUTES_SECONDS.get(h, m, s); |
| | | } else { |
| | | // We can express it in days, hours, minutes, and seconds. |
| | | final int d = numSeconds / 86400; |
| | | final int h = (numSeconds % 86400) / 3600; |
| | | final int m = (numSeconds % 86400 % 3600) / 60; |
| | | final int s = numSeconds % 86400 % 3600 % 60; |
| | | return INFO_TIME_IN_DAYS_HOURS_MINUTES_SECONDS.get(d, h, m, s); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Inserts line breaks into the provided buffer to wrap text at no more than |
| | | * the specified column width. Wrapping will only be done at space |
| | | * boundaries and if there are no spaces within the specified width, then |
| | | * wrapping will be performed at the first space after the specified column. |
| | | * |
| | | * @param message |
| | | * The message to be wrapped. |
| | | * @param width |
| | | * The maximum number of characters to allow on a line if there |
| | | * is a suitable breaking point. |
| | | * @return The wrapped text. |
| | | */ |
| | | public static String wrapText(final LocalizableMessage message, final int width) { |
| | | return wrapText(message.toString(), width, 0); |
| | | } |
| | | |
| | | /** |
| | | * Inserts line breaks into the provided buffer to wrap text at no more than |
| | | * the specified column width. Wrapping will only be done at space |
| | | * boundaries and if there are no spaces within the specified width, then |
| | | * wrapping will be performed at the first space after the specified column. |
| | | * In addition each line will be indented by the specified amount. |
| | | * |
| | | * @param message |
| | | * The message to be wrapped. |
| | | * @param width |
| | | * The maximum number of characters to allow on a line if there |
| | | * is a suitable breaking point (including any indentation). |
| | | * @param indent |
| | | * The number of columns to indent each line. |
| | | * @return The wrapped text. |
| | | */ |
| | | public static String wrapText(final LocalizableMessage message, final int width, final int indent) { |
| | | return wrapText(message.toString(), width, indent); |
| | | } |
| | | |
| | | /** |
| | | * Inserts line breaks into the provided buffer to wrap text at no more than |
| | | * the specified column width. Wrapping will only be done at space |
| | | * boundaries and if there are no spaces within the specified width, then |
| | | * wrapping will be performed at the first space after the specified column. |
| | | * |
| | | * @param text |
| | | * The text to be wrapped. |
| | | * @param width |
| | | * The maximum number of characters to allow on a line if there |
| | | * is a suitable breaking point. |
| | | * @return The wrapped text. |
| | | */ |
| | | public static String wrapText(final String text, final int width) { |
| | | return wrapText(text, width, 0); |
| | | } |
| | | |
| | | /** |
| | | * Inserts line breaks into the provided buffer to wrap text at no more than |
| | | * the specified column width. Wrapping will only be done at space |
| | | * boundaries and if there are no spaces within the specified width, then |
| | | * wrapping will be performed at the first space after the specified column. |
| | | * In addition each line will be indented by the specified amount. |
| | | * |
| | | * @param text |
| | | * The text to be wrapped. |
| | | * @param width |
| | | * The maximum number of characters to allow on a line if there |
| | | * is a suitable breaking point (including any indentation). |
| | | * @param indent |
| | | * The number of columns to indent each line. |
| | | * @return The wrapped text. |
| | | */ |
| | | public static String wrapText(final String text, int width, final int indent) { |
| | | if (text == null) { |
| | | return ""; |
| | | } |
| | | |
| | | // Calculate the real width and indentation padding. |
| | | width -= indent; |
| | | final StringBuilder pb = new StringBuilder(); |
| | | for (int i = 0; i < indent; i++) { |
| | | pb.append(' '); |
| | | } |
| | | final String padding = pb.toString(); |
| | | |
| | | final StringBuilder buffer = new StringBuilder(); |
| | | final StringTokenizer lineTokenizer = new StringTokenizer(text, "\r\n", true); |
| | | while (lineTokenizer.hasMoreTokens()) { |
| | | final String line = lineTokenizer.nextToken(); |
| | | if ("\r".equals(line) || "\n".equals(line)) { |
| | | // It's an end-of-line character, so append it as-is. |
| | | buffer.append(line); |
| | | } else if (line.length() <= width) { |
| | | // The line fits in the specified width, so append it as-is. |
| | | buffer.append(padding); |
| | | buffer.append(line); |
| | | } else { |
| | | // The line doesn't fit in the specified width, so it needs |
| | | // to be wrapped. Do so at space boundaries. |
| | | StringBuilder lineBuffer = new StringBuilder(); |
| | | StringBuilder delimBuffer = new StringBuilder(); |
| | | final StringTokenizer wordTokenizer = new StringTokenizer(line, " ", true); |
| | | while (wordTokenizer.hasMoreTokens()) { |
| | | final String word = wordTokenizer.nextToken(); |
| | | if (" ".equals(word)) { |
| | | // It's a space, so add it to the delim buffer only |
| | | // if the line buffer is not empty. |
| | | if (lineBuffer.length() > 0) { |
| | | delimBuffer.append(word); |
| | | } |
| | | } else if (word.length() > width) { |
| | | // This is a long word that can't be wrapped, |
| | | // so we'll just have to make do. |
| | | if (lineBuffer.length() > 0) { |
| | | buffer.append(padding).append(lineBuffer).append(EOL); |
| | | lineBuffer = new StringBuilder(); |
| | | } |
| | | buffer.append(padding); |
| | | buffer.append(word); |
| | | |
| | | if (wordTokenizer.hasMoreTokens()) { |
| | | // The next token must be a space, so remove it. |
| | | // If there are still more tokens after that, then append an EOL. |
| | | wordTokenizer.nextToken(); |
| | | if (wordTokenizer.hasMoreTokens()) { |
| | | buffer.append(EOL); |
| | | } |
| | | } |
| | | |
| | | if (delimBuffer.length() > 0) { |
| | | delimBuffer = new StringBuilder(); |
| | | } |
| | | } else { |
| | | // It's not a space, so see if we can fit it on the current line. |
| | | final int newLineLength = |
| | | lineBuffer.length() + delimBuffer.length() + word.length(); |
| | | if (newLineLength < width) { |
| | | // It does fit on the line, so add it. |
| | | lineBuffer.append(delimBuffer).append(word); |
| | | |
| | | if (delimBuffer.length() > 0) { |
| | | delimBuffer = new StringBuilder(); |
| | | } |
| | | } else { |
| | | // It doesn't fit on the line, so end the |
| | | // current line and start a new one. |
| | | buffer.append(padding).append(lineBuffer).append(EOL); |
| | | |
| | | lineBuffer = new StringBuilder(); |
| | | lineBuffer.append(word); |
| | | |
| | | if (delimBuffer.length() > 0) { |
| | | delimBuffer = new StringBuilder(); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | // If there's anything left in the line buffer, then add it |
| | | // to the final buffer. |
| | | buffer.append(padding); |
| | | buffer.append(lineBuffer); |
| | | } |
| | | } |
| | | return buffer.toString(); |
| | | } |
| | | |
| | | /** |
| | | * Checks the java version. |
| | | * |
| | | * @throws ClientException |
| | | * If the java version we are running on is not compatible. |
| | | */ |
| | | public static void checkJavaVersion() throws ClientException { |
| | | final String version = System.getProperty("java.specification.version"); |
| | | if (Float.valueOf(version) < CliConstants.MINIMUM_JAVA_VERSION) { |
| | | final String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; |
| | | throw new ClientException(ReturnCode.JAVA_VERSION_INCOMPATIBLE, |
| | | ERR_INCOMPATIBLE_JAVA_VERSION.get(CliConstants.MINIMUM_JAVA_VERSION, version, javaBin), null); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns the default host name. |
| | | * |
| | | * @return The default host name or empty string if the host name cannot be resolved. |
| | | */ |
| | | public static String getDefaultHostName() { |
| | | try { |
| | | return InetAddress.getLocalHost().getHostName(); |
| | | } catch (UnknownHostException e) { |
| | | // Fails. |
| | | } |
| | | String host = System.getenv("COMPUTERNAME"); // Windows. |
| | | if (host != null) { |
| | | return host; |
| | | } |
| | | host = System.getenv("HOSTNAME"); // Unix. |
| | | if (host != null) { |
| | | return host; |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | /** |
| | | * Tells whether the provided Throwable was caused because of a problem with a certificate while trying to establish |
| | | * a connection. |
| | | * |
| | | * @param t |
| | | * The Throwable to analyze. |
| | | * @return <CODE>true</CODE> if the provided Throwable was caused because of a problem with a certificate while |
| | | * trying to establish a connection and <CODE>false</CODE> otherwise. |
| | | */ |
| | | public static boolean isCertificateException(Throwable t) { |
| | | while (t != null) { |
| | | if (t instanceof SSLHandshakeException || t instanceof GeneralSecurityException) { |
| | | return true; |
| | | } |
| | | t = t.getCause(); |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** |
| | | * Returns a message object for the given NamingException. |
| | | * |
| | | * @param ne |
| | | * The NamingException. |
| | | * @param hostPort |
| | | * The hostPort representation of the server we were contacting when the NamingException occurred. |
| | | * @return A message object for the given NamingException. |
| | | */ |
| | | public static LocalizableMessage getMessageForException(NamingException ne, String hostPort) { |
| | | String arg; |
| | | if (ne.getLocalizedMessage() != null) { |
| | | arg = ne.getLocalizedMessage(); |
| | | } else if (ne.getExplanation() != null) { |
| | | arg = ne.getExplanation(); |
| | | } else { |
| | | arg = ne.toString(true); |
| | | } |
| | | |
| | | if (Utils.isCertificateException(ne)) { |
| | | return INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(hostPort, arg); |
| | | } else if (ne instanceof AuthenticationException) { |
| | | return INFO_CANNOT_CONNECT_TO_REMOTE_AUTHENTICATION.get(hostPort, arg); |
| | | } else if (ne instanceof NoPermissionException) { |
| | | return INFO_CANNOT_CONNECT_TO_REMOTE_PERMISSIONS.get(hostPort, arg); |
| | | } else if (ne instanceof NamingSecurityException) { |
| | | return INFO_CANNOT_CONNECT_TO_REMOTE_PERMISSIONS.get(hostPort, arg); |
| | | } else if (ne instanceof CommunicationException) { |
| | | return ERR_CANNOT_CONNECT_TO_REMOTE_COMMUNICATION.get(hostPort, arg); |
| | | } else { |
| | | return INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC.get(hostPort, arg); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns a localized message for a given properties key an throwable. |
| | | * |
| | | * @param message |
| | | * prefix |
| | | * @param t |
| | | * the throwable for which we want to get a message. |
| | | * @return a localized message for a given properties key and throwable. |
| | | */ |
| | | public static LocalizableMessage getThrowableMsg(final LocalizableMessage message, final Throwable t) { |
| | | LocalizableMessageDescriptor.Arg1<Object> tag; |
| | | if (isOutOfMemory(t)) { |
| | | tag = INFO_EXCEPTION_OUT_OF_MEMORY_DETAILS; |
| | | } else { |
| | | tag = INFO_EXCEPTION_DETAILS; |
| | | } |
| | | final LocalizableMessageBuilder mb = new LocalizableMessageBuilder(message); |
| | | String detail = t.toString(); |
| | | if (detail != null) { |
| | | mb.append(" ").append(tag.get(detail)); |
| | | } |
| | | return mb.toMessage(); |
| | | } |
| | | |
| | | /** |
| | | * Returns <CODE>true</CODE> if we can write on the provided path and <CODE>false</CODE> otherwise. |
| | | * |
| | | * @param path |
| | | * the path. |
| | | * @return <CODE>true</CODE> if we can write on the provided path and <CODE>false</CODE> otherwise. |
| | | */ |
| | | public static boolean canWrite(String path) { |
| | | final File file = new File(path); |
| | | if (file.exists()) { |
| | | return file.canWrite(); |
| | | } |
| | | final File parentFile = file.getParentFile(); |
| | | return parentFile != null && parentFile.canWrite(); |
| | | } |
| | | |
| | | /** Prevent instantiation. */ |
| | | private Utils() { |
| | | // Do nothing. |
| | | } |
| | | |
| | | /** |
| | | * Returns {@code true} if the the provided string is a DN and {@code false} otherwise. |
| | | * |
| | | * @param dn |
| | | * The String we are analyzing. |
| | | * @return {@code true} if the the provided string is a DN and {@code false} otherwise. |
| | | */ |
| | | public static boolean isDN(String dn) { |
| | | try { |
| | | DN.valueOf(dn); |
| | | return true; |
| | | } catch (Exception ex) { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns the DN of the global administrator for a given UID. |
| | | * |
| | | * @param uid |
| | | * The UID to be used to generate the DN. |
| | | * @return The DN of the administrator for the given UID. |
| | | */ |
| | | public static String getAdministratorDN(String uid) { |
| | | return RDN.valueOf("cn=" + uid) + ",cn=Administrators, cn=admin data"; |
| | | } |
| | | |
| | | /** |
| | | * Tells whether this throwable has been generated for an out of memory error or not. |
| | | * |
| | | * @param t |
| | | * The throwable to analyze. |
| | | * @return {@code true} if the throwable was generated by an out of memory error and false otherwise. |
| | | */ |
| | | private static boolean isOutOfMemory(Throwable t) { |
| | | boolean isOutOfMemory = false; |
| | | while (!isOutOfMemory && t != null) { |
| | | if (t instanceof OutOfMemoryError) { |
| | | isOutOfMemory = true; |
| | | } else if (t instanceof IOException) { |
| | | final String msg = t.toString(); |
| | | if (msg != null) { |
| | | isOutOfMemory = msg.contains("Not enough space"); |
| | | } |
| | | } |
| | | t = t.getCause(); |
| | | } |
| | | return isOutOfMemory; |
| | | } |
| | | |
| | | /** |
| | | * Returns the string that can be used to represent a given host name in a LDAP URL. |
| | | * This method must be used when we have IPv6 addresses (the address in the LDAP URL |
| | | * must be enclosed with brackets). |
| | | * E.g:<pre> |
| | | * -h "[2a01:e35:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]" |
| | | * </pre> |
| | | * |
| | | * @param host |
| | | * The host name. |
| | | * @return The String that can be used to represent a given host name in a LDAP URL. |
| | | */ |
| | | public static String getHostNameForLdapUrl(String host) { |
| | | if (host != null && host.contains(":")) { |
| | | // Assume an IPv6 address has been specified and adds the brackets |
| | | // for the URL. |
| | | host = host.trim(); |
| | | if (!host.startsWith("[")) { |
| | | host = "[" + host; |
| | | } |
| | | if (!host.endsWith("]")) { |
| | | host = host + "]"; |
| | | } |
| | | } |
| | | return host; |
| | | } |
| | | |
| | | /** |
| | | * Prints the provided string on the provided stream. |
| | | * |
| | | * @param stream |
| | | * The stream to print the message. |
| | | * @param message |
| | | * The message to print. |
| | | */ |
| | | public static void printWrappedText(final PrintStream stream, final String message) { |
| | | if (stream != null && message != null && !message.isEmpty()) { |
| | | stream.println(wrapText(message, MAX_LINE_WIDTH)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Print the provided message on the provided stream. |
| | | * |
| | | * @param stream |
| | | * The stream to print the message. |
| | | * @param message |
| | | * The message to print. |
| | | */ |
| | | public static void printWrappedText(final PrintStream stream, final LocalizableMessage message) { |
| | | printWrappedText(stream, message != null ? message.toString() : null); |
| | | } |
| | | |
| | | /** |
| | | * Repeats the given {@link char} n times. |
| | | * |
| | | * @param charToRepeat |
| | | * The {@link char} to repeat. |
| | | * @param length |
| | | * The repetition count. |
| | | * @return The given {@link char} n times. |
| | | */ |
| | | public static String repeat(final char charToRepeat, final int length) { |
| | | final char[] str = new char[length]; |
| | | Arrays.fill(str, charToRepeat); |
| | | return new String(str); |
| | | } |
| | | |
| | | /** |
| | | * Return a {@link ValidationCallback<Integer>} which can be used to validate a port number. |
| | | * |
| | | * @param defaultPort |
| | | * The default value to suggest to the user. |
| | | * @return a {@link ValidationCallback<Integer>} which can be used to validate a port number. |
| | | */ |
| | | public static ValidationCallback<Integer> portValidationCallback(final int defaultPort) { |
| | | return new ValidationCallback<Integer>() { |
| | | @Override |
| | | public Integer validate(ConsoleApplication app, String rawInput) throws ClientException { |
| | | final String input = rawInput.trim(); |
| | | if (input.length() == 0) { |
| | | return defaultPort; |
| | | } |
| | | |
| | | try { |
| | | int i = Integer.parseInt(input); |
| | | if (i < 1 || i > 65535) { |
| | | throw new NumberFormatException(); |
| | | } |
| | | return i; |
| | | } catch (NumberFormatException e) { |
| | | // Try again... |
| | | app.println(); |
| | | app.println(ERR_BAD_PORT_NUMBER.get(input)); |
| | | app.println(); |
| | | return null; |
| | | } |
| | | } |
| | | }; |
| | | } |
| | | |
| | | /** |
| | | * Throws an {@link ArgumentException} if both provided {@link Argument} are presents in the command line arguments. |
| | | * |
| | | * @param arg1 |
| | | * The first {@link Argument} which should not be present if {@literal arg2} is. |
| | | * @param arg2 |
| | | * The second {@link Argument} which should not be present if {@literal arg1} is. |
| | | * @throws ArgumentException |
| | | * If both provided {@link Argument} are presents in the command line arguments |
| | | */ |
| | | public static void throwIfArgumentsConflict(final Argument arg1, final Argument arg2) throws ArgumentException { |
| | | if (argsConflicts(arg1, arg2)) { |
| | | throw new ArgumentException(conflictingArgsErrorMessage(arg1, arg2)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Adds a {@link LocalizableMessage} to the provided {@link Collection<LocalizableMessage>} |
| | | * if both provided {@link Argument} are presents in the command line arguments. |
| | | * |
| | | * @param errors |
| | | * The {@link Collection<LocalizableMessage>} to use to add the conflict error (if occurs). |
| | | * @param arg1 |
| | | * The first {@link Argument} which should not be present if {@literal arg2} is. |
| | | * @param arg2 |
| | | * The second {@link Argument} which should not be present if {@literal arg1} is. |
| | | */ |
| | | public static void addErrorMessageIfArgumentsConflict( |
| | | final Collection<LocalizableMessage> errors, final Argument arg1, final Argument arg2) { |
| | | if (argsConflicts(arg1, arg2)) { |
| | | errors.add(conflictingArgsErrorMessage(arg1, arg2)); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Return {@code true} if provided {@link Argument} are presents in the command line arguments. |
| | | * <p> |
| | | * If so, adds a {@link LocalizableMessage} to the provided {@link LocalizableMessageBuilder}. |
| | | * |
| | | * @param builder |
| | | * The {@link LocalizableMessageBuilder} to use to write the conflict error (if occurs). |
| | | * @param arg1 |
| | | * The first {@link Argument} which should not be present if {@literal arg2} is. |
| | | * @param arg2 |
| | | * The second {@link Argument} which should not be present if {@literal arg1} is. |
| | | * @return {@code true} if provided {@link Argument} are presents in the command line arguments. |
| | | */ |
| | | public static boolean appendErrorMessageIfArgumentsConflict( |
| | | final LocalizableMessageBuilder builder, final Argument arg1, final Argument arg2) { |
| | | if (argsConflicts(arg1, arg2)) { |
| | | if (builder.length() > 0) { |
| | | builder.append(LINE_SEPARATOR); |
| | | } |
| | | builder.append(conflictingArgsErrorMessage(arg1, arg2)); |
| | | return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private static boolean argsConflicts(final Argument arg1, final Argument arg2) { |
| | | return arg1.isPresent() && arg2.isPresent(); |
| | | } |
| | | |
| | | /** |
| | | * Returns a {@link LocalizableMessage} which explains to the user |
| | | * that provided {@link Argument}s can not be used together on the command line. |
| | | * |
| | | * @param arg1 |
| | | * The first {@link Argument} which conflicts with {@literal arg2}. |
| | | * @param arg2 |
| | | * The second {@link Argument} which conflicts with {@literal arg1}. |
| | | * @return A {@link LocalizableMessage} which explains to the user that arguments |
| | | * can not be used together on the command line. |
| | | */ |
| | | public static LocalizableMessage conflictingArgsErrorMessage(final Argument arg1, final Argument arg2) { |
| | | return ERR_TOOL_CONFLICTING_ARGS.get(arg1.getLongIdentifier(), arg2.getLongIdentifier()); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | /** |
| | | * An interface for validating user input. |
| | | * |
| | | * @param <T> |
| | | * The type of the decoded input. |
| | | */ |
| | | public interface ValidationCallback<T> { |
| | | |
| | | /** |
| | | * Validates and decodes the user-provided input. Implementations must validate |
| | | * <code>input</code> and return the decoded value if the input is acceptable. |
| | | * If the input is unacceptable, implementations must return |
| | | * <code>null</code> and output a user friendly error message to the provided |
| | | * application console. |
| | | * |
| | | * @param app |
| | | * The console application. |
| | | * @param input |
| | | * The user input to be validated. |
| | | * @return Returns the decoded input if the input is valid, or <code>null</code> if it is not. |
| | | * @throws ClientException |
| | | * If an unexpected error occurred which prevented validation. |
| | | */ |
| | | T validate(ConsoleApplication app, String input) throws ClientException; |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2014 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | /** |
| | | * A handler for printing product version. |
| | | */ |
| | | //@FunctionalInterface |
| | | public interface VersionHandler { |
| | | |
| | | /** Invoked when the version of the product should be printed. */ |
| | | void printVersion(); |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2014 ForgeRock AS. |
| | | */ |
| | | /** |
| | | * Classes implementing the OpenDJ CLI shared APIs. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| New file |
| | |
| | | # |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2014-2016 ForgeRock AS. |
| | | |
| | | ERR_ARG_NO_VALUE_PLACEHOLDER=The %s argument is configured to take \ |
| | | a value but no value placeholder has been defined for it |
| | | ERR_ARG_NO_INT_VALUE=The %s argument does not have any value that \ |
| | | may be retrieved as an integer |
| | | ERR_ARG_CANNOT_DECODE_AS_INT=The provided value "%s" for the %s \ |
| | | argument cannot be decoded as an integer |
| | | ERR_ARG_INT_MULTIPLE_VALUES=The %s argument has multiple values and \ |
| | | therefore cannot be decoded as a single integer value |
| | | ERR_INTARG_LOWER_BOUND_ABOVE_UPPER_BOUND=The %s argument \ |
| | | configuration is invalid because the lower bound of %d is greater than the \ |
| | | upper bound of %d |
| | | ERR_INTARG_VALUE_BELOW_LOWER_BOUND=The provided %s value %d is \ |
| | | unacceptable because it is below the lower bound of %d |
| | | ERR_INTARG_VALUE_ABOVE_UPPER_BOUND=The provided %s value %d is \ |
| | | unacceptable because it is above the upper bound of %d |
| | | ERR_BOOLEANARG_NO_VALUE_ALLOWED=The provided %s value is \ |
| | | unacceptable because Boolean arguments are never allowed to have values |
| | | ERR_MCARG_VALUE_NOT_ALLOWED=The provided %s value %s is \ |
| | | unacceptable because it is not included in the set of allowed values for that \ |
| | | argument |
| | | ERR_FILEARG_NO_SUCH_FILE=The file %s specified for argument %s does \ |
| | | not exist |
| | | ERR_FILEARG_CANNOT_VERIFY_FILE_EXISTENCE=An error occurred while \ |
| | | trying to verify the existence of file %s specified for argument %s: %s |
| | | ERR_FILEARG_CANNOT_OPEN_FILE=An error occurred while trying to open \ |
| | | file %s specified for argument %s for reading: %s |
| | | ERR_FILEARG_CANNOT_READ_FILE=An error occurred while trying to read \ |
| | | from file %s specified for argument %s: %s |
| | | ERR_FILEARG_EMPTY_FILE=The file %s specified for argument %s exists \ |
| | | but is empty |
| | | ERR_ARGPARSER_DUPLICATE_SHORT_ID=Cannot add argument %s to the \ |
| | | argument list because its short identifier -%s conflicts with the %s argument \ |
| | | that has already been defined |
| | | ERR_ARGPARSER_DUPLICATE_LONG_ID=Cannot add argument %s to the \ |
| | | argument list because there is already one defined with the same identifier |
| | | ERR_ARGPARSER_CANNOT_READ_PROPERTIES_FILE=An error occurred while \ |
| | | attempting to read the contents of the argument properties file %s: %s |
| | | ERR_ARGPARSER_TOO_MANY_TRAILING_ARGS=The provided set of \ |
| | | command-line arguments contained too many unnamed trailing arguments. The \ |
| | | maximum number of allowed trailing arguments is %d |
| | | ERR_ARGPARSER_LONG_ARG_WITHOUT_NAME=The provided argument "%s" is \ |
| | | invalid because it does not include the argument name |
| | | ERR_ARGPARSER_NO_ARGUMENT_WITH_LONG_ID=Argument --%s is not allowed \ |
| | | for use with this program |
| | | ERR_ARGPARSER_NO_VALUE_FOR_ARGUMENT_WITH_LONG_ID=Argument --%s \ |
| | | requires a value but none was provided |
| | | ERR_ARGPARSER_VALUE_UNACCEPTABLE_FOR_LONG_ID=The provided value \ |
| | | "%s" for argument --%s is not acceptable: %s |
| | | ERR_ARGPARSER_NOT_MULTIVALUED_FOR_LONG_ID=The argument --%s was \ |
| | | included multiple times in the provided set of arguments but it does not \ |
| | | allow multiple values |
| | | ERR_ARGPARSER_ARG_FOR_LONG_ID_DOESNT_TAKE_VALUE=A value was \ |
| | | provided for argument --%s but that argument does not take a value |
| | | ERR_ARGPARSER_INVALID_DASH_AS_ARGUMENT=The dash character by itself \ |
| | | is invalid for use as an argument name |
| | | ERR_ARGPARSER_NO_ARGUMENT_WITH_SHORT_ID=Argument -%s is not allowed \ |
| | | for use with this program |
| | | ERR_ARGPARSER_NO_VALUE_FOR_ARGUMENT_WITH_SHORT_ID=Argument -%s \ |
| | | requires a value but none was provided |
| | | ERR_ARGPARSER_VALUE_UNACCEPTABLE_FOR_SHORT_ID=The provided value \ |
| | | "%s" for argument -%s is not acceptable: %s |
| | | ERR_ARGPARSER_NOT_MULTIVALUED_FOR_SHORT_ID=The argument -%s was \ |
| | | included multiple times in the provided set of arguments but it does not \ |
| | | allow multiple values |
| | | ERR_ARGPARSER_CANT_MIX_ARGS_WITH_VALUES=The provided argument block \ |
| | | '-%s%s' is illegal because the '%s' argument requires a value but is in the \ |
| | | same block as at least one other argument that does not require a value |
| | | ERR_ARGPARSER_DISALLOWED_TRAILING_ARGUMENT=Argument "%s" does not \ |
| | | start with one or two dashes and unnamed trailing arguments are not allowed |
| | | ERR_ARGPARSER_TOO_FEW_TRAILING_ARGUMENTS=At least %d unnamed \ |
| | | trailing arguments are required in the argument list, but too few were \ |
| | | provided |
| | | ERR_ARGPARSER_NO_VALUE_FOR_REQUIRED_ARG=The argument %s is required \ |
| | | to have a value but none was provided in the argument list and no default \ |
| | | value is available |
| | | INFO_TIME_IN_SECONDS=%d seconds |
| | | INFO_TIME_IN_MINUTES_SECONDS=%d minutes, %d seconds |
| | | INFO_TIME_IN_HOURS_MINUTES_SECONDS=%d hours, %d minutes, %d seconds |
| | | INFO_TIME_IN_DAYS_HOURS_MINUTES_SECONDS=%d days, %d hours, %d minutes, %d \ |
| | | seconds |
| | | INFO_SUBCMDPARSER_WHERE_OPTIONS_INCLUDE=Command options: |
| | | INFO_MENU_PROMPT_RETURN_TO_CONTINUE=Press RETURN to continue |
| | | ERR_CONSOLE_INPUT_ERROR=The response could not be read from the console due to the following error: %s |
| | | INFO_PROMPT_SINGLE_DEFAULT=%s [%s]: |
| | | INFO_ARGPARSER_USAGE_JAVA_CLASSNAME=Usage: java %s {options} |
| | | INFO_ARGPARSER_USAGE_JAVA_SCRIPTNAME=Usage: %s {options} |
| | | INFO_ARGPARSER_USAGE_TRAILINGARGS={trailing-arguments} |
| | | INFO_ARGPARSER_USAGE_DEFAULT_VALUE=Default value: %s |
| | | INFO_SUBCMDPARSER_OPTIONS={options} |
| | | INFO_GLOBAL_OPTIONS=Global Options: |
| | | INFO_GLOBAL_OPTIONS_REFERENCE=See "%s --help" |
| | | INFO_GLOBAL_HELP_REFERENCE=See "%s --help" to get more usage help |
| | | INFO_SUBCMD_OPTIONS=SubCommand Options: |
| | | INFO_ARGPARSER_USAGE=Usage: |
| | | INFO_SUBCMDPARSER_SUBCMD_AND_OPTIONS={subcommand} {options} |
| | | INFO_SUBCMDPARSER_SUBCMD_HELP_HEADING=To get the list of subcommands use: |
| | | INFO_SUBCMDPARSER_SUBCMD_HEADING=Available subcommands: |
| | | ERR_ARG_SUBCOMMAND_INVALID=Invalid subcommand |
| | | INFO_SUBCMDPARSER_GLOBAL_HEADING=The global options are: |
| | | # |
| | | # Extension messages |
| | | # |
| | | # |
| | | # Tools messages |
| | | # |
| | | INFO_DESCRIPTION_TRUSTALL=Trust all server SSL certificates |
| | | INFO_DESCRIPTION_BINDDN=DN to use to bind to the server |
| | | INFO_DESCRIPTION_BINDPASSWORD=Password to use to bind to \ |
| | | the server. Use -w - to ensure that the command prompts for the password, \ |
| | | rather than entering the password as a command argument |
| | | INFO_DESCRIPTION_BINDPASSWORDFILE=Bind password file |
| | | INFO_DESCRIPTION_ENCODING=Use the specified character set for \ |
| | | command-line input |
| | | INFO_DESCRIPTION_VERBOSE=Use verbose mode |
| | | INFO_DESCRIPTION_KEYSTOREPATH=Certificate key store path |
| | | INFO_DESCRIPTION_TRUSTSTOREPATH=Certificate trust store path |
| | | INFO_DESCRIPTION_HOST=Directory server hostname or IP address |
| | | INFO_DESCRIPTION_PORT=Directory server port number |
| | | INFO_DESCRIPTION_SHOWUSAGE=Display this usage information |
| | | INFO_DESCRIPTION_CONTROLS=Use a request control with the provided \ |
| | | information |
| | | INFO_DESCRIPTION_CONTINUE_ON_ERROR=Continue processing even if there are \ |
| | | errors |
| | | INFO_DESCRIPTION_USE_SSL=Use SSL for secure communication with the server |
| | | INFO_DESCRIPTION_START_TLS=Use StartTLS to secure communication with the \ |
| | | server |
| | | INFO_DESCRIPTION_PROXYAUTHZID=Use the proxied authorization \ |
| | | control with the given authorization ID |
| | | INFO_DESCRIPTION_RESTART=Attempt to automatically restart the \ |
| | | server once it has stopped |
| | | INFO_SEARCH_DESCRIPTION_SEARCH_SCOPE=Search scope ('base', 'one', 'sub', \ |
| | | or 'subordinate') |
| | | ERR_LDAPAUTH_UNSUPPORTED_SASL_MECHANISM=The requested SASL mechanism \ |
| | | "%s" is not supported by this client |
| | | ERR_LDAPAUTH_SASL_AUTHID_REQUIRED=The "authid" SASL property is \ |
| | | required for use with the %s mechanism |
| | | INFO_DESCRIPTION_VERSION=LDAP protocol version number |
| | | INFO_DESCRIPTION_NOOP=Show what would be done but do not perform any \ |
| | | operation |
| | | INFO_DESCRIPTION_REPORT_AUTHZID=Use the authorization identity control |
| | | INFO_DESCRIPTION_USE_PWP_CONTROL=Use the password policy request control |
| | | ERR_TOOL_CONFLICTING_ARGS=You may not provide both the --%s and \ |
| | | the --%s arguments |
| | | ERR_TOOL_SASLEXTERNAL_NEEDS_SSL_OR_TLS=SASL EXTERNAL \ |
| | | authentication may only be requested if SSL or StartTLS is used |
| | | ERR_TOOL_SASLEXTERNAL_NEEDS_KEYSTORE=SASL EXTERNAL authentication \ |
| | | may only be used if a client certificate key store is specified |
| | | INFO_DESCRIPTION_TRUSTSTOREPASSWORD=Certificate trust store PIN |
| | | INFO_DESCRIPTION_TRUSTSTOREPASSWORD_FILE=Certificate trust store PIN file |
| | | INFO_DESCRIPTION_PRODUCT_VERSION=Display Directory Server version \ |
| | | information |
| | | INFO_DESCRIPTION_SCRIPT_FRIENDLY=Use script-friendly mode |
| | | ERR_LDAP_CONN_CANNOT_INITIALIZE_SSL=ERROR: Unable to perform SSL \ |
| | | initialization: %s |
| | | ERR_LDAP_CONN_CANNOT_PARSE_SASL_OPTION=ERROR: The provided SASL \ |
| | | option string "%s" could not be parsed in the form "name=value" |
| | | INFO_LDAP_CONN_DESCRIPTION_SASLOPTIONS=SASL bind options |
| | | INFO_DESCRIPTION_PROP_FILE_PATH=Path to the file containing default \ |
| | | property values used for command line arguments |
| | | INFO_DESCRIPTION_NO_PROP_FILE=No properties file will be \ |
| | | used to get default command line argument values |
| | | INFO_DESCRIPTION_GENERAL_ARGS=General options: |
| | | INFO_DESCRIPTION_IO_ARGS=Utility input/output options: |
| | | INFO_DESCRIPTION_LDAP_CONNECTION_ARGS=LDAP connection options: |
| | | INFO_FILE_PLACEHOLDER={file} |
| | | INFO_KEYSTOREPATH_PLACEHOLDER={keyStorePath} |
| | | INFO_TRUSTSTOREPATH_PLACEHOLDER={trustStorePath} |
| | | INFO_BINDPWD_FILE_PLACEHOLDER={bindPasswordFile} |
| | | INFO_HOST_PLACEHOLDER={host} |
| | | INFO_PORT_PLACEHOLDER={port} |
| | | INFO_BASEDN_PLACEHOLDER={baseDN} |
| | | INFO_BINDDN_PLACEHOLDER={bindDN} |
| | | INFO_BINDPWD_PLACEHOLDER={bindPassword} |
| | | INFO_KEYSTORE_PWD_PLACEHOLDER={keyStorePassword} |
| | | INFO_TRUSTSTORE_PWD_FILE_PLACEHOLDER={path} |
| | | INFO_TRUSTSTORE_PWD_PLACEHOLDER={trustStorePassword} |
| | | INFO_NICKNAME_PLACEHOLDER={nickname} |
| | | INFO_PROXYAUTHID_PLACEHOLDER={authzID} |
| | | INFO_SASL_OPTION_PLACEHOLDER={name=value} |
| | | INFO_PROTOCOL_VERSION_PLACEHOLDER={version} |
| | | INFO_PROP_FILE_PATH_PLACEHOLDER={propertiesFilePath} |
| | | INFO_NUM_ENTRIES_PLACEHOLDER={numEntries} |
| | | INFO_LDAP_CONTROL_PLACEHOLDER={controloid[:criticality[:value|::b64value|:<filePath]]} |
| | | INFO_ENCODING_PLACEHOLDER={encoding} |
| | | INFO_SEARCH_SCOPE_PLACEHOLDER={searchScope} |
| | | INFO_KEYSTORE_PWD_FILE_PLACEHOLDER={keyStorePasswordFile} |
| | | INFO_PATH_PLACEHOLDER={path} |
| | | INFO_CONFIGCLASS_PLACEHOLDER={configClass} |
| | | INFO_CONFIGFILE_PLACEHOLDER={configFile} |
| | | INFO_ADMINUID_PLACEHOLDER={adminUID} |
| | | ERR_CANNOT_READ_TRUSTSTORE=Cannot access trust store '%s'. Verify \ |
| | | that the provided trust store exists and that you have read access rights to it |
| | | ERR_CANNOT_READ_KEYSTORE=Cannot access key store '%s'. Verify \ |
| | | that the provided key store exists and that you have read access rights to it |
| | | INFO_DESCRIPTION_ADMIN_PORT=Directory server administration port number |
| | | INFO_DESCRIPTION_ADMIN_BINDDN=Administrator user bind DN |
| | | INFO_ERROR_EMPTY_RESPONSE=ERROR: a response must be provided in order to continue |
| | | # |
| | | # MakeLDIF tool |
| | | # |
| | | INFO_DESCRIPTION_QUIET=Use quiet mode |
| | | INFO_DESCRIPTION_NO_PROMPT=Use non-interactive mode. If data in \ |
| | | the command is missing, the user is not prompted and the tool will fail |
| | | INFO_OPTION_ACCEPT_LICENSE=Automatically accepts the product license \ |
| | | (if present) |
| | | # |
| | | # Setup messages |
| | | # |
| | | INFO_ARGUMENT_DESCRIPTION_CLI=Use the command line install. \ |
| | | If not specified the graphical interface will be launched. The rest of the \ |
| | | options (excluding help and version) will only be taken into account if this \ |
| | | option is specified |
| | | INFO_ARGUMENT_DESCRIPTION_BASEDN=Base DN for user \ |
| | | information in the Directory Server. Multiple base DNs may be provided by \ |
| | | using this option multiple times |
| | | INFO_ARGUMENT_DESCRIPTION_ADDBASE=Indicates whether to create the base \ |
| | | entry in the Directory Server database |
| | | INFO_LDIFFILE_PLACEHOLDER={ldifFile} |
| | | INFO_REJECT_FILE_PLACEHOLDER={rejectFile} |
| | | INFO_SKIP_FILE_PLACEHOLDER={skipFile} |
| | | INFO_JMXPORT_PLACEHOLDER={jmxPort} |
| | | INFO_ROOT_USER_DN_PLACEHOLDER={rootUserDN} |
| | | INFO_ROOT_USER_PWD_PLACEHOLDER={rootUserPassword} |
| | | INFO_ROOT_USER_PWD_FILE_PLACEHOLDER={rootUserPasswordFile} |
| | | INFO_TIMEOUT_PLACEHOLDER={timeout} |
| | | INFO_GENERAL_DESCRIPTION_REJECTED_FILE=Write rejected entries to the \ |
| | | specified file |
| | | INFO_GENERAL_DESCRIPTION_SKIPPED_FILE=Write skipped entries to the \ |
| | | specified file |
| | | INFO_SETUP_DESCRIPTION_SAMPLE_DATA=Specifies that the database should \ |
| | | be populated with the specified number of sample entries |
| | | INFO_ARGUMENT_DESCRIPTION_LDAPPORT=Port on which the \ |
| | | Directory Server should listen for LDAP communication |
| | | INFO_ARGUMENT_DESCRIPTION_ADMINCONNECTORPORT=Port on which the \ |
| | | Administration Connector should listen for communication |
| | | INFO_ARGUMENT_DESCRIPTION_SKIPPORT=Skip the check to determine whether \ |
| | | the specified ports are usable |
| | | INFO_ARGUMENT_DESCRIPTION_ROOTDN=DN for the initial root \ |
| | | user for the Directory Server |
| | | INFO_ARGUMENT_DESCRIPTION_ROOTPWFILE=Path to a file \ |
| | | containing the password for the initial root user for the Directory Server |
| | | INFO_ARGUMENT_DESCRIPTION_ENABLE_WINDOWS_SERVICE=Enable the server to run \ |
| | | as a Windows Service |
| | | INFO_ARGUMENT_DESCRIPTION_LDAPSPORT=Port on which the \ |
| | | Directory Server should listen for LDAPS communication. The LDAPS port will \ |
| | | be configured and SSL will be enabled only if this argument is explicitly \ |
| | | specified |
| | | INFO_ARGUMENT_DESCRIPTION_HOST_NAME=The fully-qualified directory server \ |
| | | host name that will be used when generating self-signed \ |
| | | certificates for LDAP SSL/StartTLS, the administration connector, and \ |
| | | replication |
| | | INFO_ARGUMENT_DESCRIPTION_USE_SELF_SIGNED_CERTIFICATE=Generate a \ |
| | | self-signed certificate that the server should use when accepting SSL-based \ |
| | | connections or performing StartTLS negotiation |
| | | INFO_ARGUMENT_DESCRIPTION_USE_PKCS11=Use a certificate in a \ |
| | | PKCS#11 token that the server should use when accepting SSL-based \ |
| | | connections or performing StartTLS negotiation |
| | | INFO_ARGUMENT_DESCRIPTION_USE_JAVAKEYSTORE=Path of a Java \ |
| | | Key Store (JKS) containing a certificate to be used as the server certificate |
| | | INFO_ARGUMENT_DESCRIPTION_USE_JCEKS=Path of a JCEKS containing a \ |
| | | certificate to be used as the server certificate |
| | | INFO_ARGUMENT_DESCRIPTION_USE_PKCS12=Path of a PKCS#12 key \ |
| | | store containing the certificate that the server should use when accepting \ |
| | | SSL-based connections or performing StartTLS negotiation |
| | | INFO_ARGUMENT_DESCRIPTION_CERT_NICKNAME=Nickname of the \ |
| | | certificate that the server should use when accepting SSL-based \ |
| | | connections or performing StartTLS negotiation |
| | | INFO_ARGUMENT_DESCRIPTION_KEYSTOREPASSWORD=Certificate key store PIN. \ |
| | | A PIN is required when you specify to use an existing certificate \ |
| | | as server certificate |
| | | INFO_ARGUMENT_DESCRIPTION_KEYSTOREPASSWORD_FILE=Certificate key store \ |
| | | PIN file. A PIN is required when you specify to use an existing certificate \ |
| | | as server certificate |
| | | INFO_SETUP_DESCRIPTION_DO_NOT_START=Do not start the server when the \ |
| | | configuration is completed |
| | | INFO_SETUP_DESCRIPTION_ENABLE_STARTTLS=Enable StartTLS to allow \ |
| | | secure communication with the server using the LDAP port |
| | | # |
| | | # SubCommandes messages |
| | | # |
| | | ERR_ARG_SUBCOMMAND_DUPLICATE_SUBCOMMAND=The argument parser already \ |
| | | has a %s subcommand |
| | | ERR_ARG_SUBCOMMAND_DUPLICATE_ARGUMENT_NAME=There are multiple \ |
| | | arguments for subcommand %s with name %s |
| | | ERR_ARG_SUBCOMMAND_ARGUMENT_GLOBAL_CONFLICT=Argument %s for \ |
| | | subcommand %s conflicts with a global argument with the same name |
| | | ERR_ARG_SUBCOMMAND_DUPLICATE_SHORT_ID=Argument %s for subcommand %s \ |
| | | has a short identifier -%s that conflicts with that of argument %s |
| | | ERR_ARG_SUBCOMMAND_ARGUMENT_SHORT_ID_GLOBAL_CONFLICT=Argument %s \ |
| | | for subcommand %s has a short ID -%s that conflicts with that of global \ |
| | | argument %s |
| | | ERR_ARG_SUBCOMMAND_DUPLICATE_LONG_ID=Failed to add Argument %s for subcommand %s \ |
| | | because there is already an argument with the same identifier for this subcommand |
| | | ERR_ARG_SUBCOMMAND_ARGUMENT_LONG_ID_GLOBAL_CONFLICT=Failed to add Argument %s for \ |
| | | subcommand %s because there is already a global argument defined with the \ |
| | | same long identifier |
| | | ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_NAME=There is already another \ |
| | | global argument named "%s" |
| | | ERR_SUBCMDPARSER_GLOBAL_ARG_NAME_SUBCMD_CONFLICT=The argument name \ |
| | | %s conflicts with the name of another argument associated with the %s \ |
| | | subcommand |
| | | ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_SHORT_ID=Short ID -%s for \ |
| | | global argument %s conflicts with the short ID of another global argument %s |
| | | ERR_SUBCMDPARSER_GLOBAL_ARG_SHORT_ID_CONFLICT=Short ID -%s for \ |
| | | global argument %s conflicts with the short ID for the %s argument associated \ |
| | | with subcommand %s |
| | | ERR_SUBCMDPARSER_DUPLICATE_GLOBAL_ARG_LONG_ID=Failed to add global argument \ |
| | | %s because there is already one defined with the same long identifier |
| | | ERR_SUBCMDPARSER_GLOBAL_ARG_LONG_ID_CONFLICT=Failed to add argument %s to \ |
| | | subcommand %s because there is already one argument with the same long identifier \ |
| | | associated to this subcommand. |
| | | ERR_SUBCMDPARSER_LONG_ARG_WITHOUT_NAME=The provided command-line \ |
| | | argument %s does not contain an argument name |
| | | ERR_SUBCMDPARSER_NO_GLOBAL_ARGUMENT_FOR_LONG_ID=The provided \ |
| | | argument --%s is not a valid global argument identifier |
| | | ERR_SUBCMDPARSER_NO_ARGUMENT_FOR_LONG_ID=The provided argument --%s \ |
| | | is not a valid global or subcommand argument identifier |
| | | ERR_SUBCMDPARSER_NO_VALUE_FOR_ARGUMENT_WITH_LONG_ID=Command-line \ |
| | | argument --%s requires a value but none was given |
| | | ERR_SUBCMDPARSER_VALUE_UNACCEPTABLE_FOR_LONG_ID=The provided value \ |
| | | "%s" for argument --%s is not acceptable: %s |
| | | ERR_SUBCMDPARSER_NOT_MULTIVALUED_FOR_LONG_ID=The argument --%s was \ |
| | | included multiple times in the provided set of arguments but it does not \ |
| | | allow multiple values |
| | | ERR_SUBCMDPARSER_ARG_FOR_LONG_ID_DOESNT_TAKE_VALUE=A value was \ |
| | | provided for argument --%s but that argument does not take a value |
| | | ERR_SUBCMDPARSER_INVALID_DASH_AS_ARGUMENT=The dash character by \ |
| | | itself is invalid for use as an argument name |
| | | ERR_SUBCMDPARSER_NO_GLOBAL_ARGUMENT_FOR_SHORT_ID=The provided \ |
| | | argument -%s is not a valid global argument identifier |
| | | ERR_SUBCMDPARSER_NO_ARGUMENT_FOR_SHORT_ID=The provided argument \ |
| | | -%s is not a valid global or subcommand argument identifier |
| | | ERR_SUBCMDPARSER_NO_VALUE_FOR_ARGUMENT_WITH_SHORT_ID=Argument -%s \ |
| | | requires a value but none was provided |
| | | ERR_SUBCMDPARSER_VALUE_UNACCEPTABLE_FOR_SHORT_ID=The provided \ |
| | | value "%s" for argument -%s is not acceptable: %s |
| | | ERR_SUBCMDPARSER_NOT_MULTIVALUED_FOR_SHORT_ID=The argument -%s was \ |
| | | included multiple times in the provided set of arguments but it does not \ |
| | | allow multiple values |
| | | ERR_SUBCMDPARSER_CANT_MIX_ARGS_WITH_VALUES=The provided argument \ |
| | | block '-%s%s' is illegal because the '%s' argument requires a value but is in \ |
| | | the same block as at least one other argument that does not require a value |
| | | ERR_SUBCMDPARSER_INVALID_ARGUMENT=The provided argument "%s" is \ |
| | | not recognized |
| | | ERR_INCOMPATIBLE_JAVA_VERSION=The minimum Java version required is %s.%n%n\ |
| | | The detected version is %s.%nThe binary detected is %s%n%nPlease set \ |
| | | OPENDJ_JAVA_HOME to the root of a compatible Java installation or edit the \ |
| | | java.properties file and then run the dsjavaproperties script to specify the \ |
| | | java version to be used. |
| | | INFO_DESCRIPTION_CONNECTION_TIMEOUT=Maximum length of time (in \ |
| | | milliseconds) that can be taken to establish a connection. Use '0' to \ |
| | | specify no time out |
| | | ERR_MENU_BAD_CHOICE_MULTI=Invalid response. Please enter one or \ |
| | | more valid menu options |
| | | ERR_MENU_BAD_CHOICE_SINGLE=Invalid response. Please enter a valid \ |
| | | menu option |
| | | ERR_MENU_BAD_CHOICE_MULTI_DUPE=The option "%s" was specified \ |
| | | more than once. Please enter one or more valid menu options |
| | | INFO_MENU_PROMPT_MULTI_DEFAULT=Enter one or more choices separated by commas [%s]: |
| | | INFO_MENU_PROMPT_MULTI=Enter one or more choices separated by commas: |
| | | INFO_MENU_PROMPT_SINGLE_DEFAULT=Enter choice [%s]: |
| | | INFO_MENU_PROMPT_SINGLE=Enter choice: |
| | | INFO_MENU_PROMPT_CONFIRM=%s (%s / %s) [%s]: |
| | | INFO_MENU_OPTION_HELP=help |
| | | INFO_MENU_OPTION_HELP_KEY=? |
| | | INFO_MENU_OPTION_CANCEL=cancel |
| | | INFO_MENU_OPTION_CANCEL_KEY=c |
| | | INFO_MENU_OPTION_QUIT=quit |
| | | INFO_MENU_OPTION_QUIT_KEY=q |
| | | INFO_MENU_NUMERIC_OPTION=%d) |
| | | INFO_MENU_CHAR_OPTION=%c) |
| | | INFO_MENU_OPTION_BACK=back |
| | | INFO_MENU_OPTION_BACK_KEY=b |
| | | INFO_GENERAL_NO=no |
| | | INFO_GENERAL_YES=yes |
| | | ERR_CONSOLE_APP_CONFIRM=Invalid response. Please enter \ |
| | | "%s" or "%s" |
| | | ERR_TRIES_LIMIT_REACHED=Input tries limit reached (%d) |
| | | ERR_BAD_PORT_NUMBER=Invalid port number "%s". Please \ |
| | | enter a valid port number between 1 and 65535 |
| | | INFO_OPERATION_START_TIME_MESSAGE=Operation date: %s |
| | | INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER=Error reading data from \ |
| | | server %s. There is an error with the certificate presented by the \ |
| | | server.\nDetails: %s |
| | | INFO_CANNOT_CONNECT_TO_REMOTE_AUTHENTICATION=The provided credentials are not \ |
| | | valid in server %s. Details: %s |
| | | INFO_CANNOT_CONNECT_TO_REMOTE_PERMISSIONS=You do not have enough access \ |
| | | rights to read the configuration in %s. %nProvide credentials with enough \ |
| | | rights. Details: %s |
| | | ERR_CANNOT_CONNECT_TO_REMOTE_COMMUNICATION=Could not connect to \ |
| | | %s. Check that the server is running and that it is accessible \ |
| | | from the local machine. Details: %s |
| | | INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC=Could not connect to %s. Check that the \ |
| | | server is running and that the provided credentials are valid.%nError \ |
| | | details:%n%s |
| | | ERR_CONFIRMATION_TRIES_LIMIT_REACHED=Confirmation tries limit reached (%d) |
| | | INFO_DESCRIPTION_DISPLAY_EQUIVALENT=Display the equivalent \ |
| | | non-interactive argument in the standard output when this command is run in \ |
| | | interactive mode |
| | | INFO_DESCRIPTION_ADVANCED=Allows the configuration of advanced \ |
| | | components and properties |
| | | INFO_DESCRIPTION_REMOTE=Connect to a remote server |
| | | INFO_DESCRIPTION_CONFIG_CLASS=The fully-qualified name of the Java class \ |
| | | to use as the Directory Server configuration handler. If this is not \ |
| | | provided, then a default of org.opends.server.extensions.ConfigFileHandler \ |
| | | will be used |
| | | INFO_DESCRIPTION_CONFIG_FILE=Path to the Directory Server \ |
| | | configuration file |
| | | INFO_LDAPAUTH_PASSWORD_PROMPT=Password for user '%s': |
| | | # |
| | | # Uninstall messages |
| | | # |
| | | # |
| | | # Connection messages |
| | | # |
| | | INFO_EXCEPTION_OUT_OF_MEMORY_DETAILS=Not enough memory to perform the \ |
| | | operation. Details: %s |
| | | INFO_EXCEPTION_DETAILS=Details: %s |
| | | INFO_LDAP_CONN_PROMPT_SECURITY_SERVER_CERTIFICATE=Server Certificate: |
| | | INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE=%s |
| | | INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION=Do you trust this server certificate? |
| | | INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_NO=No |
| | | INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_SESSION=Yes, for this session only |
| | | INFO_LDAP_CONN_PROMPT_SECURITY_TRUST_OPTION_ALWAYS=Yes, also add it to a truststore |
| | | INFO_LDAP_CONN_PROMPT_SECURITY_CERTIFICATE_DETAILS=View certificate details |
| | | INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_USER_DN=User DN : %s |
| | | INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_VALIDITY=Validity : From '%s'%n To '%s' |
| | | INFO_LDAP_CONN_SECURITY_SERVER_CERTIFICATE_ISSUER=Issuer : %s |
| | | INFO_LDAP_CONN_HEADING_CONNECTION_PARAMETERS=>>>> Specify OpenDJ LDAP \ |
| | | connection parameters |
| | | ERR_ERROR_CANNOT_READ_PASSWORD=Unable to read password |
| | | ERR_ERROR_CANNOT_READ_BIND_NAME=Unable to read bind name |
| | | ERR_ERROR_CANNOT_READ_HOST_NAME=Cannot read the host name |
| | | |
| | | # Strings for generated reference documentation. |
| | | REF_TITLE_DESCRIPTION=Description |
| | | REF_TITLE_OPTIONS=Options |
| | | REF_INTRO_OPTIONS=The <command>%s</command> command takes the following options: |
| | | REF_DEFAULT=Default: %s |
| | | REF_TITLE_SUBCOMMANDS=Subcommands |
| | | REF_INTRO_SUBCOMMANDS=The <command>%s</command> command supports the following subcommands: |
| | | REF_PART_TITLE_SUBCOMMANDS=%s Subcommands Reference |
| | | REF_PART_INTRO_SUBCOMMANDS=This section covers <command>%s</command> subcommands. |
| | | REF_DEFAULT_BACKEND_TYPE=Default: <literal>je</literal> for standard edition, \ |
| | | <literal>pdb</literal> for OEM edition. |
| | | |
| | | # Supplements to descriptions for generated reference documentation. |
| | | SUPPLEMENT_DESCRIPTION_CONTROLS=<xinclude:include href="variablelist-ldap-controls.xml" /> |
| New file |
| | |
| | | # |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2016 ForgeRock AS. |
| | | # |
| | | |
| | | ERR_TOOL_CONFLICTING_ARGS=ERROR: Potser nou heu introdu\u00eft ambd\u00f3s arguments %s i %s al mateix cop |
| New file |
| | |
| | | # |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2016 ForgeRock AS. |
| | | # |
| | | |
| | | ERR_TOOL_CONFLICTING_ARGS=Sie haben m\u00f6glicherweise nicht beide Argumente --%s und --%s angegeben |
| New file |
| | |
| | | # |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2016 ForgeRock AS. |
| | | # |
| | | |
| | | ERR_TOOL_CONFLICTING_ARGS=No se pueden proporcionar los argumentos --%s y --%s conjuntamente |
| New file |
| | |
| | | # |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2016 ForgeRock AS. |
| | | # |
| | | |
| | | ERR_TOOL_CONFLICTING_ARGS=Vous ne pouvez pas utiliser \u00e0 la fois les arguments --%s et --%s |
| New file |
| | |
| | | # |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2016 ForgeRock AS. |
| | | # |
| | | |
| | | ERR_TOOL_CONFLICTING_ARGS=--%s \u5f15\u6570\u3068 --%s \u5f15\u6570\u306e\u4e21\u65b9\u306f\u6307\u5b9a\u3067\u304d\u307e\u305b\u3093 |
| New file |
| | |
| | | # |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2016 ForgeRock AS. |
| | | # |
| | | |
| | | ERR_TOOL_CONFLICTING_ARGS=--%s \uc778\uc218\uc640 --%s \uc778\uc218\ub97c \ubaa8\ub450 \uc81c\uacf5\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4. |
| New file |
| | |
| | | # |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2016 ForgeRock AS. |
| | | # |
| | | |
| | | ERR_TOOL_CONFLICTING_ARGS=B\u0141\u0104D\: Nie mo\u017cesz poda\u0107 obydwu arument\u00f3w %s i %s w tym samym czasie |
| New file |
| | |
| | | # |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2016 ForgeRock AS. |
| | | # |
| | | |
| | | ERR_TOOL_CONFLICTING_ARGS=\u4e0d\u80fd\u540c\u65f6\u63d0\u4f9b --%s \u548c --%s \u53c2\u6570 |
| New file |
| | |
| | | # |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2016 ForgeRock AS. |
| | | # |
| | | |
| | | ERR_TOOL_CONFLICTING_ARGS=\u60a8\u7121\u6cd5\u540c\u6642\u63d0\u4f9b --%s \u8207 --%s \u5f15\u6578 |
| New file |
| | |
| | | <#-- |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2015 ForgeRock AS. |
| | | #--> |
| | | <refsect1 xml:id="${id}"> |
| | | <title>${title}</title> |
| | | |
| | | <para> |
| | | ${intro} |
| | | </para> |
| | | |
| | | ${list} |
| | | </refsect1> |
| New file |
| | |
| | | <#-- |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2015 ForgeRock AS. |
| | | #--> |
| | | <listitem> |
| | | <para> |
| | | <link |
| | | <#-- Link to the Reference. Change this if the pages move to another document. --> |
| | | xlink:href="reference#${id}" |
| | | xlink:role="http://docbook.org/xlink/role/olink" |
| | | xlink:show="new" |
| | | ><command>${name}</command></link>: ${description} |
| | | </para> |
| | | </listitem> |
| New file |
| | |
| | | <#-- |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2015 ForgeRock AS. |
| | | #--> |
| | | <variablelist> |
| | | |
| | | <para> |
| | | ${dependencies} |
| | | </para> |
| | | |
| | | <para> |
| | | ${typesIntro} |
| | | </para> |
| | | |
| | | <#list children as child> |
| | | <varlistentry> |
| | | <term>${child.name}</term> |
| | | <listitem> |
| | | <para> |
| | | ${child.default} |
| | | </para> |
| | | |
| | | <para> |
| | | ${child.enabled} |
| | | </para> |
| | | |
| | | <para> |
| | | ${child.link} |
| | | </para> |
| | | </listitem> |
| | | </varlistentry> |
| | | </#list> |
| | | |
| | | </variablelist> |
| New file |
| | |
| | | <#-- |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2015 ForgeRock AS. |
| | | #--> |
| | | ${marker} |
| | | <reference xml:id="${name}-subcommands-ref" |
| | | xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="${locale}" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://docbook.org/ns/docbook |
| | | http://docbook.org/xml/5.0/xsd/docbook.xsd" |
| | | xmlns:xinclude="http://www.w3.org/2001/XInclude"> |
| | | |
| | | <title>${title}</title> |
| | | |
| | | <partintro> |
| | | <para> |
| | | ${partintro} |
| | | </para> |
| | | </partintro> |
| | | |
| | | <#list subcommands as subcommand> |
| | | <xinclude:include href="man-${subcommand.id}.xml" /> |
| | | </#list> |
| | | </reference> |
| New file |
| | |
| | | ${marker} |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!-- |
| | | The contents of this file are subject to the terms of the Common Development and |
| | | Distribution License (the License). You may not use this file except in compliance with the |
| | | License. |
| | | |
| | | You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | specific language governing permission and limitations under the License. |
| | | |
| | | When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | information: "Portions Copyright [year] [name of copyright owner]". |
| | | |
| | | Copyright 2011-${year} ForgeRock AS. |
| | | --> |
| | | <refentry xml:id="${id}" |
| | | xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="${locale}" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://docbook.org/ns/docbook |
| | | http://docbook.org/xml/5.0/xsd/docbook.xsd" |
| | | xmlns:xlink="http://www.w3.org/1999/xlink" |
| | | xmlns:xinclude="http://www.w3.org/2001/XInclude"> |
| | | |
| | | <info> |
| | | <copyright> |
| | | <year>2011-${year}</year> |
| | | <holder>ForgeRock AS.</holder> |
| | | </copyright> |
| | | </info> |
| | | |
| | | <refmeta> |
| | | <refentrytitle>${name}</refentrytitle><manvolnum>1</manvolnum> |
| | | <refmiscinfo class="software">OpenDJ</refmiscinfo> |
| | | <refmiscinfo class="version">${r"${project.version}"}</refmiscinfo> |
| | | </refmeta> |
| | | |
| | | <refnamediv> |
| | | <refname>${name}</refname> |
| | | <refpurpose>${purpose}</refpurpose> |
| | | </refnamediv> |
| | | |
| | | <refsynopsisdiv> |
| | | <cmdsynopsis> |
| | | <command>${name}</command> |
| | | <arg choice="plain">${args}</arg> |
| | | </cmdsynopsis> |
| | | </refsynopsisdiv> |
| | | |
| | | <refsect1 xml:id="${id}-description"> |
| | | <title>${descTitle}</title> |
| | | |
| | | <para> |
| | | ${description?ensure_ends_with(".")} |
| | | </para> |
| | | |
| | | <#if info??>${info}</#if> |
| | | </refsect1> |
| | | |
| | | <#if options??> |
| | | <refsect1 xml:id="${id}-options"> |
| | | <title>${optionsTitle}</title> |
| | | |
| | | <variablelist> |
| | | <para> |
| | | ${optionsIntro} |
| | | </para> |
| | | |
| | | <#list options as option> |
| | | <varlistentry> |
| | | <term><option>${option.synopsis?xml}</option></term> |
| | | <listitem> |
| | | <para> |
| | | ${option.description?ensure_ends_with(".")} |
| | | </para> |
| | | |
| | | <#if option.info??> |
| | | <#if option.info.usage??>${option.info.usage}</#if> |
| | | |
| | | <#if option.info.default??> |
| | | <para> |
| | | ${option.info.default} |
| | | </para> |
| | | </#if> |
| | | |
| | | <#if option.info.doc??>${option.info.doc}</#if> |
| | | </#if> |
| | | </listitem> |
| | | </varlistentry> |
| | | </#list> |
| | | </variablelist> |
| | | </refsect1> |
| | | </#if> |
| | | |
| | | <#if propertiesInfo??>${propertiesInfo}</#if> |
| | | </refentry> |
| New file |
| | |
| | | <#-- |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2015 ForgeRock AS. |
| | | #--> |
| | | <varlistentry> |
| | | <term>${term}</term> |
| | | <listitem> |
| | | ${definition} |
| | | </listitem> |
| | | </varlistentry> |
| New file |
| | |
| | | <#-- |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2015 ForgeRock AS. |
| | | #--> |
| | | <variablelist> |
| | | |
| | | <#list properties as property> |
| | | |
| | | <varlistentry> |
| | | <term>${property.term}</term> |
| | | <listitem> |
| | | <variablelist> |
| | | |
| | | <varlistentry> |
| | | <term>${property.descTitle}</term> |
| | | <listitem> |
| | | <para> |
| | | ${property.description} |
| | | </para> |
| | | </listitem> |
| | | </varlistentry> |
| | | |
| | | ${property.list} |
| | | </variablelist> |
| | | </listitem> |
| | | </varlistentry> |
| | | </#list> |
| | | |
| | | </variablelist> |
| New file |
| | |
| | | <#-- |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2015 ForgeRock AS. |
| | | #--> |
| | | <refsect1 xml:id="${name}-options"> |
| | | <title>${title}</title> |
| | | |
| | | <para> |
| | | ${intro} |
| | | </para> |
| | | |
| | | <#list groups as group> |
| | | <variablelist> |
| | | <#if group.description??> |
| | | <para> |
| | | ${group.description} |
| | | </para> |
| | | </#if> |
| | | |
| | | <#list group.options as option> |
| | | <varlistentry> |
| | | <term><option>${option.synopsis?xml}</option></term> |
| | | <listitem> |
| | | <para> |
| | | ${option.description?ensure_ends_with(".")} |
| | | </para> |
| | | |
| | | <#if option.default??> |
| | | <para> |
| | | ${option.default} |
| | | </para> |
| | | </#if> |
| | | |
| | | <#if option.info??>${option.info}</#if> |
| | | </listitem> |
| | | </varlistentry> |
| | | </#list> |
| | | </variablelist> |
| | | </#list> |
| | | </refsect1> |
| New file |
| | |
| | | <#-- |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2015 ForgeRock AS. |
| | | #--> |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!-- |
| | | The contents of this file are subject to the terms of the Common Development and |
| | | Distribution License (the License). You may not use this file except in compliance with the |
| | | License. |
| | | |
| | | You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | specific language governing permission and limitations under the License. |
| | | |
| | | When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | information: "Portions Copyright [year] [name of copyright owner]". |
| | | |
| | | Copyright 2011-${year} ForgeRock AS. |
| | | --> |
| | | <refentry xml:id="${name}-1" |
| | | xmlns="http://docbook.org/ns/docbook" version="5.0" xml:lang="${locale}" |
| | | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
| | | xsi:schemaLocation="http://docbook.org/ns/docbook |
| | | http://docbook.org/xml/5.0/xsd/docbook.xsd" |
| | | xmlns:xlink="http://www.w3.org/1999/xlink" |
| | | xmlns:xinclude="http://www.w3.org/2001/XInclude"> |
| | | |
| | | <info> |
| | | <copyright> |
| | | <year>2011-${year}</year> |
| | | <holder>ForgeRock AS.</holder> |
| | | </copyright> |
| | | </info> |
| | | |
| | | <refmeta> |
| | | <refentrytitle>${name}</refentrytitle><manvolnum>1</manvolnum> |
| | | <refmiscinfo class="software">OpenDJ</refmiscinfo> |
| | | <refmiscinfo class="version">${r"${project.version}"}</refmiscinfo> |
| | | </refmeta> |
| | | |
| | | <refnamediv> |
| | | <refname>${name}</refname> |
| | | <refpurpose>${shortDesc}</refpurpose> |
| | | </refnamediv> |
| | | |
| | | <refsynopsisdiv> |
| | | <cmdsynopsis> |
| | | <command>${name}</command> |
| | | <#if args??><arg choice="plain">${args}</arg></#if> |
| | | </cmdsynopsis> |
| | | </refsynopsisdiv> |
| | | |
| | | <refsect1 xml:id="${name}-description"> |
| | | <title>${descTitle}</title> |
| | | |
| | | <para> |
| | | ${description?ensure_ends_with(".")} |
| | | </para> |
| | | |
| | | <#if info??>${info}</#if> |
| | | </refsect1> |
| | | |
| | | <#if optionSection??> |
| | | ${optionSection} |
| | | </#if> |
| | | |
| | | <#if subcommands??> |
| | | ${subcommands} |
| | | </#if> |
| | | |
| | | <#if trailingSectionString??> |
| | | ${trailingSectionString} |
| | | </#if> |
| | | </refentry> |
| New file |
| | |
| | | <#-- |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2015 ForgeRock AS. |
| | | #--> |
| | | <refsect1 xml:id="${name}-subcommands"> |
| | | <title>${title}</title> |
| | | |
| | | <#if info??> |
| | | ${info} |
| | | </#if> |
| | | |
| | | <para> |
| | | ${intro} |
| | | </para> |
| | | |
| | | <#if isItemizedList??><itemizedlist></#if> |
| | | <#list subcommands as subcommand> |
| | | ${subcommand} |
| | | </#list> |
| | | <#if isItemizedList??></itemizedlist></#if> |
| | | </refsect1> |
| New file |
| | |
| | | <#-- |
| | | # The contents of this file are subject to the terms of the Common Development and |
| | | # Distribution License (the License). You may not use this file except in compliance with the |
| | | # License. |
| | | # |
| | | # You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | # specific language governing permission and limitations under the License. |
| | | # |
| | | # When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | # the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | # Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | # information: "Portions Copyright [year] [name of copyright owner]". |
| | | # |
| | | # Copyright 2015 ForgeRock AS. |
| | | #--> |
| | | <refsect2 xml:id="${id}"> |
| | | <title>${name}</title> |
| | | |
| | | <para> |
| | | ${description?ensure_ends_with(".")} |
| | | </para> |
| | | |
| | | <#if info??>${info}</#if> |
| | | |
| | | <#if options??> |
| | | <refsect3 xml:id="${id}-options"> |
| | | <title>${optionsTitle}</title> |
| | | |
| | | <variablelist> |
| | | <para> |
| | | ${optionsIntro} |
| | | </para> |
| | | |
| | | <#list options as option> |
| | | |
| | | <varlistentry> |
| | | <term><option>${option.synopsis?xml}</option></term> |
| | | <listitem> |
| | | <para> |
| | | ${option.description?ensure_ends_with(".")} |
| | | </para> |
| | | |
| | | <#if option.info??> |
| | | <#if option.info.usage??>${option.info.usage}</#if> |
| | | |
| | | <#if option.info.default??> |
| | | <para> |
| | | ${option.info.default} |
| | | </para> |
| | | </#if> |
| | | |
| | | <#if option.info.doc??>${option.info.doc}</#if> |
| | | </#if> |
| | | </listitem> |
| | | </varlistentry> |
| | | |
| | | </#list> |
| | | </variablelist> |
| | | </refsect3> |
| | | </#if> |
| | | |
| | | <#if propertiesInfo??> |
| | | ${propertiesInfo} |
| | | </#if> |
| | | </refsect2> |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2014 ForgeRock AS. |
| | | */ |
| | | |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import org.forgerock.testng.ForgeRockTestCase; |
| | | import org.testng.annotations.Test; |
| | | |
| | | /** |
| | | * An abstract class that all CLI unit tests should extend. |
| | | */ |
| | | @Test(groups = { "precommit", "cli", "sdk" }) |
| | | public abstract class CliTestCase extends ForgeRockTestCase { |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.io.ByteArrayOutputStream; |
| | | import java.io.PrintStream; |
| | | import java.io.UnsupportedEncodingException; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.testng.annotations.Test; |
| | | |
| | | import static org.fest.assertions.Assertions.assertThat; |
| | | import static org.testng.Assert.assertFalse; |
| | | import static org.testng.Assert.assertTrue; |
| | | |
| | | /** Unit tests for the console application class. */ |
| | | @SuppressWarnings("javadoc") |
| | | public class ConsoleApplicationTestCase extends CliTestCase { |
| | | final LocalizableMessage msg = LocalizableMessage.raw("Language is the source of misunderstandings."); |
| | | final LocalizableMessage msg2 = LocalizableMessage |
| | | .raw("If somebody wants a sheep, that is a proof that one exists."); |
| | | |
| | | /** For test purposes only. */ |
| | | private static class MockConsoleApplication extends ConsoleApplication { |
| | | private static ByteArrayOutputStream out; |
| | | private static ByteArrayOutputStream err; |
| | | private boolean verbose; |
| | | private boolean interactive; |
| | | private boolean quiet; |
| | | |
| | | private MockConsoleApplication(PrintStream out, PrintStream err) { |
| | | super(out, err); |
| | | } |
| | | |
| | | static MockConsoleApplication getDefault() { |
| | | out = new ByteArrayOutputStream(); |
| | | final PrintStream psOut = new PrintStream(out); |
| | | err = new ByteArrayOutputStream(); |
| | | final PrintStream psErr = new PrintStream(err); |
| | | return new MockConsoleApplication(psOut, psErr); |
| | | } |
| | | |
| | | public String getOut() throws UnsupportedEncodingException { |
| | | return out.toString("UTF-8"); |
| | | } |
| | | |
| | | public String getErr() throws UnsupportedEncodingException { |
| | | return err.toString("UTF-8"); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isVerbose() { |
| | | return verbose; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isInteractive() { |
| | | return interactive; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isQuiet() { |
| | | return quiet; |
| | | } |
| | | |
| | | public void setVerbose(boolean v) { |
| | | verbose = v; |
| | | } |
| | | |
| | | public void setInteractive(boolean inter) { |
| | | interactive = inter; |
| | | } |
| | | |
| | | public void setQuiet(boolean q) { |
| | | quiet = q; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isMenuDrivenMode() { |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | @Test |
| | | public void testWriteLineInOutputStream() throws UnsupportedEncodingException { |
| | | final MockConsoleApplication ca = MockConsoleApplication.getDefault(); |
| | | ca.print(msg); |
| | | assertThat(ca.getOut()).contains(msg.toString()); |
| | | assertThat(ca.getErr()).isEmpty(); |
| | | } |
| | | |
| | | @Test |
| | | public void testWriteLineInErrorStream() throws UnsupportedEncodingException { |
| | | final MockConsoleApplication ca = MockConsoleApplication.getDefault(); |
| | | ca.errPrintln(msg); |
| | | assertThat(ca.getOut()).isEmpty(); |
| | | assertThat(ca.getErr()).contains(msg.toString()); |
| | | } |
| | | |
| | | @Test |
| | | public void testWriteOutputStreamVerbose() throws UnsupportedEncodingException { |
| | | final MockConsoleApplication ca = MockConsoleApplication.getDefault(); |
| | | ca.printVerboseMessage(msg); |
| | | assertThat(ca.isVerbose()).isFalse(); |
| | | assertThat(ca.getOut()).isEmpty(); |
| | | assertThat(ca.getErr()).isEmpty(); |
| | | ca.setVerbose(true); |
| | | ca.printVerboseMessage(msg); |
| | | assertThat(ca.isVerbose()).isTrue(); |
| | | assertThat(ca.getOut()).contains(msg.toString()); |
| | | assertThat(ca.getErr()).isEmpty(); |
| | | } |
| | | |
| | | @Test |
| | | public void testWriteErrorStreamVerbose() throws UnsupportedEncodingException { |
| | | final MockConsoleApplication ca = MockConsoleApplication.getDefault(); |
| | | ca.errPrintVerboseMessage(msg); |
| | | assertThat(ca.isVerbose()).isFalse(); |
| | | assertThat(ca.getOut()).isEmpty(); |
| | | assertThat(ca.getErr()).isEmpty(); |
| | | ca.setVerbose(true); |
| | | ca.errPrintVerboseMessage(msg); |
| | | assertThat(ca.isVerbose()).isTrue(); |
| | | assertThat(ca.getOut()).isEmpty(); |
| | | assertThat(ca.getErr()).contains(msg.toString()); |
| | | } |
| | | |
| | | /** |
| | | * In non interactive applications, standard messages should be displayed in the stdout(info) and errors to the |
| | | * stderr (warnings, errors). |
| | | * |
| | | * @throws UnsupportedEncodingException |
| | | */ |
| | | @Test |
| | | public void testNonInteractiveApplicationShouldNotStdoutErrors() throws UnsupportedEncodingException { |
| | | final MockConsoleApplication ca = MockConsoleApplication.getDefault(); |
| | | |
| | | assertFalse(ca.isInteractive()); |
| | | ca.errPrintln(msg); |
| | | assertThat(ca.getOut()).isEmpty(); |
| | | assertThat(ca.getErr()).contains(msg.toString()); |
| | | ca.println(msg2); |
| | | assertThat(ca.getOut()).contains(msg2.toString()); |
| | | assertThat(ca.getErr()).doesNotContain(msg2.toString()); |
| | | } |
| | | |
| | | /** |
| | | * If an application is interactive, all messages should be redirect to the stdout. (info, warnings, errors). |
| | | * |
| | | * @throws UnsupportedEncodingException |
| | | */ |
| | | @Test |
| | | public void testInteractiveApplicationShouldStdoutErrors() throws UnsupportedEncodingException { |
| | | final MockConsoleApplication ca = MockConsoleApplication.getDefault(); |
| | | |
| | | assertFalse(ca.isInteractive()); |
| | | ca.setInteractive(true); |
| | | assertTrue(ca.isInteractive()); |
| | | ca.errPrintln(msg); |
| | | assertThat(ca.getOut()).contains(msg.toString()); |
| | | assertThat(ca.getErr()).isEmpty(); |
| | | ca.println(msg2); |
| | | assertThat(ca.getOut()).contains(msg2.toString()); |
| | | assertThat(ca.getErr()).isEmpty(); |
| | | } |
| | | |
| | | /** |
| | | * In quiet mode, only the stderr should contain lines. |
| | | * @throws UnsupportedEncodingException |
| | | */ |
| | | @Test |
| | | public void testQuietMode() throws UnsupportedEncodingException { |
| | | final MockConsoleApplication ca = MockConsoleApplication.getDefault(); |
| | | ca.setQuiet(true); |
| | | assertTrue(ca.isQuiet()); |
| | | ca.println(msg); |
| | | ca.errPrintln(msg2); |
| | | assertThat(ca.getOut()).isEmpty(); |
| | | assertThat(ca.getErr()).contains(msg2.toString()); |
| | | assertThat(ca.getErr()).doesNotContain(msg.toString()); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | import org.fest.assertions.Assertions; |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.testng.Assert; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | | /** |
| | | * Unit tests for the SubCommand class. |
| | | */ |
| | | @SuppressWarnings("javadoc") |
| | | public final class TestSubCommandArgumentParserTestCase extends CliTestCase { |
| | | |
| | | private SubCommandArgumentParser parser; |
| | | |
| | | /** First sub-command. */ |
| | | private SubCommand sc1; |
| | | /** Second sub-command. */ |
| | | private SubCommand sc2; |
| | | |
| | | /** |
| | | * Create the sub-commands and parser. |
| | | * |
| | | * @throws Exception |
| | | * If something unexpected happened. |
| | | */ |
| | | @BeforeClass |
| | | public void setup() throws Exception { |
| | | parser = new SubCommandArgumentParser(getClass().getName(), LocalizableMessage.raw("test description"), true); |
| | | |
| | | sc1 = new SubCommand(parser, "sub-command1", LocalizableMessage.raw("sub-command1")); |
| | | sc2 = new SubCommand(parser, "sub-command2", true, 2, 4, "args1 arg2 [arg3 arg4]", |
| | | LocalizableMessage.raw("sub-command2")); |
| | | } |
| | | |
| | | /** |
| | | * Test the getSubCommand method. |
| | | * |
| | | * @throws Exception |
| | | * If something unexpected happened. |
| | | */ |
| | | @Test |
| | | public void testGetSubCommand() throws Exception { |
| | | Assert.assertSame(parser.getSubCommand("sub-command1"), sc1); |
| | | Assert.assertSame(parser.getSubCommand("sub-command2"), sc2); |
| | | Assert.assertNull(parser.getSubCommand("sub-command3")); |
| | | } |
| | | |
| | | /** |
| | | * Provide valid command line args. |
| | | * |
| | | * @return Array of valid command line args. |
| | | */ |
| | | @DataProvider(name = "validCommandLineArgs") |
| | | public Object[][] createValidCommandLineArgs() { |
| | | return new Object[][] { |
| | | { new String[] {}, null }, |
| | | { new String[] { "sub-command1" }, sc1 }, |
| | | { new String[] { "sub-command2", "one", "two" }, sc2 }, |
| | | { new String[] { "sub-command2", "one", "two", "three" }, sc2 }, |
| | | { new String[] { "sub-command2", "one", "two", "three", "four" }, sc2 }, }; |
| | | } |
| | | |
| | | /** |
| | | * Test the parseArguments method with valid args. |
| | | * |
| | | * @param args |
| | | * The command line args. |
| | | * @param sc |
| | | * The expected sub-command. |
| | | * @throws Exception |
| | | * If something unexpected happened. |
| | | */ |
| | | @Test(dataProvider = "validCommandLineArgs") |
| | | public void testParseArgumentsWithValidArgs(String[] args, SubCommand sc) throws Exception { |
| | | parser.parseArguments(args); |
| | | |
| | | // Check the correct sub-command was parsed. |
| | | Assert.assertEquals(parser.getSubCommand(), sc); |
| | | |
| | | // Check that the trailing arguments were retrieved correctly and |
| | | // in the right order. |
| | | if (args.length > 1) { |
| | | List<String> scargs = new ArrayList<>(); |
| | | for (int i = 1; i < args.length; i++) { |
| | | scargs.add(args[i]); |
| | | } |
| | | Assert.assertEquals(parser.getTrailingArguments(), scargs); |
| | | } else { |
| | | Assert.assertTrue(parser.getTrailingArguments().isEmpty()); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Provide invalid command line args. |
| | | * |
| | | * @return Array of invalid command line args. |
| | | */ |
| | | @DataProvider(name = "invalidCommandLineArgs") |
| | | public Object[][] createInvalidCommandLineArgs() { |
| | | return new Object[][] { |
| | | { new String[] { "sub-command1", "one" } }, |
| | | { new String[] { "sub-command1", "one", "two" } }, |
| | | { new String[] { "sub-command2" } }, |
| | | { new String[] { "sub-command2", "one" } }, |
| | | { new String[] { "sub-command2", "one", "two", "three", "four", "five" } }, }; |
| | | } |
| | | |
| | | /** |
| | | * Test the parseArguments method with invalid args. |
| | | * |
| | | * @param args |
| | | * The command line args. |
| | | * @throws Exception |
| | | * If something unexpected happened. |
| | | */ |
| | | @Test(dataProvider = "invalidCommandLineArgs", expectedExceptions = ArgumentException.class) |
| | | public void testParseArgumentsWithInvalidArgs(String[] args) throws Exception { |
| | | parser.parseArguments(args); |
| | | } |
| | | |
| | | @DataProvider |
| | | public Object[][] indentAndWrapProvider() throws Exception { |
| | | final String eol = System.getProperty("line.separator"); |
| | | return new Object[][] { |
| | | { "test1", 5, " ", " test1" + eol }, |
| | | { "test1 test2", 5, " ", " test1" + eol + " test2" + eol }, |
| | | { "test1 test2test3", 5, " ", " test1" + eol + " test2test3" + eol }, |
| | | { "test1 test2test3 test4", 5, " ", " test1" + eol + " test2test3" + eol + " test4" + eol }, |
| | | }; |
| | | } |
| | | |
| | | @Test(dataProvider = "indentAndWrapProvider") |
| | | public void testIndentAndWrap(String text, int wrapColumn, String indent, String expected) { |
| | | final StringBuilder buffer = new StringBuilder(); |
| | | SubCommandArgumentParser.indentAndWrap(indent, buffer, wrapColumn, LocalizableMessage.raw(text)); |
| | | Assertions.assertThat(buffer.toString()).isEqualTo(expected); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.util.Arrays; |
| | | |
| | | import org.testng.Assert; |
| | | import org.testng.annotations.Test; |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | |
| | | |
| | | /** |
| | | * Unit tests for the SubCommand class. |
| | | */ |
| | | public final class TestSubCommandTestCase extends CliTestCase { |
| | | |
| | | /** |
| | | * Tests that allowsTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testAllowsTrailingArgumentsFalse1() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command1", LocalizableMessage.raw("XXX")); |
| | | Assert.assertFalse(sc.allowsTrailingArguments()); |
| | | } |
| | | |
| | | /** |
| | | * Tests that allowsTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testAllowsTrailingArgumentsFalse2() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command2", false, 0, 0, null, LocalizableMessage.raw("XXX")); |
| | | Assert.assertFalse(sc.allowsTrailingArguments()); |
| | | } |
| | | |
| | | /** |
| | | * Tests that allowsTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testAllowsTrailingArgumentsTrue() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command2", true, 2, 4, "args1 arg2 [arg3 arg4]", |
| | | LocalizableMessage.raw("XXX")); |
| | | Assert.assertTrue(sc.allowsTrailingArguments()); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getMaxTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetMaxTrailingArguments1() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command1", LocalizableMessage.raw("XXX")); |
| | | Assert.assertEquals(sc.getMaxTrailingArguments(), 0); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getMaxTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetMaxTrailingArguments2() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command2", false, 0, 0, null, LocalizableMessage.raw("XXX")); |
| | | Assert.assertEquals(sc.getMaxTrailingArguments(), 0); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getMaxTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetMaxTrailingArguments3() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command2", true, 2, 4, "args1 arg2 [arg3 arg4]", |
| | | LocalizableMessage.raw("XXX")); |
| | | Assert.assertEquals(sc.getMaxTrailingArguments(), 4); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getMinTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetMinTrailingArguments1() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command1", LocalizableMessage.raw("XXX")); |
| | | Assert.assertEquals(sc.getMinTrailingArguments(), 0); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getMinTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetMinTrailingArguments2() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command2", false, 0, 0, null, LocalizableMessage.raw("XXX")); |
| | | Assert.assertEquals(sc.getMinTrailingArguments(), 0); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getMinTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetMinTrailingArguments3() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command2", true, 2, 4, "args1 arg2 [arg3 arg4]", |
| | | LocalizableMessage.raw("XXX")); |
| | | Assert.assertEquals(sc.getMinTrailingArguments(), 2); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getTrailingArgumentsDisplayName works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetTrailingArgumentsDisplayName1() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command1", LocalizableMessage.raw("XXX")); |
| | | Assert.assertNull(sc.getTrailingArgumentsDisplayName()); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getTrailingArgumentsDisplayName works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetTrailingArgumentsDisplayName2() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command2", false, 0, 0, null, LocalizableMessage.raw("XXX")); |
| | | Assert.assertNull(sc.getTrailingArgumentsDisplayName()); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getTrailingArgumentsDisplayName works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetTrailingArgumentsDisplayName3() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command2", true, 2, 4, "args1 arg2 [arg3 arg4]", |
| | | LocalizableMessage.raw("XXX")); |
| | | Assert.assertEquals(sc.getTrailingArgumentsDisplayName(), "args1 arg2 [arg3 arg4]"); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetTrailingArguments1() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command1", LocalizableMessage.raw("XXX")); |
| | | parser.parseArguments(new String[] { "sub-command1" }); |
| | | Assert.assertTrue(sc.getTrailingArguments().isEmpty()); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetTrailingArguments2() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command2", false, 0, 0, null, LocalizableMessage.raw("XXX")); |
| | | parser.parseArguments(new String[] { "sub-command2" }); |
| | | Assert.assertTrue(sc.getTrailingArguments().isEmpty()); |
| | | } |
| | | |
| | | /** |
| | | * Tests that getTrailingArguments works correctly. |
| | | * |
| | | * @throws Exception |
| | | * If an unexpected problem occurred. |
| | | */ |
| | | @Test |
| | | public void testGetTrailingArguments3() throws Exception { |
| | | SubCommandArgumentParser parser = new SubCommandArgumentParser(getClass().getName(), |
| | | LocalizableMessage.raw("test description"), true); |
| | | SubCommand sc = new SubCommand(parser, "sub-command2", true, 2, 4, "args1 arg2 [arg3 arg4]", |
| | | LocalizableMessage.raw("XXX")); |
| | | parser.parseArguments(new String[] { "sub-command2", "arg1", "arg2", "arg3" }); |
| | | Assert.assertEquals(sc.getTrailingArguments(), Arrays.asList(new String[] { "arg1", "arg2", "arg3" })); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2014-2015 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.cli; |
| | | |
| | | import java.io.File; |
| | | import java.io.IOException; |
| | | |
| | | import org.testng.annotations.Test; |
| | | import static org.testng.Assert.assertFalse; |
| | | import static org.testng.Assert.assertTrue; |
| | | import static org.testng.Assert.assertEquals; |
| | | |
| | | @SuppressWarnings("javadoc") |
| | | public class UtilsTestCase extends CliTestCase { |
| | | |
| | | @Test(expectedExceptions = ClientException.class) |
| | | public void testInvalidJavaVersion() throws ClientException { |
| | | final String original = System.getProperty("java.specification.version"); |
| | | System.setProperty("java.specification.version", "1.6"); |
| | | try { |
| | | Utils.checkJavaVersion(); |
| | | } finally { |
| | | System.setProperty("java.specification.version", original); |
| | | } |
| | | } |
| | | |
| | | @Test |
| | | public void testValidJavaVersion() throws ClientException { |
| | | Utils.checkJavaVersion(); |
| | | } |
| | | |
| | | @Test |
| | | public void testCanWriteOnNewFile() throws ClientException, IOException { |
| | | final File f = File.createTempFile("tempFile", ".txt"); |
| | | f.deleteOnExit(); |
| | | assertTrue(f.exists()); |
| | | assertTrue(Utils.canWrite(f.getPath())); |
| | | } |
| | | |
| | | @Test |
| | | public void testCannotWriteOnNewFile() throws ClientException, IOException { |
| | | final File f = File.createTempFile("tempFile", ".txt"); |
| | | f.setReadOnly(); |
| | | f.deleteOnExit(); |
| | | assertTrue(f.exists()); |
| | | assertFalse(Utils.canWrite(f.getPath())); |
| | | } |
| | | |
| | | @Test |
| | | public void testGetHostNameForLdapUrl() { |
| | | assertEquals(Utils.getHostNameForLdapUrl("2a01:e35:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx"), |
| | | "[2a01:e35:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]"); |
| | | assertEquals(Utils.getHostNameForLdapUrl("basicUrl"), "basicUrl"); |
| | | assertEquals(Utils.getHostNameForLdapUrl(null), null); |
| | | // Left/right brackets. |
| | | assertEquals(Utils.getHostNameForLdapUrl("[2a01:e35:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx"), |
| | | "[2a01:e35:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]"); |
| | | assertEquals(Utils.getHostNameForLdapUrl("2a01:e35:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]"), |
| | | "[2a01:e35:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx]"); |
| | | } |
| | | |
| | | @Test |
| | | public void isDN() { |
| | | assertTrue(Utils.isDN("cn=Jensen,ou=people,dc=example,dc=com")); |
| | | assertTrue(Utils.isDN("cn=John Doe,dc=example,dc=org")); |
| | | assertFalse(Utils.isDN(null)); |
| | | assertFalse(Utils.isDN("babs@example.com")); |
| | | } |
| | | |
| | | |
| | | } |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!-- |
| | | The contents of this file are subject to the terms of the Common Development and |
| | | Distribution License (the License). You may not use this file except in compliance with the |
| | | License. |
| | | |
| | | You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | specific language governing permission and limitations under the License. |
| | | |
| | | When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | information: "Portions Copyright [year] [name of copyright owner]". |
| | | |
| | | Copyright 2014-2016 ForgeRock AS. |
| | | --> |
| | | <differences> |
| | | <!-- |
| | | For specifying ignored differences, see: |
| | | http://mojo.codehaus.org/clirr-maven-plugin/examples/ignored-differences.html |
| | | |
| | | path/methods/to/from matching can either use: |
| | | - regex when surrounded with '%regex[]' |
| | | - ant style path matching when surrounded with '%ant[]' |
| | | - ant style path matching when not surrounded by anything |
| | | |
| | | For path/methods matching in maven-clirr-plugin see (change version numbers accordingly): |
| | | http://svn.codehaus.org/mojo/tags/clirr-maven-plugin-2.6.1/src/main/java/org/codehaus/mojo/clirr/Difference.java |
| | | http://grepcode.com/file/repo1.maven.org/maven2/org.codehaus.plexus/plexus-utils/3.0.7/org/codehaus/plexus/util/SelectorUtils.java |
| | | For a description of ant style path expressions see: |
| | | http://ant.apache.org/manual/dirtasks.html#patterns |
| | | |
| | | Note: waiting on https://jira.codehaus.org/browse/MCLIRR-62 to be resolved to avoid the need to use \s* in the '<to>' tags. |
| | | --> |
| | | </differences> |
| New file |
| | |
| | | <?xml version="1.0" encoding="UTF-8"?> |
| | | <!-- |
| | | The contents of this file are subject to the terms of the Common Development and |
| | | Distribution License (the License). You may not use this file except in compliance with the |
| | | License. |
| | | |
| | | You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | specific language governing permission and limitations under the License. |
| | | |
| | | When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | information: "Portions Copyright [year] [name of copyright owner]". |
| | | |
| | | Copyright 2011-2016 ForgeRock AS. |
| | | --> |
| | | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
| | | <modelVersion>4.0.0</modelVersion> |
| | | |
| | | <parent> |
| | | <artifactId>opendj-sdk-parent</artifactId> |
| | | <groupId>org.forgerock.opendj</groupId> |
| | | <version>4.0.0-SNAPSHOT</version> |
| | | </parent> |
| | | |
| | | <artifactId>opendj-core</artifactId> |
| | | <name>OpenDJ Core APIs</name> |
| | | <description> |
| | | This module provides the core APIs required for implementing LDAP Directory |
| | | client and server applications. Unlike the SDK this module does not |
| | | include a default network transport which must be obtained separately. |
| | | </description> |
| | | |
| | | <packaging>bundle</packaging> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.forgerock.commons</groupId> |
| | | <artifactId>i18n-core</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.slf4j</groupId> |
| | | <artifactId>slf4j-api</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.forgerock.commons</groupId> |
| | | <artifactId>forgerock-util</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.forgerock.commons</groupId> |
| | | <artifactId>i18n-slf4j</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>com.github.stephenc.jcip</groupId> |
| | | <artifactId>jcip-annotations</artifactId> |
| | | </dependency> |
| | | |
| | | <dependency> |
| | | <groupId>org.forgerock</groupId> |
| | | <artifactId>forgerock-build-tools</artifactId> |
| | | <scope>test</scope> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | |
| | | <properties> |
| | | <opendj.osgi.import.additional> |
| | | com.sun.security.auth*;resolution:=optional |
| | | </opendj.osgi.import.additional> |
| | | <maven.build.timestamp.format>yyyy-MM-dd'T'HH:mm:ss'Z'</maven.build.timestamp.format> |
| | | </properties> |
| | | |
| | | |
| | | <build> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.forgerock.commons</groupId> |
| | | <artifactId>i18n-maven-plugin</artifactId> |
| | | <executions> |
| | | <execution> |
| | | <phase>generate-sources</phase> |
| | | <goals> |
| | | <goal>generate-messages</goal> |
| | | </goals> |
| | | <configuration> |
| | | <messageFiles> |
| | | <messageFile>com/forgerock/opendj/ldap/core.properties</messageFile> |
| | | </messageFiles> |
| | | </configuration> |
| | | </execution> |
| | | </executions> |
| | | </plugin> |
| | | |
| | | <!-- Retrieve the SCM revision number and store it into the ${buildRevision} property --> |
| | | <plugin> |
| | | <groupId>org.codehaus.mojo</groupId> |
| | | <artifactId>buildnumber-maven-plugin</artifactId> |
| | | </plugin> |
| | | |
| | | <!-- Creates opendj-core bundle --> |
| | | <plugin> |
| | | <groupId>org.apache.felix</groupId> |
| | | <artifactId>maven-bundle-plugin</artifactId> |
| | | <configuration> |
| | | <instructions> |
| | | <Export-Package> |
| | | com.forgerock.opendj.util, |
| | | org.forgerock.opendj.io, |
| | | org.forgerock.opendj.ldap*, |
| | | org.forgerock.opendj.ldif |
| | | </Export-Package> |
| | | <Build-Maven>Apache Maven ${maven.version}</Build-Maven> |
| | | <SCM-Revision>${buildRevision}</SCM-Revision> |
| | | <SCM-Branch>${scmBranch}</SCM-Branch> |
| | | <Build-Time>${maven.build.timestamp}</Build-Time> |
| | | <Build-Java>${java.version}</Build-Java> |
| | | </instructions> |
| | | </configuration> |
| | | </plugin> |
| | | |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-surefire-plugin</artifactId> |
| | | </plugin> |
| | | |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-source-plugin</artifactId> |
| | | </plugin> |
| | | |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-jar-plugin</artifactId> |
| | | <executions> |
| | | <execution> |
| | | <goals> |
| | | <goal>test-jar</goal> |
| | | </goals> |
| | | </execution> |
| | | </executions> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | |
| | | |
| | | <profiles> |
| | | <profile> |
| | | <!-- This profile provides API/ABI compatiblity checks and reports via Clirr --> |
| | | <id>clirr</id> |
| | | <activation> |
| | | <file> |
| | | <exists>clirr-ignored-api-changes.xml</exists> |
| | | <!-- this file name is duplicated due to MNG-4471 --> |
| | | </file> |
| | | </activation> |
| | | |
| | | <build> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.codehaus.mojo</groupId> |
| | | <artifactId>clirr-maven-plugin</artifactId> |
| | | <version>${clirrPluginVersion}</version> |
| | | <inherited>true</inherited> |
| | | <configuration> |
| | | <comparisonArtifacts> |
| | | <comparisonArtifact> |
| | | <groupId>${project.groupId}</groupId> |
| | | <artifactId>opendj-ldap-sdk</artifactId> |
| | | <!-- former name of this jar --> |
| | | <version>3.0.0-SNAPSHOT</version> |
| | | </comparisonArtifact> |
| | | </comparisonArtifacts> |
| | | <excludes> |
| | | <exclude>com/**</exclude> |
| | | </excludes> |
| | | <ignoredDifferencesFile>clirr-ignored-api-changes.xml</ignoredDifferencesFile> |
| | | </configuration> |
| | | |
| | | <executions> |
| | | <execution> |
| | | <id>mvn clirr:check</id> |
| | | </execution> |
| | | |
| | | <execution> |
| | | <id>mvn verify</id> |
| | | <goals> |
| | | <goal>check</goal> |
| | | </goals> |
| | | </execution> |
| | | </executions> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | |
| | | <reporting> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.codehaus.mojo</groupId> |
| | | <artifactId>clirr-maven-plugin</artifactId> |
| | | <version>${clirrPluginVersion}</version> |
| | | <inherited>true</inherited> |
| | | <configuration> |
| | | <comparisonArtifacts> |
| | | <comparisonArtifact> |
| | | <groupId>${project.groupId}</groupId> |
| | | <artifactId>opendj-ldap-sdk</artifactId> |
| | | <!-- former name of this jar --> |
| | | <version>2.6.0</version> |
| | | </comparisonArtifact> |
| | | </comparisonArtifacts> |
| | | <excludes> |
| | | <exclude>com/**</exclude> |
| | | </excludes> |
| | | <ignoredDifferencesFile>clirr-ignored-api-changes.xml</ignoredDifferencesFile> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | </reporting> |
| | | </profile> |
| | | |
| | | <!-- |
| | | Generates consolidated Javadoc covering both LDAP SDK packages |
| | | and also dependency (and transitive dependency) ForgeRock packages. |
| | | --> |
| | | <profile> |
| | | <id>forgerock-release</id> |
| | | |
| | | <properties> |
| | | <javadocTitle>OpenDJ LDAP SDK ${project.version} API</javadocTitle> |
| | | <timestamp>${maven.build.timestamp}</timestamp> |
| | | <maven.build.timestamp.format>yyyy</maven.build.timestamp.format> |
| | | </properties> |
| | | |
| | | <build> |
| | | <plugins> |
| | | <plugin> |
| | | <artifactId>maven-javadoc-plugin</artifactId> |
| | | <executions> |
| | | <execution> |
| | | <id>javadoc-jar</id> |
| | | <phase>package</phase> |
| | | <goals> |
| | | <goal>jar</goal> |
| | | </goals> |
| | | </execution> |
| | | </executions> |
| | | <configuration> |
| | | <includeDependencySources>true</includeDependencySources> |
| | | <includeTransitiveDependencySources>true</includeTransitiveDependencySources> |
| | | <dependencySourceIncludes> |
| | | <dependencySourceInclude>org.forgerock.*:*</dependencySourceInclude> |
| | | </dependencySourceIncludes> |
| | | <excludePackageNames>com.*:*.internal</excludePackageNames> |
| | | <groups> |
| | | <group> |
| | | <title>${project.name} Packages</title> |
| | | <packages>${project.groupId}*</packages> |
| | | </group> |
| | | |
| | | <group> |
| | | <title>ForgeRock Common Packages</title> |
| | | <packages>*</packages> |
| | | </group> |
| | | </groups> |
| | | <author>false</author> |
| | | <doctitle>${javadocTitle}</doctitle> |
| | | <windowtitle>${javadocTitle}</windowtitle> |
| | | <header>${javadocTitle}</header> |
| | | <footer>${javadocTitle}</footer> |
| | | <bottom>Copyright 2011-${maven.build.timestamp} ForgeRock AS.</bottom> |
| | | <links> |
| | | <link>http://docs.oracle.com/javase/7/docs/api/</link> |
| | | <link>http://www.slf4j.org/apidocs/</link> |
| | | </links> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | </build> |
| | | </profile> |
| | | </profiles> |
| | | |
| | | |
| | | <reporting> |
| | | <plugins> |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-project-info-reports-plugin</artifactId> |
| | | <reportSets> |
| | | <reportSet> |
| | | <reports> |
| | | <report>dependencies</report> |
| | | </reports> |
| | | </reportSet> |
| | | </reportSets> |
| | | </plugin> |
| | | |
| | | <plugin> |
| | | <groupId>org.apache.maven.plugins</groupId> |
| | | <artifactId>maven-javadoc-plugin</artifactId> |
| | | <configuration> |
| | | <links> |
| | | <link>http://commons.forgerock.org/i18n-framework/i18n-core/apidocs</link> |
| | | </links> |
| | | </configuration> |
| | | </plugin> |
| | | </plugins> |
| | | </reporting> |
| | | </project> |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.ldap.controls; |
| | | |
| | | import static com.forgerock.opendj.ldap.CoreMessages.ERR_ACCTUSABLEREQ_CONTROL_BAD_OID; |
| | | import static com.forgerock.opendj.ldap.CoreMessages.ERR_ACCTUSABLEREQ_CONTROL_HAS_VALUE; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.DecodeOptions; |
| | | import org.forgerock.opendj.ldap.controls.Control; |
| | | import org.forgerock.opendj.ldap.controls.ControlDecoder; |
| | | |
| | | import org.forgerock.util.Reject; |
| | | |
| | | /** |
| | | * 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>() { |
| | | |
| | | @Override |
| | | public AccountUsabilityRequestControl decodeControl(final Control control, |
| | | final DecodeOptions options) throws DecodeException { |
| | | Reject.ifNull(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; |
| | | } |
| | | |
| | | @Override |
| | | 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; |
| | | } |
| | | |
| | | @Override |
| | | public String getOID() { |
| | | return OID; |
| | | } |
| | | |
| | | @Override |
| | | public ByteString getValue() { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasValue() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isCritical() { |
| | | return isCritical; |
| | | } |
| | | |
| | | @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 |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2011-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.ldap.controls; |
| | | |
| | | import static com.forgerock.opendj.util.StaticUtils.byteToHex; |
| | | import static com.forgerock.opendj.util.StaticUtils.getExceptionMessage; |
| | | import static com.forgerock.opendj.ldap.CoreMessages.*; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.io.ASN1; |
| | | import org.forgerock.opendj.io.ASN1Reader; |
| | | import org.forgerock.opendj.io.ASN1Writer; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ByteStringBuilder; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.DecodeOptions; |
| | | import org.forgerock.opendj.ldap.controls.Control; |
| | | import org.forgerock.opendj.ldap.controls.ControlDecoder; |
| | | |
| | | import org.forgerock.util.Reject; |
| | | |
| | | /** |
| | | * 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 { |
| | | |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | /** 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>() { |
| | | |
| | | @Override |
| | | public AccountUsabilityResponseControl decodeControl(final Control control, |
| | | final DecodeOptions options) throws DecodeException { |
| | | Reject.ifNull(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) { |
| | | logger.debug(LocalizableMessage.raw("%s", e)); |
| | | |
| | | final LocalizableMessage message = |
| | | ERR_ACCTUSABLERES_DECODE_ERROR.get(getExceptionMessage(e)); |
| | | throw DecodeException.error(message); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | 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; |
| | | } |
| | | |
| | | @Override |
| | | 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; |
| | | } |
| | | |
| | | @Override |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasValue() { |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | 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; |
| | | } |
| | | |
| | | @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 |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.ldap.controls; |
| | | |
| | | import static com.forgerock.opendj.ldap.CoreMessages.ERR_REAL_ATTRS_ONLY_CONTROL_BAD_OID; |
| | | import static com.forgerock.opendj.ldap.CoreMessages.ERR_REAL_ATTRS_ONLY_INVALID_CONTROL_VALUE; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.DecodeOptions; |
| | | import org.forgerock.opendj.ldap.controls.Control; |
| | | import org.forgerock.opendj.ldap.controls.ControlDecoder; |
| | | |
| | | import org.forgerock.util.Reject; |
| | | |
| | | /** |
| | | * 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>() { |
| | | |
| | | @Override |
| | | public RealAttributesOnlyRequestControl decodeControl(final Control control, |
| | | final DecodeOptions options) throws DecodeException { |
| | | Reject.ifNull(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; |
| | | } |
| | | |
| | | @Override |
| | | 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; |
| | | } |
| | | |
| | | @Override |
| | | public String getOID() { |
| | | return OID; |
| | | } |
| | | |
| | | @Override |
| | | public ByteString getValue() { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasValue() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isCritical() { |
| | | return isCritical; |
| | | } |
| | | |
| | | @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 |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2015 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.ldap.controls; |
| | | |
| | | import static com.forgerock.opendj.ldap.CoreMessages.*; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.DecodeOptions; |
| | | import org.forgerock.opendj.ldap.controls.Control; |
| | | import org.forgerock.opendj.ldap.controls.ControlDecoder; |
| | | import org.forgerock.util.Reject; |
| | | |
| | | /** |
| | | * Control to provide a transaction ID. |
| | | * <p> |
| | | * The transaction ID is related to Common Audit : it is used for tracking the processing of a user-interaction as it |
| | | * passes through the Forgerock stack |
| | | * <p> |
| | | * The control's value is the UTF-8 encoding of the transaction ID. |
| | | */ |
| | | public final class TransactionIdControl implements Control { |
| | | |
| | | /** OID for this control. */ |
| | | public static final String OID = "1.3.6.1.4.1.36733.2.1.5.1"; |
| | | |
| | | /** A decoder which can be used for decoding the simple paged results control. */ |
| | | public static final ControlDecoder<TransactionIdControl> DECODER = new ControlDecoder<TransactionIdControl>() { |
| | | |
| | | @Override |
| | | public TransactionIdControl decodeControl(final Control control, final DecodeOptions options) |
| | | throws DecodeException { |
| | | Reject.ifNull(control); |
| | | |
| | | if (control instanceof TransactionIdControl) { |
| | | return (TransactionIdControl) control; |
| | | } |
| | | |
| | | if (!control.getOID().equals(OID)) { |
| | | throw DecodeException.error(ERR_TRANSACTION_ID_CONTROL_BAD_OID.get(control.getOID(), OID)); |
| | | } |
| | | |
| | | if (!control.hasValue()) { |
| | | // The control must always have a value. |
| | | throw DecodeException.error(ERR_TRANSACTION_ID_CONTROL_DECODE_NULL.get()); |
| | | } |
| | | |
| | | return new TransactionIdControl(control.getValue().toString()); |
| | | } |
| | | |
| | | @Override |
| | | public String getOID() { |
| | | return OID; |
| | | } |
| | | }; |
| | | |
| | | /** |
| | | * Creates a new transactionId control. |
| | | * |
| | | * @param transactionId |
| | | * The transaction id to provide through this control. |
| | | * @return The new control. |
| | | * @throws NullPointerException |
| | | * If {@code transactionId} was {@code null}. |
| | | */ |
| | | public static TransactionIdControl newControl(final String transactionId) { |
| | | Reject.ifNull(transactionId); |
| | | return new TransactionIdControl(transactionId); |
| | | } |
| | | |
| | | /** The control value transactionId element. */ |
| | | private final String transactionId; |
| | | |
| | | private TransactionIdControl(final String transactionId) { |
| | | this.transactionId = transactionId; |
| | | } |
| | | |
| | | /** |
| | | * Returns the transaction id. |
| | | * |
| | | * @return The transaction id. |
| | | */ |
| | | public String getTransactionId() { |
| | | return transactionId; |
| | | } |
| | | |
| | | @Override |
| | | public String getOID() { |
| | | return OID; |
| | | } |
| | | |
| | | @Override |
| | | public ByteString getValue() { |
| | | return ByteString.valueOfUtf8(transactionId); |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasValue() { |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isCritical() { |
| | | // This control is never critical. |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | final StringBuilder builder = new StringBuilder(); |
| | | builder.append("TransactionIdControl(oid="); |
| | | builder.append(getOID()); |
| | | builder.append(", transactionId="); |
| | | builder.append(transactionId); |
| | | builder.append(")"); |
| | | return builder.toString(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.ldap.controls; |
| | | |
| | | import static com.forgerock.opendj.ldap.CoreMessages.ERR_VIRTUAL_ATTRS_ONLY_CONTROL_BAD_OID; |
| | | import static com.forgerock.opendj.ldap.CoreMessages.ERR_VIRTUAL_ATTRS_ONLY_INVALID_CONTROL_VALUE; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.DecodeOptions; |
| | | import org.forgerock.opendj.ldap.controls.Control; |
| | | import org.forgerock.opendj.ldap.controls.ControlDecoder; |
| | | |
| | | import org.forgerock.util.Reject; |
| | | |
| | | /** |
| | | * 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>() { |
| | | |
| | | @Override |
| | | public VirtualAttributesOnlyRequestControl decodeControl(final Control control, |
| | | final DecodeOptions options) throws DecodeException { |
| | | Reject.ifNull(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; |
| | | } |
| | | |
| | | @Override |
| | | 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; |
| | | } |
| | | |
| | | @Override |
| | | public String getOID() { |
| | | return OID; |
| | | } |
| | | |
| | | @Override |
| | | public ByteString getValue() { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasValue() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public boolean isCritical() { |
| | | return isCritical; |
| | | } |
| | | |
| | | @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(); |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | /** |
| | | * Classes implementing Sun proprietary LDAP controls. |
| | | */ |
| | | package com.forgerock.opendj.ldap.controls; |
| | | |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.ldap.extensions; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.opendj.io.ASN1; |
| | | import org.forgerock.opendj.io.ASN1Reader; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.DecodeOptions; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.controls.Control; |
| | | import org.forgerock.opendj.ldap.requests.AbstractExtendedRequest; |
| | | import org.forgerock.opendj.ldap.requests.ExtendedRequest; |
| | | import org.forgerock.opendj.ldap.requests.ExtendedRequestDecoder; |
| | | import org.forgerock.opendj.ldap.responses.AbstractExtendedResultDecoder; |
| | | import org.forgerock.opendj.ldap.responses.ExtendedResult; |
| | | import org.forgerock.opendj.ldap.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> { |
| | | |
| | | @Override |
| | | 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 extends |
| | | AbstractExtendedResultDecoder<GetConnectionIDExtendedResult> { |
| | | @Override |
| | | public GetConnectionIDExtendedResult newExtendedErrorResult(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).setMatchedDN(matchedDN) |
| | | .setDiagnosticMessage(diagnosticMessage); |
| | | } |
| | | |
| | | @Override |
| | | public GetConnectionIDExtendedResult decodeExtendedResult(final ExtendedResult result, |
| | | final DecodeOptions options) throws DecodeException { |
| | | if (result instanceof GetConnectionIDExtendedResult) { |
| | | return (GetConnectionIDExtendedResult) result; |
| | | } |
| | | |
| | | final ResultCode resultCode = result.getResultCode(); |
| | | final GetConnectionIDExtendedResult newResult = |
| | | GetConnectionIDExtendedResult.newResult(resultCode) |
| | | .setMatchedDN(result.getMatchedDN()) |
| | | .setDiagnosticMessage(result.getDiagnosticMessage()); |
| | | |
| | | final ByteString responseValue = result.getValue(); |
| | | if (!resultCode.isExceptional() && responseValue == null) { |
| | | throw DecodeException.error(LocalizableMessage.raw("Empty response value")); |
| | | } |
| | | if (responseValue != null) { |
| | | try { |
| | | final ASN1Reader reader = ASN1.getReader(responseValue); |
| | | newResult.setConnectionID((int) reader.readInteger()); |
| | | } catch (final IOException e) { |
| | | throw DecodeException.error(LocalizableMessage |
| | | .raw("Error decoding response value"), e); |
| | | } |
| | | } |
| | | for (final Control control : result.getControls()) { |
| | | newResult.addControl(control); |
| | | } |
| | | return newResult; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 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. |
| | | } |
| | | |
| | | @Override |
| | | public String getOID() { |
| | | return OID; |
| | | } |
| | | |
| | | @Override |
| | | public ExtendedResultDecoder<GetConnectionIDExtendedResult> getResultDecoder() { |
| | | return RESULT_DECODER; |
| | | } |
| | | |
| | | @Override |
| | | public ByteString getValue() { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasValue() { |
| | | return false; |
| | | } |
| | | |
| | | @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 |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2012-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.ldap.extensions; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | import org.forgerock.opendj.io.ASN1; |
| | | import org.forgerock.opendj.io.ASN1Writer; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ByteStringBuilder; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.responses.AbstractExtendedResult; |
| | | |
| | | import org.forgerock.util.Reject; |
| | | |
| | | /** |
| | | * Get connection ID extended result. |
| | | * |
| | | * @see GetConnectionIDExtendedRequest |
| | | */ |
| | | public final class GetConnectionIDExtendedResult extends |
| | | AbstractExtendedResult<GetConnectionIDExtendedResult> { |
| | | /** |
| | | * Creates a new get connection ID extended result with a default connection |
| | | * ID of -1. |
| | | * |
| | | * @param resultCode |
| | | * The result code. |
| | | * @return The new get connection ID extended result. |
| | | * @throws NullPointerException |
| | | * If {@code resultCode} was {@code null}. |
| | | */ |
| | | public static GetConnectionIDExtendedResult newResult(final ResultCode resultCode) { |
| | | Reject.ifNull(resultCode); |
| | | return new GetConnectionIDExtendedResult(resultCode); |
| | | } |
| | | |
| | | private int connectionID = -1; |
| | | |
| | | private GetConnectionIDExtendedResult(final ResultCode resultCode) { |
| | | super(resultCode); |
| | | } |
| | | |
| | | /** |
| | | * Returns the client connection ID. |
| | | * |
| | | * @return The client connection ID. |
| | | */ |
| | | public int getConnectionID() { |
| | | return connectionID; |
| | | } |
| | | |
| | | @Override |
| | | public String getOID() { |
| | | return GetConnectionIDExtendedRequest.OID; |
| | | } |
| | | |
| | | @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(); |
| | | } |
| | | |
| | | @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; |
| | | } |
| | | |
| | | @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 |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2013-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.ldap.extensions; |
| | | |
| | | import static com.forgerock.opendj.ldap.CoreMessages.*; |
| | | |
| | | import java.io.IOException; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.i18n.slf4j.LocalizedLogger; |
| | | import org.forgerock.opendj.io.ASN1; |
| | | import org.forgerock.opendj.io.ASN1Reader; |
| | | import org.forgerock.opendj.io.ASN1Writer; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ByteStringBuilder; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.DecodeOptions; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.controls.Control; |
| | | import org.forgerock.opendj.ldap.requests.AbstractExtendedRequest; |
| | | import org.forgerock.opendj.ldap.requests.ExtendedRequest; |
| | | import org.forgerock.opendj.ldap.requests.ExtendedRequestDecoder; |
| | | import org.forgerock.opendj.ldap.responses.AbstractExtendedResultDecoder; |
| | | import org.forgerock.opendj.ldap.responses.ExtendedResult; |
| | | import org.forgerock.opendj.ldap.responses.ExtendedResultDecoder; |
| | | import org.forgerock.opendj.ldap.responses.Responses; |
| | | |
| | | /** Get symmetric key extended request. */ |
| | | public final class GetSymmetricKeyExtendedRequest extends |
| | | AbstractExtendedRequest<GetSymmetricKeyExtendedRequest, ExtendedResult> { |
| | | private static final class RequestDecoder implements |
| | | ExtendedRequestDecoder<GetSymmetricKeyExtendedRequest, ExtendedResult> { |
| | | @Override |
| | | 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 ioe) { |
| | | logger.debug(LocalizableMessage.raw("%s", ioe)); |
| | | |
| | | final LocalizableMessage message = |
| | | ERR_GET_SYMMETRIC_KEY_ASN1_DECODE_EXCEPTION.get(ioe.getMessage()); |
| | | throw DecodeException.error(message, ioe); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private static final class ResultDecoder extends AbstractExtendedResultDecoder<ExtendedResult> { |
| | | @Override |
| | | public ExtendedResult newExtendedErrorResult(final ResultCode resultCode, |
| | | final String matchedDN, final String diagnosticMessage) { |
| | | return Responses.newGenericExtendedResult(resultCode).setMatchedDN(matchedDN) |
| | | .setDiagnosticMessage(diagnosticMessage); |
| | | } |
| | | |
| | | @Override |
| | | public ExtendedResult decodeExtendedResult(final ExtendedResult result, |
| | | final DecodeOptions options) throws DecodeException { |
| | | return result; |
| | | } |
| | | } |
| | | |
| | | private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); |
| | | |
| | | /** 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; |
| | | private String instanceKeyID; |
| | | |
| | | /** Instantiation via factory. */ |
| | | private GetSymmetricKeyExtendedRequest() { |
| | | } |
| | | |
| | | /** |
| | | * Returns the instance key ID. |
| | | * |
| | | * @return The instance key ID. |
| | | */ |
| | | public String getInstanceKeyID() { |
| | | return instanceKeyID; |
| | | } |
| | | |
| | | @Override |
| | | public String getOID() { |
| | | return OID; |
| | | } |
| | | |
| | | /** |
| | | * Returns the request symmetric key. |
| | | * |
| | | * @return The request symmetric key. |
| | | */ |
| | | public String getRequestSymmetricKey() { |
| | | return requestSymmetricKey; |
| | | } |
| | | |
| | | @Override |
| | | public ExtendedResultDecoder<ExtendedResult> getResultDecoder() { |
| | | return RESULT_DECODER; |
| | | } |
| | | |
| | | @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(); |
| | | } |
| | | |
| | | @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; |
| | | } |
| | | |
| | | @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 |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2011-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.ldap.extensions; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | import org.forgerock.i18n.LocalizableMessage; |
| | | import org.forgerock.opendj.io.ASN1; |
| | | import org.forgerock.opendj.io.ASN1Reader; |
| | | import org.forgerock.opendj.io.ASN1Writer; |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ByteStringBuilder; |
| | | import org.forgerock.opendj.ldap.DecodeException; |
| | | import org.forgerock.opendj.ldap.DecodeOptions; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.controls.Control; |
| | | import org.forgerock.opendj.ldap.requests.AbstractExtendedRequest; |
| | | import org.forgerock.opendj.ldap.requests.ExtendedRequest; |
| | | import org.forgerock.opendj.ldap.requests.ExtendedRequestDecoder; |
| | | import org.forgerock.opendj.ldap.responses.AbstractExtendedResultDecoder; |
| | | import org.forgerock.opendj.ldap.responses.ExtendedResult; |
| | | import org.forgerock.opendj.ldap.responses.ExtendedResultDecoder; |
| | | |
| | | import static com.forgerock.opendj.ldap.CoreMessages.*; |
| | | import static com.forgerock.opendj.ldap.extensions.PasswordPolicyStateOperationType.*; |
| | | import static com.forgerock.opendj.util.StaticUtils.*; |
| | | |
| | | /** |
| | | * 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; |
| | | } |
| | | |
| | | @Override |
| | | public PasswordPolicyStateOperationType getOperationType() { |
| | | return property; |
| | | } |
| | | |
| | | @Override |
| | | public Iterable<ByteString> getValues() { |
| | | return values; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return property + ": " + values; |
| | | } |
| | | } |
| | | |
| | | private static final class RequestDecoder |
| | | implements |
| | | ExtendedRequestDecoder<PasswordPolicyStateExtendedRequest, PasswordPolicyStateExtendedResult> { |
| | | @Override |
| | | 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(); |
| | | newRequest.setTargetUser(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 extends |
| | | AbstractExtendedResultDecoder<PasswordPolicyStateExtendedResult> { |
| | | @Override |
| | | public PasswordPolicyStateExtendedResult newExtendedErrorResult( |
| | | 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).setMatchedDN( |
| | | matchedDN).setDiagnosticMessage(diagnosticMessage); |
| | | } |
| | | |
| | | @Override |
| | | public PasswordPolicyStateExtendedResult decodeExtendedResult(final ExtendedResult result, |
| | | final DecodeOptions options) throws DecodeException { |
| | | final ResultCode resultCode = result.getResultCode(); |
| | | final PasswordPolicyStateExtendedResult newResult = |
| | | new PasswordPolicyStateExtendedResult(resultCode).setMatchedDN( |
| | | result.getMatchedDN()).setDiagnosticMessage( |
| | | result.getDiagnosticMessage()); |
| | | |
| | | final ByteString responseValue = result.getValue(); |
| | | if (!resultCode.isExceptional() && responseValue == null) { |
| | | throw DecodeException.error(ERR_PWPSTATE_EXTOP_NO_REQUEST_VALUE.get()); |
| | | } |
| | | if (responseValue != null) { |
| | | try { |
| | | final ASN1Reader reader = ASN1.getReader(responseValue); |
| | | reader.readStartSequence(); |
| | | newResult.setTargetUser(reader.readOctetStringAsString()); |
| | | decodeOperations(reader, newResult); |
| | | reader.readEndSequence(); |
| | | } catch (final IOException ioe) { |
| | | final LocalizableMessage message = |
| | | ERR_PWPSTATE_EXTOP_DECODE_FAILURE.get(getExceptionMessage(ioe)); |
| | | throw DecodeException.error(message, ioe); |
| | | } |
| | | } |
| | | for (final Control control : result.getControls()) { |
| | | newResult.addControl(control); |
| | | } |
| | | return newResult; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 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 String targetUser = ""; |
| | | |
| | | private final List<PasswordPolicyStateOperation> operations = new ArrayList<>(); |
| | | |
| | | 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<>(); |
| | | 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. */ |
| | | public PasswordPolicyStateExtendedRequest() { |
| | | // Nothing to do. |
| | | } |
| | | |
| | | /** |
| | | * Adds the provided authentication failure time to this request. |
| | | * |
| | | * @param date |
| | | * The authentication failure time. |
| | | */ |
| | | public void addAuthenticationFailureTime(final Date date) { |
| | | setDateProperty(ADD_AUTHENTICATION_FAILURE_TIMES, date); |
| | | } |
| | | |
| | | /** |
| | | * Adds the provided grace login use time to this request. |
| | | * |
| | | * @param date |
| | | * The grace login use time. |
| | | */ |
| | | public void addGraceLoginUseTime(final Date date) { |
| | | setDateProperty(ADD_GRACE_LOGIN_USE_TIME, date); |
| | | } |
| | | |
| | | @Override |
| | | 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); |
| | | } |
| | | |
| | | @Override |
| | | public String getOID() { |
| | | return OID; |
| | | } |
| | | |
| | | @Override |
| | | public Iterable<PasswordPolicyStateOperation> getOperations() { |
| | | return operations; |
| | | } |
| | | |
| | | @Override |
| | | public ExtendedResultDecoder<PasswordPolicyStateExtendedResult> getResultDecoder() { |
| | | return RESULT_DECODER; |
| | | } |
| | | |
| | | @Override |
| | | public String getTargetUser() { |
| | | return targetUser; |
| | | } |
| | | |
| | | @Override |
| | | public ByteString getValue() { |
| | | return encode(targetUser, operations); |
| | | } |
| | | |
| | | @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) { |
| | | setBooleanProperty(SET_ACCOUNT_DISABLED_STATE, state); |
| | | } |
| | | |
| | | /** |
| | | * Sets the account expiration time. |
| | | * |
| | | * @param date |
| | | * The account expiration time. |
| | | */ |
| | | public void setAccountExpirationTime(final Date date) { |
| | | setDateProperty(SET_ACCOUNT_EXPIRATION_TIME, date); |
| | | } |
| | | |
| | | /** |
| | | * Sets the authentication failure times. |
| | | * |
| | | * @param dates |
| | | * The authentication failure times. |
| | | */ |
| | | public void setAuthenticationFailureTimes(final Date... dates) { |
| | | setDateProperties(SET_AUTHENTICATION_FAILURE_TIMES, dates); |
| | | } |
| | | |
| | | /** |
| | | * Sets the grace login use times. |
| | | * |
| | | * @param dates |
| | | * The grace login use times. |
| | | */ |
| | | public void setGraceLoginUseTimes(final Date... dates) { |
| | | setDateProperties(SET_GRACE_LOGIN_USE_TIMES, dates); |
| | | } |
| | | |
| | | /** |
| | | * Sets the last login time. |
| | | * |
| | | * @param date |
| | | * The last login time. |
| | | */ |
| | | public void setLastLoginTime(final Date date) { |
| | | setDateProperty(SET_LAST_LOGIN_TIME, date); |
| | | } |
| | | |
| | | /** |
| | | * Sets the password changed by required time. |
| | | * |
| | | * @param state |
| | | * The password changed by required time. |
| | | */ |
| | | public void setPasswordChangedByRequiredTime(final boolean state) { |
| | | setBooleanProperty(SET_PASSWORD_CHANGED_BY_REQUIRED_TIME, state); |
| | | } |
| | | |
| | | /** |
| | | * Sets the password changed time. |
| | | * |
| | | * @param date |
| | | * The password changed time. |
| | | */ |
| | | public void setPasswordChangedTime(final Date date) { |
| | | setDateProperty(SET_PASSWORD_CHANGED_TIME, date); |
| | | } |
| | | |
| | | /** |
| | | * Sets the password expiration warned time. |
| | | * |
| | | * @param date |
| | | * The password expiration warned time. |
| | | */ |
| | | public void setPasswordExpirationWarnedTime(final Date date) { |
| | | setDateProperty(SET_PASSWORD_EXPIRATION_WARNED_TIME, date); |
| | | } |
| | | |
| | | /** |
| | | * Sets the password reset state. |
| | | * |
| | | * @param state |
| | | * The password reset state. |
| | | */ |
| | | public void setPasswordResetState(final boolean state) { |
| | | setBooleanProperty(SET_PASSWORD_RESET_STATE, state); |
| | | } |
| | | |
| | | private void setBooleanProperty(PasswordPolicyStateOperationType property, final boolean state) { |
| | | operations.add(new MultiValueOperation(property, ByteString.valueOfUtf8(String.valueOf(state)))); |
| | | } |
| | | |
| | | private void setDateProperty(PasswordPolicyStateOperationType property, final Date date) { |
| | | if (date != null) { |
| | | operations.add(new MultiValueOperation(property, toByteString(date))); |
| | | } else { |
| | | operations.add(property); |
| | | } |
| | | } |
| | | |
| | | private void setDateProperties(PasswordPolicyStateOperationType property, final Date... dates) { |
| | | if (dates == null) { |
| | | operations.add(property); |
| | | } else { |
| | | final ArrayList<ByteString> times = new ArrayList<>(dates.length); |
| | | for (final Date date : dates) { |
| | | times.add(toByteString(date)); |
| | | } |
| | | operations.add(new MultiValueOperation(property, times)); |
| | | } |
| | | } |
| | | |
| | | private ByteString toByteString(final Date date) { |
| | | return ByteString.valueOfUtf8(formatAsGeneralizedTime(date)); |
| | | } |
| | | |
| | | @Override |
| | | public void setTargetUser(String targetUser) { |
| | | this.targetUser = targetUser != null ? targetUser : ""; |
| | | } |
| | | |
| | | @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 |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2015-2016 ForgeRock AS. |
| | | */ |
| | | |
| | | package com.forgerock.opendj.ldap.extensions; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | import org.forgerock.opendj.ldap.ResultCode; |
| | | import org.forgerock.opendj.ldap.responses.AbstractExtendedResult; |
| | | |
| | | /** The password policy state extended result. */ |
| | | public final class PasswordPolicyStateExtendedResult extends |
| | | AbstractExtendedResult<PasswordPolicyStateExtendedResult> implements |
| | | PasswordPolicyStateOperationContainer { |
| | | private String targetUser = ""; |
| | | private final List<PasswordPolicyStateOperation> operations = new ArrayList<>(); |
| | | |
| | | /** |
| | | * Creates a new password policy state extended result with the provided |
| | | * result code. |
| | | * |
| | | * @param resultCode |
| | | * The result code. |
| | | */ |
| | | public PasswordPolicyStateExtendedResult(final ResultCode resultCode) { |
| | | super(resultCode); |
| | | } |
| | | |
| | | @Override |
| | | public void addOperation(final PasswordPolicyStateOperation operation) { |
| | | operations.add(operation); |
| | | } |
| | | |
| | | @Override |
| | | public String getOID() { |
| | | // No response name defined. |
| | | return PasswordPolicyStateExtendedRequest.OID; |
| | | } |
| | | |
| | | @Override |
| | | public Iterable<PasswordPolicyStateOperation> getOperations() { |
| | | return operations; |
| | | } |
| | | |
| | | @Override |
| | | public String getTargetUser() { |
| | | return targetUser; |
| | | } |
| | | |
| | | @Override |
| | | public ByteString getValue() { |
| | | return PasswordPolicyStateExtendedRequest.encode(targetUser, operations); |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasValue() { |
| | | return true; |
| | | } |
| | | |
| | | @Override |
| | | public void setTargetUser(String targetUser) { |
| | | this.targetUser = targetUser != null ? targetUser : ""; |
| | | } |
| | | |
| | | @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(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | package com.forgerock.opendj.ldap.extensions; |
| | | |
| | | import org.forgerock.opendj.ldap.ByteString; |
| | | |
| | | /** |
| | | * Password policy state operation. |
| | | */ |
| | | public interface PasswordPolicyStateOperation { |
| | | /** |
| | | * Returns the type of operation. |
| | | * |
| | | * @return The type of operation. |
| | | */ |
| | | PasswordPolicyStateOperationType getOperationType(); |
| | | |
| | | /** |
| | | * Returns the operation values. |
| | | * |
| | | * @return The operation values. |
| | | */ |
| | | Iterable<ByteString> getValues(); |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | package com.forgerock.opendj.ldap.extensions; |
| | | |
| | | /** |
| | | * Password policy state operation container. |
| | | */ |
| | | interface PasswordPolicyStateOperationContainer { |
| | | /** |
| | | * Returns the name of the user targeted by this password policy state |
| | | * operation. |
| | | * |
| | | * @return The name of the user targeted by this password policy state |
| | | * operation. |
| | | */ |
| | | String getTargetUser(); |
| | | |
| | | /** |
| | | * Sets the name of the user targeted by this password policy state |
| | | * operation. |
| | | * |
| | | * @param targetUser |
| | | * The name of the user targeted by this password policy state |
| | | * operation. |
| | | */ |
| | | void setTargetUser(String targetUser); |
| | | |
| | | /** |
| | | * 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 |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2016 ForgeRock AS. |
| | | */ |
| | | |
| | | package com.forgerock.opendj.ldap.extensions; |
| | | |
| | | import org.forgerock.opendj.ldap.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; |
| | | } |
| | | |
| | | @Override |
| | | public PasswordPolicyStateOperationType getOperationType() { |
| | | return this; |
| | | } |
| | | |
| | | @Override |
| | | public Iterable<ByteString> getValues() { |
| | | return null; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return propertyName; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2009 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | /** |
| | | * Classes implementing Sun proprietary LDAP extended operations. |
| | | */ |
| | | package com.forgerock.opendj.ldap.extensions; |
| | | |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2009 Sun Microsystems, Inc. |
| | | * Portions copyright 2011-2016 ForgeRock AS. |
| | | */ |
| | | |
| | | package com.forgerock.opendj.util; |
| | | |
| | | /** |
| | | * A {@code ASCIICharProp} provides fast access to ASCII character properties. |
| | | * In particular, the ability to query whether or not a character is a letter, a |
| | | * digit, hexadecimal character, as well as various methods for performing |
| | | * character conversions. |
| | | * <p> |
| | | * The methods in this class do not perform memory allocations nor calculations |
| | | * and so can be used safely in high performance situations. |
| | | */ |
| | | public final class ASCIICharProp implements Comparable<ASCIICharProp> { |
| | | private final char c; |
| | | |
| | | private final char upperCaseChar; |
| | | |
| | | private final char lowerCaseChar; |
| | | |
| | | private final boolean isUpperCaseChar; |
| | | |
| | | private final boolean isLowerCaseChar; |
| | | |
| | | private final boolean isDigit; |
| | | |
| | | private final boolean isLetter; |
| | | |
| | | private final boolean isKeyChar; |
| | | |
| | | private final boolean isCompatKeyChar; |
| | | |
| | | private final boolean isHexChar; |
| | | |
| | | private final int hexValue; |
| | | |
| | | private final int decimalValue; |
| | | |
| | | private final String stringValue; |
| | | |
| | | private static final ASCIICharProp[] CHAR_PROPS = new ASCIICharProp[128]; |
| | | |
| | | static { |
| | | for (int i = 0; i < 128; i++) { |
| | | CHAR_PROPS[i] = new ASCIICharProp((char) i); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns the character properties for the provided ASCII character. If a |
| | | * non-ASCII character is provided then this method returns {@code null}. |
| | | * |
| | | * @param c |
| | | * The ASCII character. |
| | | * @return The character properties for the provided ASCII character, or |
| | | * {@code null} if {@code c} is greater than {@code \u007F} . |
| | | */ |
| | | public static ASCIICharProp valueOf(final char c) { |
| | | if (c < 128) { |
| | | return CHAR_PROPS[c]; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns the character properties for the provided ASCII character. If a |
| | | * non-ASCII character is provided then this method returns {@code null}. |
| | | * |
| | | * @param c |
| | | * The ASCII character. |
| | | * @return The character properties for the provided ASCII character, or |
| | | * {@code null} if {@code c} is less than zero or greater than |
| | | * {@code \u007F} . |
| | | */ |
| | | public static ASCIICharProp valueOf(final int c) { |
| | | if (c >= 0 && c < 128) { |
| | | return CHAR_PROPS[c]; |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private ASCIICharProp(final char c) { |
| | | this.c = c; |
| | | this.stringValue = new String(new char[] { c }); |
| | | |
| | | if (c >= 'a' && c <= 'z') { |
| | | this.upperCaseChar = (char) (c - 32); |
| | | this.lowerCaseChar = c; |
| | | this.isUpperCaseChar = false; |
| | | this.isLowerCaseChar = true; |
| | | this.isDigit = false; |
| | | this.isLetter = true; |
| | | this.isKeyChar = true; |
| | | this.isCompatKeyChar = true; |
| | | this.decimalValue = -1; |
| | | if (c >= 'a' && c <= 'f') { |
| | | this.isHexChar = true; |
| | | this.hexValue = c - 87; |
| | | } else { |
| | | this.isHexChar = false; |
| | | this.hexValue = -1; |
| | | } |
| | | } else if (c >= 'A' && c <= 'Z') { |
| | | this.upperCaseChar = c; |
| | | this.lowerCaseChar = (char) (c + 32); |
| | | this.isUpperCaseChar = true; |
| | | this.isLowerCaseChar = false; |
| | | this.isDigit = false; |
| | | this.isLetter = true; |
| | | this.isKeyChar = true; |
| | | this.isCompatKeyChar = true; |
| | | this.decimalValue = -1; |
| | | if (c >= 'A' && c <= 'F') { |
| | | this.isHexChar = true; |
| | | this.hexValue = c - 55; |
| | | } else { |
| | | this.isHexChar = false; |
| | | this.hexValue = -1; |
| | | } |
| | | } else if (c >= '0' && c <= '9') { |
| | | this.upperCaseChar = c; |
| | | this.lowerCaseChar = c; |
| | | this.isUpperCaseChar = false; |
| | | this.isLowerCaseChar = false; |
| | | this.isDigit = true; |
| | | this.isLetter = false; |
| | | this.isKeyChar = true; |
| | | this.isCompatKeyChar = true; |
| | | this.isHexChar = true; |
| | | this.hexValue = c - 48; |
| | | this.decimalValue = c - 48; |
| | | } else { |
| | | this.upperCaseChar = c; |
| | | this.lowerCaseChar = c; |
| | | this.isUpperCaseChar = false; |
| | | this.isLowerCaseChar = false; |
| | | this.isDigit = false; |
| | | this.isLetter = false; |
| | | this.isKeyChar = c == '-'; |
| | | this.isCompatKeyChar = (c == '-') || (c == '.') || (c == '_') || (c == '='); |
| | | this.isHexChar = false; |
| | | this.hexValue = -1; |
| | | this.decimalValue = -1; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns the char value associated with this {@code ASCIICharProp}. |
| | | * |
| | | * @return The char value associated with this {@code ASCIICharProp}. |
| | | */ |
| | | public char charValue() { |
| | | return c; |
| | | } |
| | | |
| | | @Override |
| | | public int compareTo(final ASCIICharProp o) { |
| | | return c - o.c; |
| | | } |
| | | |
| | | /** |
| | | * Returns the decimal value associated with this {@code ASCIICharProp}, or |
| | | * {@code -1} if the value is not a decimal digit. |
| | | * |
| | | * @return The decimal value associated with this {@code ASCIICharProp}, or |
| | | * {@code -1} if the value is not a decimal digit. |
| | | */ |
| | | public int decimalValue() { |
| | | return decimalValue; |
| | | } |
| | | |
| | | @Override |
| | | public boolean equals(final Object obj) { |
| | | return this == obj; |
| | | } |
| | | |
| | | @Override |
| | | public int hashCode() { |
| | | return c; |
| | | } |
| | | |
| | | /** |
| | | * Returns the hexadecimal value associated with this {@code ASCIICharProp} |
| | | * , or {@code -1} if the value is not a hexadecimal digit. |
| | | * |
| | | * @return The hexadecimal value associated with this {@code ASCIICharProp} |
| | | * , or {@code -1} if the value is not a hexadecimal digit. |
| | | */ |
| | | public int hexValue() { |
| | | return hexValue; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the char value associated with this |
| | | * {@code ASCIICharProp} is a decimal digit. |
| | | * |
| | | * @return {@code true} if the char value associated with this |
| | | * {@code ASCIICharProp} is a decimal digit. |
| | | */ |
| | | public boolean isDigit() { |
| | | return isDigit; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the char value associated with this |
| | | * {@code ASCIICharProp} is a hexadecimal digit. |
| | | * |
| | | * @return {@code true} if the char value associated with this |
| | | * {@code ASCIICharProp} is a hexadecimal digit. |
| | | */ |
| | | public boolean isHexDigit() { |
| | | return isHexChar; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the char value associated with this |
| | | * {@code ASCIICharProp} is a {@code keychar} as defined in RFC 4512. A |
| | | * {@code keychar} is a letter, a digit, or a hyphen. When |
| | | * {@code allowCompatChars} is {@code true} the following illegal characters |
| | | * will be permitted: |
| | | * |
| | | * <pre> |
| | | * HYPHEN = %x2D ; hyphen ("-") |
| | | * DOT = %x2E ; period (".") |
| | | * EQUALS = %x3D ; equals sign ("=") |
| | | * USCORE = %x5F ; underscore ("_") |
| | | * </pre> |
| | | * |
| | | * @param allowCompatChars |
| | | * {@code true} if certain illegal characters should be allowed |
| | | * for compatibility reasons. |
| | | * @return {@code true} if the char value associated with this |
| | | * {@code ASCIICharProp} is a {@code keychar}. |
| | | */ |
| | | public boolean isKeyChar(final boolean allowCompatChars) { |
| | | return allowCompatChars ? isCompatKeyChar : isKeyChar; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the char value associated with this |
| | | * {@code ASCIICharProp} is a letter. |
| | | * |
| | | * @return {@code true} if the char value associated with this |
| | | * {@code ASCIICharProp} is a letter. |
| | | */ |
| | | public boolean isLetter() { |
| | | return isLetter; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the char value associated with this |
| | | * {@code ASCIICharProp} is a lower-case character. |
| | | * |
| | | * @return {@code true} if the char value associated with this |
| | | * {@code ASCIICharProp} is a lower-case character. |
| | | */ |
| | | public boolean isLowerCase() { |
| | | return isLowerCaseChar; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether or not the char value associated with this |
| | | * {@code ASCIICharProp} is an upper-case character. |
| | | * |
| | | * @return {@code true} if the char value associated with this |
| | | * {@code ASCIICharProp} is an upper-case character. |
| | | */ |
| | | public boolean isUpperCase() { |
| | | return isUpperCaseChar; |
| | | } |
| | | |
| | | /** |
| | | * Returns the lower-case char value associated with this |
| | | * {@code ASCIICharProp}. |
| | | * |
| | | * @return The lower-case char value associated with this |
| | | * {@code ASCIICharProp}. |
| | | */ |
| | | public char toLowerCase() { |
| | | return lowerCaseChar; |
| | | } |
| | | |
| | | @Override |
| | | public String toString() { |
| | | return stringValue; |
| | | } |
| | | |
| | | /** |
| | | * Returns the upper-case char value associated with this |
| | | * {@code ASCIICharProp}. |
| | | * |
| | | * @return The upper-case char value associated with this |
| | | * {@code ASCIICharProp}. |
| | | */ |
| | | public char toUpperCase() { |
| | | return upperCaseChar; |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.util; |
| | | |
| | | import java.util.AbstractCollection; |
| | | import java.util.Collection; |
| | | import java.util.Iterator; |
| | | import java.util.List; |
| | | import java.util.ListIterator; |
| | | |
| | | import org.forgerock.util.Function; |
| | | import org.forgerock.util.promise.NeverThrowsException; |
| | | |
| | | /** Additional {@code Collection} based utility methods. */ |
| | | public final class Collections2 { |
| | | private static class TransformedCollection<M, N, C extends Collection<M>> extends |
| | | AbstractCollection<N> implements Collection<N> { |
| | | protected final C collection; |
| | | |
| | | protected final Function<? super M, ? extends N, NeverThrowsException> funcMtoN; |
| | | |
| | | protected final Function<? super N, ? extends M, NeverThrowsException> funcNtoM; |
| | | |
| | | protected TransformedCollection(final C collection, |
| | | final Function<? super M, ? extends N, NeverThrowsException> funcMtoN, |
| | | final Function<? super N, ? extends M, NeverThrowsException> funcNtoM) { |
| | | this.collection = collection; |
| | | this.funcMtoN = funcMtoN; |
| | | this.funcNtoM = funcNtoM; |
| | | } |
| | | |
| | | @Override |
| | | public boolean add(final N e) { |
| | | return collection.add(funcNtoM.apply(e)); |
| | | } |
| | | |
| | | @Override |
| | | public void clear() { |
| | | collection.clear(); |
| | | } |
| | | |
| | | @Override |
| | | @SuppressWarnings("unchecked") |
| | | public boolean contains(final Object o) { |
| | | return collection.contains(funcNtoM.apply((N) o)); |
| | | } |
| | | |
| | | @Override |
| | | public boolean isEmpty() { |
| | | return collection.isEmpty(); |
| | | } |
| | | |
| | | @Override |
| | | public Iterator<N> iterator() { |
| | | return Iterators.transformedIterator(collection.iterator(), funcMtoN); |
| | | } |
| | | |
| | | @Override |
| | | @SuppressWarnings("unchecked") |
| | | public boolean remove(final Object o) { |
| | | return collection.remove(funcNtoM.apply((N) o)); |
| | | } |
| | | |
| | | @Override |
| | | public int size() { |
| | | return collection.size(); |
| | | } |
| | | } |
| | | |
| | | private static final class TransformedList<M, N> extends |
| | | TransformedCollection<M, N, List<M>> implements List<N> { |
| | | private TransformedList(final List<M> list, |
| | | final Function<? super M, ? extends N, NeverThrowsException> funcMtoN, |
| | | final Function<? super N, ? extends M, NeverThrowsException> funcNtoM) { |
| | | super(list, funcMtoN, funcNtoM); |
| | | } |
| | | |
| | | @Override |
| | | public void add(final int index, final N element) { |
| | | collection.add(index, funcNtoM.apply(element)); |
| | | } |
| | | |
| | | @Override |
| | | public boolean addAll(final int index, final Collection<? extends N> c) { |
| | | // We cannot transform c here due to type-safety. |
| | | boolean result = false; |
| | | for (final N e : c) { |
| | | result |= add(e); |
| | | } |
| | | return result; |
| | | } |
| | | |
| | | @Override |
| | | public N get(final int index) { |
| | | return funcMtoN.apply(collection.get(index)); |
| | | } |
| | | |
| | | @Override |
| | | @SuppressWarnings("unchecked") |
| | | public int indexOf(final Object o) { |
| | | return collection.indexOf(funcNtoM.apply((N) o)); |
| | | } |
| | | |
| | | @Override |
| | | @SuppressWarnings("unchecked") |
| | | public int lastIndexOf(final Object o) { |
| | | return collection.lastIndexOf(funcNtoM.apply((N) o)); |
| | | } |
| | | |
| | | @Override |
| | | public ListIterator<N> listIterator() { |
| | | return listIterator(0); |
| | | } |
| | | |
| | | @Override |
| | | public ListIterator<N> listIterator(final int index) { |
| | | final ListIterator<M> iterator = collection.listIterator(index); |
| | | return new ListIterator<N>() { |
| | | |
| | | @Override |
| | | public void add(final N e) { |
| | | iterator.add(funcNtoM.apply(e)); |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasNext() { |
| | | return iterator.hasNext(); |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasPrevious() { |
| | | return iterator.hasPrevious(); |
| | | } |
| | | |
| | | @Override |
| | | public N next() { |
| | | return funcMtoN.apply(iterator.next()); |
| | | } |
| | | |
| | | @Override |
| | | public int nextIndex() { |
| | | return iterator.nextIndex(); |
| | | } |
| | | |
| | | @Override |
| | | public N previous() { |
| | | return funcMtoN.apply(iterator.previous()); |
| | | } |
| | | |
| | | @Override |
| | | public int previousIndex() { |
| | | return iterator.previousIndex(); |
| | | } |
| | | |
| | | @Override |
| | | public void remove() { |
| | | iterator.remove(); |
| | | } |
| | | |
| | | @Override |
| | | public void set(final N e) { |
| | | iterator.set(funcNtoM.apply(e)); |
| | | } |
| | | |
| | | }; |
| | | } |
| | | |
| | | @Override |
| | | public N remove(final int index) { |
| | | return funcMtoN.apply(collection.remove(index)); |
| | | } |
| | | |
| | | @Override |
| | | public N set(final int index, final N element) { |
| | | final M result = collection.set(index, funcNtoM.apply(element)); |
| | | return funcMtoN.apply(result); |
| | | } |
| | | |
| | | @Override |
| | | public List<N> subList(final int fromIndex, final int toIndex) { |
| | | final List<M> subList = collection.subList(fromIndex, toIndex); |
| | | return new TransformedList<>(subList, funcMtoN, funcNtoM); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns a view of {@code collection} whose values have been mapped to |
| | | * elements of type {@code N} using {@code funcMtoN}. The returned |
| | | * collection supports all operations. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code collection}. |
| | | * @param <N> |
| | | * The type of elements contained in the returned collection. |
| | | * @param collection |
| | | * The collection to be transformed. |
| | | * @param funcMtoN |
| | | * A function which maps values of type {@code M} to values of |
| | | * type {@code N}. This function will be used when retrieving |
| | | * values from {@code collection}. |
| | | * @param funcNtoM |
| | | * A function which maps values of type {@code N} to values of |
| | | * type {@code M}. This function will be used when performing |
| | | * queries and adding values to {@code collection} . |
| | | * @return A view of {@code collection} whose values have been mapped to |
| | | * elements of type {@code N} using {@code funcMtoN}. |
| | | */ |
| | | public static <M, N> Collection<N> transformedCollection(final Collection<M> collection, |
| | | final Function<? super M, ? extends N, NeverThrowsException> funcMtoN, |
| | | final Function<? super N, ? extends M, NeverThrowsException> funcNtoM) { |
| | | return new TransformedCollection<>(collection, funcMtoN, funcNtoM); |
| | | } |
| | | |
| | | /** |
| | | * Returns a view of {@code list} whose values have been mapped to elements |
| | | * of type {@code N} using {@code funcMtoN}. The returned list supports all |
| | | * operations. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code list}. |
| | | * @param <N> |
| | | * The type of elements contained in the returned list. |
| | | * @param list |
| | | * The list to be transformed. |
| | | * @param funcMtoN |
| | | * A function which maps values of type {@code M} to values of |
| | | * type {@code N}. This function will be used when retrieving |
| | | * values from {@code list}. |
| | | * @param funcNtoM |
| | | * A function which maps values of type {@code N} to values of |
| | | * type {@code M}. This function will be used when performing |
| | | * queries and adding values to {@code list} . |
| | | * @return A view of {@code list} whose values have been mapped to elements |
| | | * of type {@code N} using {@code funcMtoN}. |
| | | */ |
| | | public static <M, N> List<N> transformedList(final List<M> list, |
| | | final Function<? super M, ? extends N, NeverThrowsException> funcMtoN, |
| | | final Function<? super N, ? extends M, NeverThrowsException> funcNtoM) { |
| | | return new TransformedList<>(list, funcMtoN, funcNtoM); |
| | | } |
| | | |
| | | /** Prevent instantiation. */ |
| | | private Collections2() { |
| | | // Do nothing. |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions copyright 2013-2015 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.util; |
| | | |
| | | import java.util.Collection; |
| | | import java.util.Iterator; |
| | | |
| | | import org.forgerock.util.Function; |
| | | import org.forgerock.util.promise.NeverThrowsException; |
| | | |
| | | /** |
| | | * Utility methods for manipulating {@link Iterable}s. |
| | | */ |
| | | public final class Iterables { |
| | | private static abstract class AbstractIterable<M> implements Iterable<M> { |
| | | @Override |
| | | public String toString() { |
| | | return Iterables.toString(this); |
| | | } |
| | | } |
| | | |
| | | private static final class ArrayIterable<M> extends AbstractIterable<M> { |
| | | private final M[] a; |
| | | |
| | | /** Constructed via factory methods. */ |
| | | private ArrayIterable(final M[] a) { |
| | | this.a = a; |
| | | } |
| | | |
| | | @Override |
| | | public Iterator<M> iterator() { |
| | | return Iterators.arrayIterator(a); |
| | | } |
| | | } |
| | | |
| | | private static final class EmptyIterable<M> extends AbstractIterable<M> { |
| | | @Override |
| | | public Iterator<M> iterator() { |
| | | return Iterators.emptyIterator(); |
| | | } |
| | | } |
| | | |
| | | private static final class FilteredIterable<M, P> extends AbstractIterable<M> { |
| | | private final Iterable<M> iterable; |
| | | private final P parameter; |
| | | private final Predicate<? super M, P> predicate; |
| | | |
| | | /** Constructed via factory methods. */ |
| | | private FilteredIterable(final Iterable<M> iterable, |
| | | final Predicate<? super M, P> predicate, final P p) { |
| | | this.iterable = iterable; |
| | | this.predicate = predicate; |
| | | this.parameter = p; |
| | | } |
| | | |
| | | @Override |
| | | public Iterator<M> iterator() { |
| | | return Iterators.filteredIterator(iterable.iterator(), predicate, parameter); |
| | | } |
| | | } |
| | | |
| | | private static final class SingletonIterable<M> extends AbstractIterable<M> { |
| | | private final M value; |
| | | |
| | | /** Constructed via factory methods. */ |
| | | private SingletonIterable(final M value) { |
| | | this.value = value; |
| | | } |
| | | |
| | | @Override |
| | | public Iterator<M> iterator() { |
| | | return Iterators.singletonIterator(value); |
| | | } |
| | | } |
| | | |
| | | private static final class TransformedIterable<M, N> extends AbstractIterable<N> { |
| | | private final Function<? super M, ? extends N, NeverThrowsException> function; |
| | | private final Iterable<M> iterable; |
| | | |
| | | /** Constructed via factory methods. */ |
| | | private TransformedIterable(final Iterable<M> iterable, |
| | | final Function<? super M, ? extends N, NeverThrowsException> function) { |
| | | this.iterable = iterable; |
| | | this.function = function; |
| | | } |
| | | |
| | | @Override |
| | | public Iterator<N> iterator() { |
| | | return Iterators.transformedIterator(iterable.iterator(), function); |
| | | } |
| | | } |
| | | |
| | | private static final class UnmodifiableIterable<M> extends AbstractIterable<M> { |
| | | private final Iterable<M> iterable; |
| | | |
| | | /** Constructed via factory methods. */ |
| | | private UnmodifiableIterable(final Iterable<M> iterable) { |
| | | this.iterable = iterable; |
| | | } |
| | | |
| | | @Override |
| | | public Iterator<M> iterator() { |
| | | return Iterators.unmodifiableIterator(iterable.iterator()); |
| | | } |
| | | } |
| | | |
| | | private static final Iterable<Object> EMPTY_ITERABLE = new EmptyIterable<>(); |
| | | |
| | | /** |
| | | * Returns an iterable containing the elements of {@code a}. The returned |
| | | * iterable's iterator does not support element removal via the |
| | | * {@code remove()} method. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code a}. |
| | | * @param a |
| | | * The array of elements. |
| | | * @return An iterable containing the elements of {@code a}. |
| | | */ |
| | | public static <M> Iterable<M> arrayIterable(final M[] a) { |
| | | return new ArrayIterable<>(a); |
| | | } |
| | | |
| | | /** |
| | | * Returns an immutable empty iterable. |
| | | * |
| | | * @param <M> |
| | | * The required type of the empty iterable. |
| | | * @return An immutable empty iterable. |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static <M> Iterable<M> emptyIterable() { |
| | | return (Iterable<M>) EMPTY_ITERABLE; |
| | | } |
| | | |
| | | /** |
| | | * Returns a filtered view of {@code iterable} containing only those |
| | | * elements which match {@code predicate}. The returned iterable's iterator |
| | | * supports element removal via the {@code remove()} method subject to any |
| | | * constraints imposed by {@code iterable}. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code iterable}. |
| | | * @param <P> |
| | | * The type of the additional parameter to the predicate's |
| | | * {@code matches} method. Use {@link java.lang.Void} for |
| | | * predicates that do not need an additional parameter. |
| | | * @param iterable |
| | | * The iterable to be filtered. |
| | | * @param predicate |
| | | * The predicate. |
| | | * @param p |
| | | * A predicate specified parameter. |
| | | * @return A filtered view of {@code iterable} containing only those |
| | | * elements which match {@code predicate}. |
| | | */ |
| | | public static <M, P> Iterable<M> filteredIterable(final Iterable<M> iterable, |
| | | final Predicate<? super M, P> predicate, final P p) { |
| | | return new FilteredIterable<>(iterable, predicate, p); |
| | | } |
| | | |
| | | /** |
| | | * Returns a filtered view of {@code iterable} containing only those |
| | | * elements which match {@code predicate}. The returned iterable's iterator |
| | | * supports element removal via the {@code remove()} method subject to any |
| | | * constraints imposed by {@code iterable}. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code iterable}. |
| | | * @param iterable |
| | | * The iterable to be filtered. |
| | | * @param predicate |
| | | * The predicate. |
| | | * @return A filtered view of {@code iterable} containing only those |
| | | * elements which match {@code predicate}. |
| | | */ |
| | | public static <M> Iterable<M> filteredIterable(final Iterable<M> iterable, |
| | | final Predicate<? super M, Void> predicate) { |
| | | return new FilteredIterable<>(iterable, predicate, null); |
| | | } |
| | | |
| | | /** |
| | | * Returns {@code true} if the provided iterable does not contain any |
| | | * elements. |
| | | * |
| | | * @param iterable |
| | | * The iterable. |
| | | * @return {@code true} if the provided iterable does not contain any |
| | | * elements. |
| | | */ |
| | | public static boolean isEmpty(final Iterable<?> iterable) { |
| | | if (iterable instanceof Collection) { |
| | | // Fall-through if possible and potentially avoid allocation. |
| | | return ((Collection<?>) iterable).isEmpty(); |
| | | } else { |
| | | return !iterable.iterator().hasNext(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns an iterable containing the single element {@code value}. The |
| | | * returned iterable's iterator does not support element removal via the |
| | | * {@code remove()} method. |
| | | * |
| | | * @param <M> |
| | | * The type of the single element {@code value}. |
| | | * @param value |
| | | * The single element. |
| | | * @return An iterable containing the single element {@code value}. |
| | | */ |
| | | public static <M> Iterable<M> singletonIterable(final M value) { |
| | | return new SingletonIterable<>(value); |
| | | } |
| | | |
| | | /** |
| | | * Returns the number of elements contained in the provided iterable. |
| | | * |
| | | * @param iterable |
| | | * The iterable. |
| | | * @return The number of elements contained in the provided iterable. |
| | | */ |
| | | public static int size(final Iterable<?> iterable) { |
| | | if (iterable instanceof Collection) { |
| | | // Fall-through if possible and potentially benefit from constant time calculation. |
| | | return ((Collection<?>) iterable).size(); |
| | | } else { |
| | | final Iterator<?> i = iterable.iterator(); |
| | | int sz = 0; |
| | | while (i.hasNext()) { |
| | | i.next(); |
| | | sz++; |
| | | } |
| | | return sz; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns a string representation of the provided iterable composed of an |
| | | * opening square bracket, followed by each element separated by commas, and |
| | | * then a closing square bracket. |
| | | * |
| | | * @param iterable |
| | | * The iterable whose string representation is to be returned. |
| | | * @return A string representation of the provided iterable. |
| | | * @see java.util.AbstractCollection#toString() |
| | | */ |
| | | public static String toString(final Iterable<?> iterable) { |
| | | if (iterable instanceof Collection) { |
| | | // Fall-through if possible. |
| | | return ((Collection<?>) iterable).toString(); |
| | | } else { |
| | | final StringBuilder builder = new StringBuilder(); |
| | | boolean firstValue = true; |
| | | builder.append('['); |
| | | for (final Object value : iterable) { |
| | | if (!firstValue) { |
| | | builder.append(", "); |
| | | } |
| | | builder.append(value); |
| | | firstValue = false; |
| | | } |
| | | builder.append(']'); |
| | | return builder.toString(); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns a view of {@code iterable} whose values have been mapped to |
| | | * elements of type {@code N} using {@code function}. The returned |
| | | * iterable's iterator supports element removal via the {@code remove()} |
| | | * method subject to any constraints imposed by {@code iterable}. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code iterable}. |
| | | * @param <N> |
| | | * The type of elements contained in the returned iterable. |
| | | * @param iterable |
| | | * The iterable to be transformed. |
| | | * @param function |
| | | * The function. |
| | | * @return A view of {@code iterable} whose values have been mapped to |
| | | * elements of type {@code N} using {@code function}. |
| | | */ |
| | | public static <M, N> Iterable<N> transformedIterable(final Iterable<M> iterable, |
| | | final Function<? super M, ? extends N, NeverThrowsException> function) { |
| | | return new TransformedIterable<>(iterable, function); |
| | | } |
| | | |
| | | /** |
| | | * Returns a read-only view of {@code iterable} whose iterator does not |
| | | * support element removal via the {@code remove()}. Attempts to use the |
| | | * {@code remove()} method will result in a |
| | | * {@code UnsupportedOperationException}. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code iterable}. |
| | | * @param iterable |
| | | * The iterable to be made read-only. |
| | | * @return A read-only view of {@code iterable} whose iterator does not |
| | | * support element removal via the {@code remove()}. |
| | | */ |
| | | public static <M> Iterable<M> unmodifiableIterable(final Iterable<M> iterable) { |
| | | return new UnmodifiableIterable<>(iterable); |
| | | } |
| | | |
| | | /** Prevent instantiation. */ |
| | | private Iterables() { |
| | | // Do nothing. |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2009-2010 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.util; |
| | | |
| | | import java.util.Iterator; |
| | | import java.util.NoSuchElementException; |
| | | |
| | | import org.forgerock.util.Function; |
| | | import org.forgerock.util.promise.NeverThrowsException; |
| | | |
| | | /** Utility methods for manipulating {@link Iterator}s. */ |
| | | public final class Iterators { |
| | | private static final class ArrayIterator<M> implements Iterator<M> { |
| | | private int i; |
| | | private final M[] a; |
| | | |
| | | /** Constructed via factory methods. */ |
| | | private ArrayIterator(final M[] a) { |
| | | this.a = a; |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasNext() { |
| | | return i < a.length; |
| | | } |
| | | |
| | | @Override |
| | | public M next() { |
| | | if (hasNext()) { |
| | | return a[i++]; |
| | | } else { |
| | | throw new NoSuchElementException(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void remove() { |
| | | throw new UnsupportedOperationException(); |
| | | } |
| | | |
| | | } |
| | | |
| | | private static final class EmptyIterator<M> implements Iterator<M> { |
| | | @Override |
| | | public boolean hasNext() { |
| | | return false; |
| | | } |
| | | |
| | | @Override |
| | | public M next() { |
| | | throw new NoSuchElementException(); |
| | | } |
| | | |
| | | @Override |
| | | public void remove() { |
| | | throw new UnsupportedOperationException(); |
| | | } |
| | | } |
| | | |
| | | private static final class FilteredIterator<M, P> implements Iterator<M> { |
| | | |
| | | private boolean hasNextMustIterate = true; |
| | | private final Iterator<M> iterator; |
| | | private M next; |
| | | |
| | | private final P parameter; |
| | | private final Predicate<? super M, P> predicate; |
| | | |
| | | /** Constructed via factory methods. */ |
| | | private FilteredIterator(final Iterator<M> iterator, |
| | | final Predicate<? super M, P> predicate, final P p) { |
| | | this.iterator = iterator; |
| | | this.predicate = predicate; |
| | | this.parameter = p; |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasNext() { |
| | | if (hasNextMustIterate) { |
| | | hasNextMustIterate = false; |
| | | while (iterator.hasNext()) { |
| | | next = iterator.next(); |
| | | if (predicate.matches(next, parameter)) { |
| | | return true; |
| | | } |
| | | } |
| | | next = null; |
| | | return false; |
| | | } else { |
| | | return next != null; |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public M next() { |
| | | if (!hasNext()) { |
| | | throw new NoSuchElementException(); |
| | | } |
| | | hasNextMustIterate = true; |
| | | return next; |
| | | } |
| | | |
| | | @Override |
| | | public void remove() { |
| | | iterator.remove(); |
| | | } |
| | | |
| | | } |
| | | |
| | | private static final class SingletonIterator<M> implements Iterator<M> { |
| | | private M value; |
| | | |
| | | /** Constructed via factory methods. */ |
| | | private SingletonIterator(final M value) { |
| | | this.value = value; |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasNext() { |
| | | return value != null; |
| | | } |
| | | |
| | | @Override |
| | | public M next() { |
| | | if (value != null) { |
| | | final M tmp = value; |
| | | value = null; |
| | | return tmp; |
| | | } else { |
| | | throw new NoSuchElementException(); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void remove() { |
| | | throw new UnsupportedOperationException(); |
| | | } |
| | | |
| | | } |
| | | |
| | | private static final class TransformedIterator<M, N> implements Iterator<N> { |
| | | |
| | | private final Function<? super M, ? extends N, NeverThrowsException> function; |
| | | private final Iterator<M> iterator; |
| | | |
| | | /** Constructed via factory methods. */ |
| | | private TransformedIterator(final Iterator<M> iterator, |
| | | final Function<? super M, ? extends N, NeverThrowsException> function) { |
| | | this.iterator = iterator; |
| | | this.function = function; |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasNext() { |
| | | return iterator.hasNext(); |
| | | } |
| | | |
| | | @Override |
| | | public N next() { |
| | | return function.apply(iterator.next()); |
| | | } |
| | | |
| | | @Override |
| | | public void remove() { |
| | | iterator.remove(); |
| | | } |
| | | |
| | | } |
| | | |
| | | private static final class UnmodifiableIterator<M> implements Iterator<M> { |
| | | private final Iterator<M> iterator; |
| | | |
| | | private UnmodifiableIterator(final Iterator<M> iterator) { |
| | | this.iterator = iterator; |
| | | } |
| | | |
| | | @Override |
| | | public boolean hasNext() { |
| | | return iterator.hasNext(); |
| | | } |
| | | |
| | | @Override |
| | | public M next() { |
| | | return iterator.next(); |
| | | } |
| | | |
| | | @Override |
| | | public void remove() { |
| | | throw new UnsupportedOperationException(); |
| | | } |
| | | } |
| | | |
| | | private static final Iterator<Object> EMPTY_ITERATOR = new EmptyIterator<>(); |
| | | |
| | | /** |
| | | * Returns an iterator over the elements contained in {@code a}. The |
| | | * returned iterator does not support element removal via the |
| | | * {@code remove()} method. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code a}. |
| | | * @param a |
| | | * The array of elements to be returned by the iterator. |
| | | * @return An iterator over the elements contained in {@code a}. |
| | | */ |
| | | public static <M> Iterator<M> arrayIterator(final M[] a) { |
| | | return new ArrayIterator<>(a); |
| | | } |
| | | |
| | | /** |
| | | * Returns an immutable empty iterator. |
| | | * |
| | | * @param <M> |
| | | * The required type of the empty iterator. |
| | | * @return An immutable empty iterator. |
| | | */ |
| | | @SuppressWarnings("unchecked") |
| | | public static <M> Iterator<M> emptyIterator() { |
| | | return (Iterator<M>) EMPTY_ITERATOR; |
| | | } |
| | | |
| | | /** |
| | | * Returns a filtered view of {@code iterator} containing only those |
| | | * elements which match {@code predicate}. The returned iterator supports |
| | | * element removal via the {@code remove()} method subject to any |
| | | * constraints imposed by {@code iterator}. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code iterator}. |
| | | * @param <P> |
| | | * The type of the additional parameter to the predicate's |
| | | * {@code matches} method. Use {@link java.lang.Void} for |
| | | * predicates that do not need an additional parameter. |
| | | * @param iterator |
| | | * The iterator to be filtered. |
| | | * @param predicate |
| | | * The predicate. |
| | | * @param p |
| | | * A predicate specified parameter. |
| | | * @return A filtered view of {@code iterator} containing only those |
| | | * elements which match {@code predicate}. |
| | | */ |
| | | public static <M, P> Iterator<M> filteredIterator(final Iterator<M> iterator, |
| | | final Predicate<? super M, P> predicate, final P p) { |
| | | return new FilteredIterator<>(iterator, predicate, p); |
| | | } |
| | | |
| | | /** |
| | | * Returns a filtered view of {@code iterator} containing only those |
| | | * elements which match {@code predicate}. The returned iterator supports |
| | | * element removal via the {@code remove()} method subject to any |
| | | * constraints imposed by {@code iterator}. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code iterator}. |
| | | * @param iterator |
| | | * The iterator to be filtered. |
| | | * @param predicate |
| | | * The predicate. |
| | | * @return A filtered view of {@code iterator} containing only those |
| | | * elements which match {@code predicate}. |
| | | */ |
| | | public static <M> Iterator<M> filteredIterator(final Iterator<M> iterator, |
| | | final Predicate<? super M, Void> predicate) { |
| | | return new FilteredIterator<>(iterator, predicate, null); |
| | | } |
| | | |
| | | /** |
| | | * Returns an iterator containing the single element {@code value}. The |
| | | * returned iterator does not support element removal via the |
| | | * {@code remove()} method. |
| | | * |
| | | * @param <M> |
| | | * The type of the single element {@code value}. |
| | | * @param value |
| | | * The single element to be returned by the iterator. |
| | | * @return An iterator containing the single element {@code value}. |
| | | */ |
| | | public static <M> Iterator<M> singletonIterator(final M value) { |
| | | return new SingletonIterator<>(value); |
| | | } |
| | | |
| | | /** |
| | | * Returns a view of {@code iterator} whose values have been mapped to |
| | | * elements of type {@code N} using {@code function}. The returned iterator |
| | | * supports element removal via the {@code remove()} method subject to any |
| | | * constraints imposed by {@code iterator}. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code iterator}. |
| | | * @param <N> |
| | | * The type of elements contained in the returned iterator. |
| | | * @param iterator |
| | | * The iterator to be transformed. |
| | | * @param function |
| | | * The function. |
| | | * @return A view of {@code iterator} whose values have been mapped to |
| | | * elements of type {@code N} using {@code function}. |
| | | */ |
| | | public static <M, N> Iterator<N> transformedIterator(final Iterator<M> iterator, |
| | | final Function<? super M, ? extends N, NeverThrowsException> function) { |
| | | return new TransformedIterator<>(iterator, function); |
| | | } |
| | | |
| | | /** |
| | | * Returns a read-only view of {@code iterator} which does not support |
| | | * element removal via the {@code remove()}. Attempts to use the |
| | | * {@code remove()} method will result in a |
| | | * {@code UnsupportedOperationException}. |
| | | * |
| | | * @param <M> |
| | | * The type of elements contained in {@code iterator}. |
| | | * @param iterator |
| | | * The iterator to be made read-only. |
| | | * @return A read-only view of {@code iterator} which does not support |
| | | * element removal via the {@code remove()}. |
| | | */ |
| | | public static <M> Iterator<M> unmodifiableIterator(final Iterator<M> iterator) { |
| | | return new UnmodifiableIterator<>(iterator); |
| | | } |
| | | |
| | | /** Prevent instantiation. */ |
| | | private Iterators() { |
| | | // Do nothing. |
| | | } |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2008 Sun Microsystems, Inc. |
| | | * Portions Copyright 2014-2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.util; |
| | | |
| | | /** |
| | | * This class defines an enumeration that may be used to identify the operating system |
| | | * on which the JVM is running. |
| | | */ |
| | | public enum OperatingSystem { |
| | | /** |
| | | * The value indicating the AIX operating system. |
| | | */ |
| | | AIX("AIX", false, false, true), |
| | | |
| | | /** |
| | | * The value indicating the FreeBSD operating system. |
| | | */ |
| | | FREEBSD("FreeBSD", false, false, true), |
| | | |
| | | /** |
| | | * The value indicating the HP-UX operating system. |
| | | */ |
| | | HPUX("HP UX", false, false, true), |
| | | |
| | | /** |
| | | * The value indicating the Linux operating system. |
| | | */ |
| | | LINUX("Linux", false, false, true), |
| | | |
| | | /** |
| | | * The value indicating the Mac OS X operating system. |
| | | */ |
| | | MACOSX("Mac OS X", false, true, true), |
| | | |
| | | /** |
| | | * The value indicating the Solaris operating system. |
| | | */ |
| | | SOLARIS("Solaris", false, false, true), |
| | | |
| | | /** |
| | | * The value indicating the Windows operating system. |
| | | */ |
| | | WINDOWS("Windows", true, false, false), |
| | | |
| | | /** |
| | | * The value indicating the Windows 7 operating system. |
| | | */ |
| | | WINDOWS7("Windows 7", true, false, false), |
| | | |
| | | /** |
| | | * The value indicating the Windows Vista operating system. |
| | | */ |
| | | WINDOWS_VISTA("Windows Vista", true, false, false), |
| | | |
| | | /** |
| | | * The value indicating the Windows Server 2008 operating system. |
| | | */ |
| | | WINDOWS_SERVER_2008("Server 2008", true, false, false), |
| | | |
| | | /** |
| | | * The value indicating the z/OS operating system. |
| | | */ |
| | | ZOS("z/OS", false, false, false), |
| | | |
| | | /** |
| | | * The value indicating an unknown operating system. |
| | | */ |
| | | UNKNOWN("Unknown", false, false, false); |
| | | |
| | | /** The human-readable name for this operating system. */ |
| | | private String osName; |
| | | |
| | | private boolean isWindows; |
| | | private boolean isMacOS; |
| | | private boolean isUnixBased; |
| | | |
| | | private static final OperatingSystem INSTANCE = forName(System.getProperty("os.name")); |
| | | |
| | | /** |
| | | * Creates a new operating system value with the provided name. |
| | | * |
| | | * @param osName |
| | | * The human-readable name for the operating system. |
| | | */ |
| | | private OperatingSystem(String osName, boolean isWindows, boolean isMacOS, boolean isUnixBased) { |
| | | this.osName = osName; |
| | | this.isWindows = isWindows; |
| | | this.isMacOS = isMacOS; |
| | | this.isUnixBased = isUnixBased; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the human-readable name of this operating system. |
| | | * |
| | | * @return The human-readable name for this operating system. |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | return osName; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the operating system for the provided name. |
| | | * |
| | | * @param osName |
| | | * The name for which to retrieve the corresponding operating system. |
| | | * @return The operating system for the provided name. |
| | | */ |
| | | public static OperatingSystem forName(final String osName) { |
| | | if (osName == null) { |
| | | return UNKNOWN; |
| | | } |
| | | |
| | | final String lowerName = osName.toLowerCase(); |
| | | if (lowerName.contains("solaris") || lowerName.contains("sunos")) { |
| | | return SOLARIS; |
| | | } else if (lowerName.contains("linux")) { |
| | | return LINUX; |
| | | } else if (lowerName.contains("hp-ux") |
| | | || lowerName.contains("hp ux") |
| | | || lowerName.contains("hpux")) { |
| | | return HPUX; |
| | | } else if (lowerName.contains("aix")) { |
| | | return AIX; |
| | | } else if (lowerName.contains("windows")) { |
| | | if (lowerName.indexOf("windows 7") != -1) { |
| | | return WINDOWS7; |
| | | } else if (lowerName.indexOf("vista") != -1) { |
| | | return WINDOWS_VISTA; |
| | | } else if (lowerName.indexOf("server 2008") != -1) { |
| | | return WINDOWS_SERVER_2008; |
| | | } |
| | | return WINDOWS; |
| | | } else if (lowerName.contains("freebsd") || lowerName.contains("free bsd")) { |
| | | return FREEBSD; |
| | | } else if (lowerName.contains("macos x") || lowerName.contains("mac os x")) { |
| | | return MACOSX; |
| | | } else if (lowerName.contains("z/os")) { |
| | | return ZOS; |
| | | } |
| | | return UNKNOWN; |
| | | } |
| | | |
| | | /** |
| | | * Returns the operating system on which the JVM is running. |
| | | * |
| | | * @return The operating system on which the JVM is running |
| | | */ |
| | | public static OperatingSystem getOperatingSystem() { |
| | | return INSTANCE; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether the underlying operating system is a Windows variant. |
| | | * |
| | | * @return {@code true} if the underlying operating system is a Windows variant, or {@code false} if not. |
| | | */ |
| | | public static boolean isWindows() { |
| | | return INSTANCE.isWindows; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether the underlying operating system is Windows Vista. |
| | | * |
| | | * @return {@code true} if the underlying operating system is Windows Vista, or {@code false} if not. |
| | | */ |
| | | public static boolean isVista() { |
| | | return INSTANCE == WINDOWS_VISTA; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether the underlying operating system is Windows 2008. |
| | | * |
| | | * @return {@code true} if the underlying operating system is Windows 2008, or {@code false} if not. |
| | | */ |
| | | public static boolean isWindows2008() { |
| | | return INSTANCE == WINDOWS_SERVER_2008; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether the underlying operating system is Windows 7. |
| | | * |
| | | * @return {@code true} if the underlying operating system is Windows 7, or {@code false} if not. |
| | | */ |
| | | public static boolean isWindows7() { |
| | | return INSTANCE == WINDOWS7; |
| | | } |
| | | |
| | | /** |
| | | * Returns {@code true} if we are running under Mac OS and {@code false} otherwise. |
| | | * |
| | | * @return {@code true} if we are running under Mac OS and {@code false} otherwise. |
| | | */ |
| | | public static boolean isMacOS() { |
| | | return INSTANCE.isMacOS; |
| | | } |
| | | |
| | | /** |
| | | * Returns {@code true} if we are running under Unix and {@code false} otherwise. |
| | | * |
| | | * @return {@code true} if we are running under Unix and {@code false} otherwise. |
| | | */ |
| | | public static boolean isUnix() { |
| | | return INSTANCE.isUnixBased; |
| | | } |
| | | |
| | | /** |
| | | * Returns {@code true} if the OS is Unix based. |
| | | * |
| | | * @return {@code true} if the OS is Unix based. |
| | | */ |
| | | public static boolean isUnixBased() { |
| | | return INSTANCE.isUnixBased; |
| | | } |
| | | |
| | | /** |
| | | * Returns {@code true} if the OS is Unknown. |
| | | * |
| | | * @return {@code true} if the OS is Unknown. |
| | | */ |
| | | public static boolean isUnknown() { |
| | | return INSTANCE == UNKNOWN; |
| | | } |
| | | |
| | | /** |
| | | * Indicates whether the underlying operating system has UAC (User Access Control). |
| | | * |
| | | * @return {@code true} if the underlying operating system has UAC (User Access Control), or {@code false} if not. |
| | | */ |
| | | public static boolean hasUAC() { |
| | | return isVista() || isWindows2008() || isWindows7(); |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2015 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.util; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.util.Arrays; |
| | | |
| | | /** |
| | | * Provides static methods to manipulate compact long representation. Compact long allow to stores unsigned long values |
| | | * up to 56 bits using a variable number of bytes from 1 to 8. The binary representations of this compact encoding has |
| | | * the interesting properties of maintaining correct order of values when compared. |
| | | */ |
| | | public final class PackedLong { |
| | | |
| | | /** Maximum size in bytes of a compact encoded value. */ |
| | | public static final int MAX_COMPACT_SIZE = 8; |
| | | |
| | | private PackedLong() { |
| | | } |
| | | |
| | | private static final int[] DECODE_SIZE = new int[256]; |
| | | static { |
| | | Arrays.fill(DECODE_SIZE, 0, 0x80, 1); |
| | | Arrays.fill(DECODE_SIZE, 0x80, 0xc0, 2); |
| | | Arrays.fill(DECODE_SIZE, 0xc0, 0xe0, 3); |
| | | Arrays.fill(DECODE_SIZE, 0xe0, 0xf0, 4); |
| | | Arrays.fill(DECODE_SIZE, 0xf0, 0xf8, 5); |
| | | Arrays.fill(DECODE_SIZE, 0xf8, 0xfc, 6); |
| | | Arrays.fill(DECODE_SIZE, 0xfc, 0xfe, 7); |
| | | Arrays.fill(DECODE_SIZE, 0xfe, 0x100, 8); |
| | | } |
| | | |
| | | /** Maximum value that can be stored with a compacted representation. */ |
| | | public static final long COMPACTED_MAX_VALUE = 0x00FFFFFFFFFFFFFFL; |
| | | |
| | | /** |
| | | * Append the compact representation of the value into the {@link OutputStream}. |
| | | * |
| | | * @param os |
| | | * {@link OutputStream} where the compact representation will be written. |
| | | * @param value |
| | | * Value to be encoded and written in the compact long format. |
| | | * @throws IOException |
| | | * if problem appear in the underlying {@link OutputStream} |
| | | * @return Number of bytes which has been written in the buffer. |
| | | */ |
| | | public static int writeCompactUnsigned(OutputStream os, long value) throws IOException { |
| | | final int size = getEncodedSize(value); |
| | | switch (size) { |
| | | case 1: |
| | | os.write((int) value); |
| | | break; |
| | | case 2: |
| | | os.write((int) ((value >>> 8) | 0x80L)); |
| | | os.write((int) value); |
| | | break; |
| | | case 3: |
| | | os.write((int) ((value >>> 16) | 0xc0L)); |
| | | os.write((int) (value >>> 8)); |
| | | os.write((int) (value)); |
| | | break; |
| | | case 4: |
| | | os.write((int) ((value >>> 24) | 0xe0L)); |
| | | os.write((int) (value >>> 16)); |
| | | os.write((int) (value >>> 8)); |
| | | os.write((int) (value)); |
| | | break; |
| | | case 5: |
| | | os.write((int) ((value >>> 32) | 0xf0L)); |
| | | os.write((int) (value >>> 24)); |
| | | os.write((int) (value >>> 16)); |
| | | os.write((int) (value >>> 8)); |
| | | os.write((int) (value)); |
| | | break; |
| | | case 6: |
| | | os.write((int) ((value >>> 40) | 0xf8L)); |
| | | os.write((int) (value >>> 32)); |
| | | os.write((int) (value >>> 24)); |
| | | os.write((int) (value >>> 16)); |
| | | os.write((int) (value >>> 8)); |
| | | os.write((int) (value)); |
| | | break; |
| | | case 7: |
| | | os.write((int) ((value >>> 48) | 0xfcL)); |
| | | os.write((int) (value >>> 40)); |
| | | os.write((int) (value >>> 32)); |
| | | os.write((int) (value >>> 24)); |
| | | os.write((int) (value >>> 16)); |
| | | os.write((int) (value >>> 8)); |
| | | os.write((int) (value)); |
| | | break; |
| | | case 8: |
| | | os.write(0xfe); |
| | | os.write((int) (value >>> 48)); |
| | | os.write((int) (value >>> 40)); |
| | | os.write((int) (value >>> 32)); |
| | | os.write((int) (value >>> 24)); |
| | | os.write((int) (value >>> 16)); |
| | | os.write((int) (value >>> 8)); |
| | | os.write((int) (value)); |
| | | break; |
| | | default: |
| | | throw new IllegalArgumentException(); |
| | | } |
| | | return size; |
| | | } |
| | | |
| | | /** |
| | | * Get the number of bytes required to store the given value using the compact long representation. |
| | | * |
| | | * @param value |
| | | * Value to get the compact representation's size. |
| | | * @return Number of bytes required to store the compact long representation of the value. |
| | | */ |
| | | public static int getEncodedSize(long value) { |
| | | if (value < 0x80L) { |
| | | return 1; |
| | | } else if (value < 0x4000L) { |
| | | return 2; |
| | | } else if (value < 0x200000L) { |
| | | return 3; |
| | | } else if (value < 0x10000000L) { |
| | | return 4; |
| | | } else if (value < 0x800000000L) { |
| | | return 5; |
| | | } else if (value < 0x40000000000L) { |
| | | return 6; |
| | | } else if (value < 0x2000000000000L) { |
| | | return 7; |
| | | } else if (value < 0x100000000000000L) { |
| | | return 8; |
| | | } else { |
| | | throw new IllegalArgumentException("value out of range: " + value); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Decode and get the value of the compact long contained in the specified {@link InputStream}. |
| | | * |
| | | * @param is |
| | | * Stream where to read the compact unsigned long |
| | | * @return The long value. |
| | | * @throws IOException |
| | | * If the first byte cannot be read for any reason other than the end of the file, if the input stream |
| | | * has been closed, or if some other I/O error occurs. |
| | | */ |
| | | public static long readCompactUnsignedLong(InputStream is) throws IOException { |
| | | final int b0 = checkNotEndOfStream(is.read()); |
| | | final int size = decodeSize(b0); |
| | | long value; |
| | | switch (size) { |
| | | case 1: |
| | | value = b2l((byte) b0); |
| | | break; |
| | | case 2: |
| | | value = (b0 & 0x3fL) << 8; |
| | | value |= checkNotEndOfStream(is.read()); |
| | | break; |
| | | case 3: |
| | | value = (b0 & 0x1fL) << 16; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 8; |
| | | value |= checkNotEndOfStream(is.read()); |
| | | break; |
| | | case 4: |
| | | value = (b0 & 0x0fL) << 24; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 16; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 8; |
| | | value |= is.read(); |
| | | break; |
| | | case 5: |
| | | value = (b0 & 0x07L) << 32; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 24; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 16; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 8; |
| | | value |= (is.read()); |
| | | break; |
| | | case 6: |
| | | value = (b0 & 0x03L) << 40; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 32; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 24; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 16; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 8; |
| | | value |= is.read(); |
| | | break; |
| | | case 7: |
| | | value = (b0 & 0x01L) << 48; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 40; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 32; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 24; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 16; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 8; |
| | | value |= is.read(); |
| | | break; |
| | | default: |
| | | value = ((long) checkNotEndOfStream(is.read())) << 48; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 40; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 32; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 24; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 16; |
| | | value |= ((long) checkNotEndOfStream(is.read())) << 8; |
| | | value |= is.read(); |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | private static int checkNotEndOfStream(final int byteValue) { |
| | | if (byteValue == -1) { |
| | | throw new IllegalArgumentException("End of stream reached."); |
| | | } |
| | | return byteValue; |
| | | } |
| | | |
| | | private static int decodeSize(int b) { |
| | | return DECODE_SIZE[b & 0xff]; |
| | | } |
| | | |
| | | private static long b2l(final byte b) { |
| | | return b & 0xffL; |
| | | } |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2009 Sun Microsystems, Inc. |
| | | */ |
| | | |
| | | package com.forgerock.opendj.util; |
| | | |
| | | /** |
| | | * Predicates transform input values of type {@code M} to a boolean output value |
| | | * and are typically used for performing filtering. |
| | | * |
| | | * @param <M> |
| | | * The type of input values matched by this predicate. |
| | | * @param <P> |
| | | * The type of the additional parameter to this predicate's |
| | | * {@code matches} method. Use {@link java.lang.Void} for predicates |
| | | * that do not need an additional parameter. |
| | | */ |
| | | public interface Predicate<M, P> { |
| | | /** |
| | | * Indicates whether or not this predicate matches the provided input value |
| | | * of type {@code M}. |
| | | * |
| | | * @param value |
| | | * The input value for which to make the determination. |
| | | * @param p |
| | | * A predicate specified parameter. |
| | | * @return {@code true} if this predicate matches {@code value}, otherwise |
| | | * {@code false}. |
| | | */ |
| | | boolean matches(M value, P p); |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2013 ForgeRock AS. |
| | | */ |
| | | |
| | | package com.forgerock.opendj.util; |
| | | |
| | | |
| | | /** |
| | | * An object which is lazily created when first referenced, and destroyed when |
| | | * the last reference is released. |
| | | * |
| | | * @param <T> |
| | | * The type of referenced object. |
| | | */ |
| | | public abstract class ReferenceCountedObject<T> { |
| | | |
| | | /** |
| | | * A reference to the reference counted object which will automatically be |
| | | * released during garbage collection. |
| | | */ |
| | | public final class Reference { |
| | | /** |
| | | * The value will be accessed by the finalizer thread so it needs to be |
| | | * volatile in order to ensure that updates are published. |
| | | */ |
| | | private volatile T value; |
| | | |
| | | private Reference(final T value) { |
| | | this.value = value; |
| | | } |
| | | |
| | | /** |
| | | * Returns the referenced object. |
| | | * |
| | | * @return The referenced object. |
| | | * @throws NullPointerException |
| | | * If the referenced object has already been released. |
| | | */ |
| | | public T get() { |
| | | if (value == null) { |
| | | throw new NullPointerException(); // Fail-fast. |
| | | } |
| | | return value; |
| | | } |
| | | |
| | | /** |
| | | * Decrements the reference count for the reference counted object if |
| | | * this reference refers to the reference counted instance. If the |
| | | * reference count drops to zero then the referenced object will be |
| | | * destroyed. |
| | | */ |
| | | public void release() { |
| | | T instanceToRelease = null; |
| | | synchronized (lock) { |
| | | if (value != null) { |
| | | if (instance == value && --refCount == 0) { |
| | | // This was the last reference. |
| | | instanceToRelease = value; |
| | | instance = null; |
| | | } |
| | | |
| | | /* |
| | | * Force NPE for subsequent get() attempts and prevent |
| | | * multiple releases. |
| | | */ |
| | | value = null; |
| | | } |
| | | } |
| | | if (instanceToRelease != null) { |
| | | destroyInstance(instanceToRelease); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Provide a finalizer because reference counting is intended for |
| | | * expensive rarely created resources which should not be accidentally |
| | | * left around. |
| | | */ |
| | | @Override |
| | | protected void finalize() { |
| | | release(); |
| | | } |
| | | } |
| | | |
| | | private T instance; |
| | | private final Object lock = new Object(); |
| | | private int refCount; |
| | | |
| | | /** |
| | | * Creates a new referenced object whose reference count is initially zero. |
| | | */ |
| | | protected ReferenceCountedObject() { |
| | | // Nothing to do. |
| | | } |
| | | |
| | | /** |
| | | * Returns a reference to the reference counted object. |
| | | * |
| | | * @return A reference to the reference counted object. |
| | | */ |
| | | public final Reference acquire() { |
| | | synchronized (lock) { |
| | | if (refCount++ == 0) { |
| | | assert instance == null; |
| | | instance = newInstance(); |
| | | } |
| | | assert instance != null; |
| | | return new Reference(instance); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Returns a reference to the provided object or, if it is {@code null}, a |
| | | * reference to the reference counted object. |
| | | * |
| | | * @param value |
| | | * The object to be referenced, or {@code null} if the reference |
| | | * counted object should be used. |
| | | * @return A reference to the provided object or, if it is {@code null}, a |
| | | * reference to the reference counted object. |
| | | */ |
| | | public final Reference acquireIfNull(final T value) { |
| | | return value != null ? new Reference(value) : acquire(); |
| | | } |
| | | |
| | | /** |
| | | * Invoked when a reference is released and the reference count will become |
| | | * zero. Implementations should release any resources associated with the |
| | | * resource and should not return until the resources have been released. |
| | | * |
| | | * @param instance |
| | | * The instance to be destroyed. |
| | | */ |
| | | protected abstract void destroyInstance(T instance); |
| | | |
| | | /** |
| | | * Invoked when a reference is acquired and the current reference count is |
| | | * zero. Implementations should create a new instance as fast as possible. |
| | | * |
| | | * @return The new instance. |
| | | */ |
| | | protected abstract T newInstance(); |
| | | |
| | | } |
| New file |
| | |
| | | /* |
| | | * The contents of this file are subject to the terms of the Common Development and |
| | | * Distribution License (the License). You may not use this file except in compliance with the |
| | | * License. |
| | | * |
| | | * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the |
| | | * specific language governing permission and limitations under the License. |
| | | * |
| | | * When distributing Covered Software, include this CDDL Header Notice in each file and include |
| | | * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL |
| | | * Header, with the fields enclosed by brackets [] replaced by your own identifying |
| | | * information: "Portions Copyright [year] [name of copyright owner]". |
| | | * |
| | | * Copyright 2006-2009 Sun Microsystems, Inc. |
| | | * Portions Copyright 2016 ForgeRock AS. |
| | | */ |
| | | package com.forgerock.opendj.util; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | |
| | | /** An implementation of input stream that enforces an read size limit. */ |
| | | public class SizeLimitInputStream extends InputStream { |
| | | private int bytesRead; |
| | | private int markBytesRead; |
| | | private final int readLimit; |
| | | private final InputStream parentStream; |
| | | |
| | | /** |
| | | * Creates a new a new size limit input stream. |
| | | * |
| | | * @param parentStream |
| | | * The parent stream. |
| | | * @param readLimit |
| | | * The size limit. |
| | | */ |
| | | public SizeLimitInputStream(final InputStream parentStream, final int readLimit) { |
| | | this.parentStream = parentStream; |
| | | this.readLimit = readLimit; |
| | | } |
| | | |
| | | @Override |
| | | public int available() throws IOException { |
| | | final int streamAvail = parentStream.available(); |
| | | final int limitedAvail = readLimit - bytesRead; |
| | | return limitedAvail < streamAvail ? limitedAvail : streamAvail; |
| | | } |
| | | |
| | | @Override |
| | | public void close() throws IOException { |
| | | parentStream.close(); |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the number of bytes read from this stream. |
| | | * |
| | | * @return The number of bytes read from this stream. |
| | | */ |
| | | public int getBytesRead() { |
| | | return bytesRead; |
| | | } |
| | | |
| | | /** |
| | | * Retrieves the size limit of this stream. |
| | | * |
| | | * @return The size limit of this stream. |
| | | */ |
| | | public int getSizeLimit() { |
| | | return readLimit; |
| | | } |
| | | |
| | | @Override |
| | | public synchronized void mark(final int readlimit) { |
| | | parentStream.mark(readlimit); |
| | | markBytesRead = bytesRead; |
| | | } |
| | | |
| | | @Override |
| | | public boolean markSupported() { |
| | | return parentStream.markSupported(); |
| | | } |
| | | |
| | | @Override |
| | | public int read() throws IOException { |
| | | if (bytesRead >= readLimit) { |
| | | return -1; |
| | | } |
| | | |
| | | final int b = parentStream.read(); |
| | | if (b != -1) { |
| | | ++bytesRead; |
| | | } |
| | | return b; |
| | | } |
| | | |
| | | @Override |
| | | public int read(final byte[] b, final int off, int len) throws IOException { |
| | | if (off < 0 || len < 0 || off + len > b.length) { |
| | | throw new IndexOutOfBoundsException(); |
| | | } |
| | | |
| | | if (len == 0) { |
| | | return 0; |
| | | } |
| | | |
| | | if (bytesRead >= readLimit) { |
| | | return -1; |
| | | } |
| | | |
| | | if (bytesRead + len > readLimit) { |
| | | len = readLimit - bytesRead; |
| | | } |
| | | |
| | | final int readLen = parentStream.read(b, off, len); |
| | | if (readLen > 0) { |
| | | bytesRead += readLen; |
| | | } |
| | | return readLen; |
| | | } |
| | | |
| | | @Override |
| | | public synchronized void reset() throws IOException { |
| | | parentStream.reset(); |
| | | bytesRead = markBytesRead; |
| | | } |
| | | |
| | | @Override |
| | | public long skip(long n) throws IOException { |
| | | if (bytesRead + n > readLimit) { |
| | | n = readLimit - bytesRead; |
| | | } |
| | | |
| | | bytesRead += n; |
| | | return parentStream.skip(n); |
| | | } |
| | | } |
| opendj-sdk/opendj-core/src/main/java/com/forgerock/opendj/util/StaticUtils.java
opendj-sdk/opendj-core/src/main/java/com/forgerock/opendj/util/StringPrepProfile.java
opendj-sdk/opendj-core/src/main/java/com/forgerock/opendj/util/SubstringReader.java
opendj-sdk/opendj-core/src/main/java/com/forgerock/opendj/util/package-info.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1ByteSequenceReader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1InputStreamReader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1OutputStreamWriter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1Reader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/ASN1Writer.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/AbstractASN1Reader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/AbstractASN1Writer.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/AbstractLDAPMessageHandler.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/LDAP.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPMessageHandler.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPReader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/LDAPWriter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/io/package-info.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AVA.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AbstractAsynchronousConnection.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AbstractAttribute.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AbstractConnection.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AbstractConnectionWrapper.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AbstractEntry.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AbstractFilterVisitor.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AbstractMapEntry.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AbstractSynchronousConnection.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AddressMask.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Assertion.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AssertionFailureException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Attribute.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AttributeDescription.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AttributeFactory.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AttributeFilter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AttributeParser.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Attributes.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AuthenticationException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/AuthorizationException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Base64.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteSequence.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteSequenceReader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteString.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/CachedConnectionPool.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/CancelRequestListener.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/CancelledResultException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/CommonLDAPOptions.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ConditionResult.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Connection.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ConnectionEventListener.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ConnectionException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ConnectionFactory.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ConnectionLoadBalancer.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ConnectionPool.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ConnectionSecurityLayer.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Connections.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ConstraintViolationException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/DN.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/DecodeException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/DecodeOptions.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/DereferenceAliasesPolicy.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Entries.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Entry.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/EntryFactory.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/EntryNotFoundException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Filter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/FilterVisitor.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Functions.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/GSERParser.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/GeneralizedTime.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/IntermediateResponseHandler.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/InternalConnection.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/InternalConnectionFactory.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/KeyManagers.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LDAPClientContext.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LDAPConnectionFactory.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LDAPListener.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LDAPUrl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LdapException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LdapPromise.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LdapResultHandler.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LinkedAttribute.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LinkedHashMapEntry.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LoadBalancer.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/LoadBalancerEventListener.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Matcher.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/MemoryBackend.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/Modification.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ModificationType.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/MultipleEntriesFoundException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ProviderNotFoundException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/RDN.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ReferralException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/RequestContext.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/RequestHandler.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/RequestHandlerFactory.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/RequestHandlerFactoryAdapter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/RequestLoadBalancer.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ResultCode.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/RootDSE.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/SSLContextBuilder.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/SchemaResolver.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/SearchResultHandler.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/SearchResultReferenceIOException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/SearchScope.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ServerConnection.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/ServerConnectionFactory.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/SortKey.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutChecker.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutEventListener.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/TimeoutResultException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/TreeMapEntry.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/TrustManagers.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ADNotificationRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/AssertionRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/AuthorizationIdentityRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/AuthorizationIdentityResponseControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/Control.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ControlDecoder.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/EntryChangeNotificationResponseControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/GenericControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/GetEffectiveRightsRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ManageDsaITRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/MatchedValuesRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PasswordExpiredResponseControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PasswordExpiringResponseControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PasswordPolicyErrorType.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PasswordPolicyRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PasswordPolicyResponseControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PasswordPolicyWarningType.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PermissiveModifyRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PersistentSearchChangeType.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PersistentSearchRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PostReadRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PostReadResponseControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PreReadRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/PreReadResponseControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ProxiedAuthV1RequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ProxiedAuthV2RequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ServerSideSortRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/ServerSideSortResponseControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/SimplePagedResultsControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/SubentriesRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/SubtreeDeleteRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/VirtualListViewRequestControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/VirtualListViewResponseControl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/controls/package-info.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/package-info.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AbandonRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AbandonRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AbstractBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AbstractExtendedRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AbstractRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AbstractSASLBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AbstractUnmodifiableBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AbstractUnmodifiableExtendedRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AbstractUnmodifiableRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AbstractUnmodifiableSASLBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AddRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AddRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AnonymousSASLBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/AnonymousSASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/BindClient.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/BindClientImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/BindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CancelExtendedRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CancelExtendedRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CompareRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/CompareRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/DeleteRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/DeleteRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ExtendedRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ExtendedRequestDecoder.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GenericBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GenericBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GenericExtendedRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/GenericExtendedRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ModifyDNRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ModifyDNRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ModifyRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/ModifyRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/PasswordModifyExtendedRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/PasswordModifyExtendedRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/Request.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/Requests.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SASLBindClientImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SASLBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SearchRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SearchRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SimpleBindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/SimpleBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/StartTLSExtendedRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/StartTLSExtendedRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnbindRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnbindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableAbandonRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableAddRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableAnonymousSASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableCRAMMD5SASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableCancelExtendedRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableCompareRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableDeleteRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableDigestMD5SASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableExternalSASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableGSSAPISASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableGenericBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableGenericExtendedRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableModifyDNRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableModifyRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiablePasswordModifyExtendedRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiablePlainSASLBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableSearchRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableSimpleBindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableStartTLSExtendedRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableUnbindRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/UnmodifiableWhoAmIExtendedRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/WhoAmIExtendedRequest.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/WhoAmIExtendedRequestImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/requests/package-info.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/AbstractExtendedResult.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/AbstractExtendedResultDecoder.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/AbstractIntermediateResponse.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/AbstractResponseImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/AbstractResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/AbstractUnmodifiableExtendedResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/AbstractUnmodifiableIntermediateResponseImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/AbstractUnmodifiableResponseImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/AbstractUnmodifiableResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/BindResult.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/BindResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/CompareResult.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/CompareResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/ExtendedResult.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/ExtendedResultDecoder.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/GenericExtendedResult.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/GenericExtendedResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/GenericIntermediateResponse.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/GenericIntermediateResponseImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/IntermediateResponse.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/PasswordModifyExtendedResult.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/PasswordModifyExtendedResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/Response.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/Responses.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/Result.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/ResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/SearchResultEntry.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/SearchResultEntryImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/SearchResultReference.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/SearchResultReferenceImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/UnmodifiableBindResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/UnmodifiableCompareResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/UnmodifiableGenericExtendedResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/UnmodifiableGenericIntermediateResponseImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/UnmodifiablePasswordModifyExtendedResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/UnmodifiableResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/UnmodifiableSearchResultEntryImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/UnmodifiableSearchResultReferenceImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/UnmodifiableWhoAmIExtendedResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/WhoAmIExtendedResult.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/WhoAmIExtendedResultImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/responses/package-info.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractApproximateMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractOrderingMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AbstractSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AttributeType.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AttributeTypeSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AttributeUsage.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordExactEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/AuthPasswordSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BinarySyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BitStringEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BitStringSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BooleanEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/BooleanSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5EqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactIA5SubstringMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactOrderingMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseExactSubstringMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5EqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5SubstringMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreListSubstringMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreOrderingMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CaseIgnoreSubstringMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactAssertionSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateListSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificatePairSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CertificateSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CollationMatchingRulesImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ConflictingSchemaElementException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CoreSchema.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CoreSchemaImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CoreSchemaSupportedLocales.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/CountryStringSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRule.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITContentRuleSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITStructureRule.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DITStructureRuleSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DelayedSchema.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DeliveryMethodSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DirectoryStringFirstComponentEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DirectoryStringSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DistinguishedNameSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/DoubleMetaphoneApproximateMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/EnhancedGuideSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/EnumOrderingMatchingRule.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/EnumSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/FacsimileNumberSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/FaxSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeOrderingMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GenerateCoreSchema.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/GuideSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IA5StringSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerFirstComponentEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerOrderingMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/IntegerSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/JPEGSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/KeywordEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/LDAPSyntaxDescriptionSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRule.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleUse.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/MatchingRuleUseSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameAndOptionalUIDSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameForm.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NameFormSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringOrderingMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringSubstringMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/NumericStringSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OIDSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectClass.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectClassSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectClassType.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ObjectIdentifierFirstComponentEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringOrderingMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringSubstringMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OctetStringSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/OtherMailboxSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/PostalAddressSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/PresentationAddressEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/PresentationAddressSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/PrintableStringSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ProtocolInformationEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/ProtocolInformationSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/RegexSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Schema.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaBuilder.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaConstants.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaElement.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaOptions.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaUtils.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SchemaValidationPolicy.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SubstringAssertionSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SupportedAlgorithmSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/Syntax.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/SyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSubstringMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TeletexTerminalIdentifierSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TelexNumberSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/TimeBasedMatchingRulesImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UTCTimeSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UUIDSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UnknownSchemaElementException.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/UserPasswordSyntaxImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/schema/package-info.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/BindResultLdapPromiseImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/ConnectionState.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/ExtendedResultLdapPromiseImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/IndexQueryFactory.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/Indexer.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/IndexingOptions.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPConnectionFactoryImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPConnectionImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LDAPListenerImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LdapPromiseImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LdapPromiseWrapper.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/LdapPromises.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/Provider.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/ResultLdapPromiseImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/SearchResultLdapPromiseImpl.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/TransportProvider.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldap/spi/package-info.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFReader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFStream.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/AbstractLDIFWriter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/ChangeRecord.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/ChangeRecordReader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/ChangeRecordVisitor.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/ChangeRecordVisitorWriter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/ChangeRecordWriter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/ConnectionChangeRecordWriter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/ConnectionEntryReader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/ConnectionEntryWriter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/EntryGenerator.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/EntryReader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/EntryWriter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/LDIF.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordReader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/LDIFChangeRecordWriter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/LDIFEntryReader.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/LDIFEntryWriter.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/RejectedChangeRecordListener.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/RejectedLDIFListener.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateFile.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/TemplateTag.java
opendj-sdk/opendj-core/src/main/java/org/forgerock/opendj/ldif/package-info.java
opendj-sdk/opendj-core/src/main/javadoc/overview.html
opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core.properties
opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core_de.properties
opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core_es.properties
opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core_fr.properties
opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core_ja.properties
opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core_ko.properties
opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core_zh_CN.properties
opendj-sdk/opendj-core/src/main/resources/com/forgerock/opendj/ldap/core_zh_TW.properties
opendj-sdk/opendj-core/src/main/resources/org/forgerock/opendj/ldif/addrate.template
opendj-sdk/opendj-core/src/main/resources/org/forgerock/opendj/ldif/cities
opendj-sdk/opendj-core/src/main/resources/org/forgerock/opendj/ldif/example.template
opendj-sdk/opendj-core/src/main/resources/org/forgerock/opendj/ldif/first.names
opendj-sdk/opendj-core/src/main/resources/org/forgerock/opendj/ldif/last.names
opendj-sdk/opendj-core/src/main/resources/org/forgerock/opendj/ldif/people_and_groups.template
opendj-sdk/opendj-core/src/main/resources/org/forgerock/opendj/ldif/states
opendj-sdk/opendj-core/src/main/resources/org/forgerock/opendj/ldif/streets
opendj-sdk/opendj-core/src/site/xdoc/index.xml.vm
opendj-sdk/opendj-core/src/test/java/com/forgerock/opendj/ldap/controls/AccountUsabilityRequestControlTestCase.java
opendj-sdk/opendj-core/src/test/java/com/forgerock/opendj/ldap/controls/AccountUsabilityResponseControlTestCase.java
opendj-sdk/opendj-core/src/test/java/com/forgerock/opendj/util/ASCIICharPropTestCase.java
opendj-sdk/opendj-core/src/test/java/com/forgerock/opendj/util/OperatingSystemTestCase.java
opendj-sdk/opendj-core/src/test/java/com/forgerock/opendj/util/ReferenceCountedObjectTestCase.java
opendj-sdk/opendj-core/src/test/java/com/forgerock/opendj/util/StaticUtilsTestCase.java
opendj-sdk/opendj-core/src/test/java/com/forgerock/opendj/util/StringPrepProfileTestCase.java
opendj-sdk/opendj-core/src/test/java/com/forgerock/opendj/util/UtilTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/io/ASN1ByteSequenceReaderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/io/ASN1InputStreamReaderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/io/ASN1OutputStreamWriterTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/io/ASN1ReaderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/io/ASN1WriterTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/io/LDAPReaderWriterTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/AVATestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/AbstractAsynchronousConnectionTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/AddressMaskTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/AttributeDescriptionTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/AttributeParserTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/AttributesTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/ByteSequenceReaderTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/ByteSequenceTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/ByteStringBuilderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/ByteStringTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/CompactDnTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/ConditionResultTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/ConnectionPoolTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/ConnectionsTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/DNTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/DataProviderIterator.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/EntriesTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/EntryTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/FilterTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/GSERParserTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/GeneralizedTimeTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/HeartBeatConnectionFactoryTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPServer.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/LDAPUrlTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/LinkedAttributeTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/LoadBalancerTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/MemoryBackendTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/MockConnectionEventListener.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/MockScheduler.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/ModificationTypeTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/PackedLongTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/RDNTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/RequestLoadBalancerTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/ResultCodeTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/SdkTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/SearchScopeTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/TestCaseUtils.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/TestCaseUtilsTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/controls/ControlsTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AbandonRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AddRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/AnonymousSASLBindRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/BindRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CRAMMD5SASLBindRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CancelExtendedRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/CompareRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DeleteRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/DigestMD5SASLBindRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExtendedRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ExternalSASLBindRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GSSAPISASLBindRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericBindRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/GenericExtendedRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyDNRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/ModifyRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PasswordModifyExtendedRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/PlainSASLBindRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/RequestsTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SearchRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/SimpleBindRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/StartTLSExtendedRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/UnbindRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/requests/WhoAmIExtendedRequestTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/responses/ResponsesTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSchemaElementTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSchemaTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSubstringMatchingRuleImplTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AbstractSyntaxTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/ApproximateMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeBuilderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AttributeTypeTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/AuthPasswordSyntaxImplTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/BitStringEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/BitStringSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/BooleanEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/BooleanSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CaseExactEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CaseExactIA5EqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CaseExactIA5SubstringMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CaseExactOrderingMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CaseExactSubstringMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CaseIgnoreEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5EqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CaseIgnoreIA5SubstringMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CaseIgnoreOrderingMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CaseIgnoreSubstringMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CertificateExactMatchingRuleImplTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CertificateSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CollationEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CollationGreaterThanMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CollationGreaterThanOrEqualMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CollationLessThanMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CollationLessThanOrEqualMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CollationSubstringMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CoreSchemaTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/CountryStringSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/DITContentRuleSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/DITContentRuleTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/DITStructureRuleTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/DirectoryStringFirstComponentEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/DistinguishedNameEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/EntrySchemaCheckingTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/EnumSyntaxTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeOrderingMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/GeneralizedTimeSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/GuideSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/IA5StringSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/IntegerEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/IntegerOrderingMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/IntegerSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/JPEGSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/LDAPSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/MatchingRuleSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/MatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/MatchingRuleTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/MatchingRuleUseBuilderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/MatchingRuleUseSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/NameFormTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/NumericStringEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/NumericStringOrderingMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/NumericStringSubstringMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/ObjectClassBuilderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/OrderingMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/OtherMailboxSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/PartialDateAndTimeMatchingRuleTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/PresentationAddressEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/ProtocolInformationEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RegexSyntaxTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeGreaterThanMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/RelativeTimeLessThanMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaBuilderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaCompatTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaOptionsTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SchemaUtilsTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SubstitutionSyntaxTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SubstringMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/SyntaxTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/TelephoneNumberSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/TelexSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/UTCTimeSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/UUIDEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/UUIDOrderingMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/UUIDSyntaxTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/UniqueMemberEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/UserPasswordExactEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/schema/WordEqualityMatchingRuleTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/spi/BasicLDAPConnectionFactory.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/spi/BasicLDAPListener.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/spi/BasicTransportProvider.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/spi/ConnectionStateTest.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldap/spi/LDAPTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/AbstractLDIFTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/ConnectionChangeRecordWriterTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/ConnectionEntryReaderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/ConnectionEntryWriterTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/EntryGeneratorTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordReaderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/LDIFChangeRecordWriterTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/LDIFEntryReaderTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/LDIFEntryWriterTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/LDIFTestCase.java
opendj-sdk/opendj-core/src/test/java/org/forgerock/opendj/ldif/TemplateTagTestcase.java
opendj-sdk/opendj-core/src/test/resources/META-INF/services/org.forgerock.opendj.ldap.spi.TransportProvider
opendj-sdk/opendj-doc-maven-plugin/pom.xml
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/CommandLineTool.java
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateConfigurationReferenceMojo.java
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateGlobalAcisTableMojo.java
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateMessageFileMojo.java
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateRefEntriesMojo.java
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateResultCodeDocMojo.java
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/GenerateSchemaDocMojo.java
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/Utils.java
opendj-sdk/opendj-doc-maven-plugin/src/main/java/org/forgerock/opendj/maven/doc/package-info.java
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/config-ref/duration-syntax.html
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/config-ref/opendj-config.css
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/config-ref/opendj_logo_sm.png
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/config-ref/pageaction.gif
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/config-ref/tab_deselected.jpg
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/config-ref/tab_selected.gif
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/org/forgerock/opendj/maven/doc/docs.properties
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/templates/appendix-ldap-result-codes.ftl
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/templates/log-message-reference.ftl
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/templates/sec-locales-subtypes.ftl
opendj-sdk/opendj-doc-maven-plugin/src/main/resources/templates/table-global-acis.ftl
opendj-sdk/opendj-grizzly/pom.xml
opendj-sdk/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/GrizzlyTransportProvider.java
opendj-sdk/opendj-grizzly/src/main/java/com/forgerock/opendj/grizzly/package-info.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferReader.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ASN1BufferWriter.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/ConnectionSecurityLayerFilter.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/DefaultTCPNIOTransport.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnection.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnectionFactory.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyLDAPListener.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/GrizzlyUtils.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPBaseFilter.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPClientFilter.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/LDAPServerFilter.java
opendj-sdk/opendj-grizzly/src/main/java/org/forgerock/opendj/grizzly/package-info.java
opendj-sdk/opendj-grizzly/src/main/resources/META-INF/services/org.forgerock.opendj.ldap.spi.TransportProvider
opendj-sdk/opendj-grizzly/src/main/resources/com/forgerock/opendj/grizzly/grizzly.properties
opendj-sdk/opendj-grizzly/src/site/xdoc/index.xml.vm
opendj-sdk/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/ASN1BufferReaderTestCase.java
opendj-sdk/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/ASN1BufferWriterTestCase.java
opendj-sdk/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/ConnectionFactoryTestCase.java
opendj-sdk/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/DefaultTCPNIOTransportTestCase.java
opendj-sdk/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnectionFactoryTestCase.java
opendj-sdk/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/GrizzlyLDAPConnectionTestCase.java
opendj-sdk/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/GrizzlyLDAPListenerTestCase.java
opendj-sdk/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/GrizzlyLDAPReaderWriterTestCase.java
opendj-sdk/opendj-grizzly/src/test/java/org/forgerock/opendj/grizzly/GrizzlyUtilsTestCase.java
opendj-sdk/opendj-ldap-sdk-examples/pom.xml
opendj-sdk/opendj-ldap-sdk-examples/src/main/assembly/examples.xml
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Controls.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ExtendedOperations.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetADChangeNotifications.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/GetInfo.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Modify.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ModifyAsync.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ParseAttributes.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/PasswordResetForAD.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Proxy.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ProxyBackend.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ReadSchema.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/RewriterProxy.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SASLAuth.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Search.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchAsync.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBind.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SearchBindAsync.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/Server.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLife.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/ShortLifeAsync.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SimpleAuth.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/SimpleAuthAsync.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UpdateGroup.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UpdateGroupAsync.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseGenericControl.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchema.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/UseSchemaAsync.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/java/org/forgerock/opendj/examples/package-info.java
opendj-sdk/opendj-ldap-sdk-examples/src/main/javadoc/overview.html
opendj-sdk/opendj-ldap-sdk-examples/src/site/xdoc/index.xml.vm
opendj-sdk/opendj-ldap-sdk-examples/src/test/bin/checkRewriterProxy.sh
opendj-sdk/opendj-ldap-toolkit/README
opendj-sdk/opendj-ldap-toolkit/legal-notices/THIRDPARTYREADME.txt
opendj-sdk/opendj-ldap-toolkit/pom.xml
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/addrate.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/authrate.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/ldapcompare.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/ldapmodify.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/ldappasswordmodify.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/ldapsearch.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/ldifdiff.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/ldifmodify.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/ldifsearch.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/makeldif.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/modrate.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bat/searchrate.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/addrate
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/authrate
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/ldapcompare
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/ldapmodify
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/ldappasswordmodify
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/ldapsearch
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/ldifdiff
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/ldifmodify
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/ldifsearch
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/makeldif
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/modrate
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/bin/searchrate
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/descriptor.xml
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/libbat/_client-script.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/libbat/_script-util.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/libbat/setcp.bat
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/libbin/_client-script.sh
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/libbin/_script-util.sh
opendj-sdk/opendj-ldap-toolkit/src/main/assembly/man-pages.xml
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AddRate.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/AuthRate.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/DataSource.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPCompare.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPModify.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPPasswordModify.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDAPSearch.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFDiff.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFModify.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/LDIFSearch.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/MakeLDIF.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/ModRate.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/PerformanceRunner.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/PerformanceRunnerOptions.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/SearchRate.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/StatsThread.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/Utils.java
opendj-sdk/opendj-ldap-toolkit/src/main/java/com/forgerock/opendj/ldap/tools/package-info.java
opendj-sdk/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools.properties
opendj-sdk/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools_ca_ES.properties
opendj-sdk/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools_de.properties
opendj-sdk/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools_es.properties
opendj-sdk/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools_fr.properties
opendj-sdk/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools_ja.properties
opendj-sdk/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools_ko.properties
opendj-sdk/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools_pl.properties
opendj-sdk/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools_zh_CN.properties
opendj-sdk/opendj-ldap-toolkit/src/main/resources/com/forgerock/opendj/ldap/tools/tools_zh_TW.properties
opendj-sdk/opendj-ldap-toolkit/src/site/xdoc/index.xml.vm
opendj-sdk/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/AddRateITCase.java
opendj-sdk/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/AuthRateITCase.java
opendj-sdk/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/ConnectionFactoryProviderTest.java
opendj-sdk/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/LDAPCompareITCase.java
opendj-sdk/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/LDAPSearchITCase.java
opendj-sdk/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/MakeLDIFITCase.java
opendj-sdk/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/ToolsITCase.java
opendj-sdk/opendj-ldap-toolkit/src/test/java/com/forgerock/opendj/ldap/tools/ToolsTestCase.java
opendj-sdk/opendj-ldap-toolkit/src/test/resources/dummy-truststore
opendj-sdk/opendj-ldap-toolkit/src/test/resources/expected_output.ldif
opendj-sdk/opendj-ldap-toolkit/src/test/resources/expected_output_80_column.ldif
opendj-sdk/opendj-ldap-toolkit/src/test/resources/invalid_test_template.ldif
opendj-sdk/opendj-ldap-toolkit/src/test/resources/valid_test_template.ldif
opendj-sdk/opendj-rest2ldap/README
opendj-sdk/opendj-rest2ldap/pom.xml
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AbstractLDAPAttributeMapper.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AttributeMapper.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthenticatedConnectionContext.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthorizationPolicy.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplate.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Config.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/FilterType.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/HttpAuthenticationFilter.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/JSONConstantAttributeMapper.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/LDAPCollectionResourceProvider.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/NameStrategy.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ObjectAttributeMapper.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReadOnUpdatePolicy.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/ReferenceAttributeMapper.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/RequestState.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAP.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Rest2LDAPHttpApplication.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/SimpleAttributeMapper.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/Utils.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/WritabilityPolicy.java
opendj-sdk/opendj-rest2ldap/src/main/java/org/forgerock/opendj/rest2ldap/package-info.java
opendj-sdk/opendj-rest2ldap/src/main/resources/META-INF/services/org.forgerock.http.HttpApplication
opendj-sdk/opendj-rest2ldap/src/site/xdoc/index.xml.vm
opendj-sdk/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/AuthzIdTemplateTest.java
opendj-sdk/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/BasicRequestsTest.java
opendj-sdk/opendj-rest2ldap/src/test/java/org/forgerock/opendj/rest2ldap/TestUtils.java
opendj-sdk/opendj-sdk-bom/pom.xml |