From 9fb13259bb1add404edb5dd42c4d51a69096617e Mon Sep 17 00:00:00 2001
From: Violette Roche-Montane <violette.roche-montane@forgerock.com>
Date: Tue, 04 Feb 2014 14:17:28 +0000
Subject: [PATCH] OPENDJ-1301 - 1306 : Checkpoint commit.

---
 opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ReplicationConfiguration.java  |  248 +++
 opendj-server/src/main/java/org/forgerock/opendj/server/setup/cli/package-info.java                |   29 
 opendj-server/src/test/java/org/forgerock/opendj/server/setup/cli/AbstractSetupCliTestCase.java    |   37 
 opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/AbstractSetupTestCase.java     |   41 
 opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/package-info.java              |   29 
 opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/Model.java                     |  328 +++++
 opendj-server/src/test/java/org/forgerock/opendj/server/setup/cli/SetupCliTestCase.java            |  166 ++
 opendj-server/src/test/java/org/opends/server/types/OperatingSystemTestCase.java                   |   76 +
 opendj-server/pom.xml                                                                              |    7 
 opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/DataConfiguration.java         |  118 +
 opendj-server/src/main/java/org/opends/server/types/NullOutputStream.java                          |  137 ++
 opendj-server/src/main/java/org/forgerock/opendj/server/setup/cli/SetupCli.java                    |  490 +++++++
 opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/DataConfigurationTestCase.java |  127 +
 opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/ListenerSettingsTestCase.java  |  103 +
 opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ListenerSettings.java          |  272 ++++
 opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/RuntimeOptionsTestCase.java    |   97 +
 opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/Certificate.java               |  171 ++
 opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/CertificateTestCase.java       |  131 ++
 opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/ModelTestCase.java             |  430 ++++++
 opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/RuntimeOptions.java            |  186 ++
 opendj-server/src/main/java/org/opends/server/types/package-info.java                              |   30 
 opendj-server/src/main/java/org/opends/server/types/OperatingSystem.java                           |  266 ++++
 opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ModelUtils.java                |  274 ++++
 opendj-server/src/test/java/org/opends/server/types/AbstractTypesTestCase.java                     |   37 
 24 files changed, 3,829 insertions(+), 1 deletions(-)

diff --git a/opendj-server/pom.xml b/opendj-server/pom.xml
index 007710c..395b727 100644
--- a/opendj-server/pom.xml
+++ b/opendj-server/pom.xml
@@ -89,6 +89,11 @@
       <version>${forgerockBuildToolsVersion}</version>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.forgerock.opendj</groupId>
+      <artifactId>opendj-cli</artifactId>
+      <version>${project.version}</version>
+    </dependency>
   </dependencies>
   <build>
     <resources>
@@ -191,7 +196,7 @@
             <link>http://commons.forgerock.org/i18n-framework/i18n-core/apidocs</link>
           </links>
         </configuration>
-      </plugin>
+      </plugin>      
     </plugins>
   </reporting>
 </project>
diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/setup/cli/SetupCli.java b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/cli/SetupCli.java
new file mode 100644
index 0000000..fde8762
--- /dev/null
+++ b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/cli/SetupCli.java
@@ -0,0 +1,490 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.cli;
+
+import static com.forgerock.opendj.cli.Utils.filterExitCode;
+import static com.forgerock.opendj.cli.Utils.LINE_SEPARATOR;
+import static com.forgerock.opendj.cli.CliMessages.*;
+
+import java.io.PrintStream;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.i18n.LocalizableMessageBuilder;
+import org.forgerock.opendj.ldap.ResultCode;
+
+import com.forgerock.opendj.cli.Argument;
+import com.forgerock.opendj.cli.ArgumentException;
+import com.forgerock.opendj.cli.ArgumentParser;
+import com.forgerock.opendj.cli.BooleanArgument;
+import com.forgerock.opendj.cli.CommonArguments;
+import com.forgerock.opendj.cli.ConsoleApplication;
+import com.forgerock.opendj.cli.FileBasedArgument;
+import com.forgerock.opendj.cli.IntegerArgument;
+import com.forgerock.opendj.cli.StringArgument;
+
+/**
+ * This class implements the new CLI for OpenDJ3 setup.
+ */
+public final class SetupCli extends ConsoleApplication {
+
+    ArgumentParser argParser;
+
+    BooleanArgument testOnly;
+    BooleanArgument cli;
+    BooleanArgument addBaseEntry;
+    BooleanArgument skipPortCheck;
+    BooleanArgument enableWindowsService;
+    BooleanArgument doNotStart;
+    BooleanArgument enableStartTLS;
+    BooleanArgument generateSelfSignedCertificate;
+    StringArgument hostName;
+    BooleanArgument usePkcs11;
+    FileBasedArgument directoryManagerPwdFile;
+    FileBasedArgument keyStorePasswordFile;
+    IntegerArgument ldapPort;
+    IntegerArgument adminConnectorPort;
+    IntegerArgument ldapsPort;
+    IntegerArgument jmxPort;
+    IntegerArgument sampleData;
+    StringArgument baseDN;
+    StringArgument importLDIF;
+    StringArgument rejectedImportFile;
+    StringArgument skippedImportFile;
+    StringArgument directoryManagerDN;
+    StringArgument directoryManagerPwdString;
+    StringArgument useJavaKeyStore;
+    StringArgument useJCEKS;
+    StringArgument usePkcs12;
+    StringArgument keyStorePassword;
+    StringArgument certNickname;
+    StringArgument progName;
+    IntegerArgument connectTimeout = null;
+    BooleanArgument acceptLicense;
+
+    // Register the global arguments.
+    BooleanArgument noPrompt;
+    BooleanArgument quietMode;
+    BooleanArgument verbose;
+    StringArgument propertiesFile;
+    BooleanArgument noPropertiesFile;
+    BooleanArgument showUsage;
+
+    private SetupCli() {
+        // Nothing to do.
+    }
+
+    // To allow tests
+    SetupCli(PrintStream out, PrintStream err) {
+        super(out, err);
+    }
+
+    /**
+     * The main method for setup tool.
+     *
+     * @param args
+     *            The command-line arguments provided to this program.
+     */
+    public static void main(final String[] args) {
+        final int retCode = new SetupCli().run(args);
+        System.exit(filterExitCode(retCode));
+    }
+
+    /** Create the command-line argument parser for use with this program. */
+    int run(final String[] args) {
+        try {
+            argParser = new ArgumentParser("Setup", INFO_SETUP_TITLE.get(), true, false, 0, 0, INFO_SETUP_DESCRIPTION
+                    .get().toString());
+
+            initializeArguments();
+
+        } catch (ArgumentException e) {
+            final LocalizableMessage message = ERR_CANNOT_INITIALIZE_ARGS.get(e.getMessage());
+            println(message);
+            return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
+        }
+
+        // Parse the command-line arguments provided to this program.
+        try {
+            argParser.parseArguments(args);
+
+            if (argParser.usageOrVersionDisplayed()) {
+                // If we should just display usage or version information, then print it and exit.
+                return ResultCode.SUCCESS.intValue();
+            }
+        } catch (final ArgumentException e) {
+            final LocalizableMessage message = ERR_ERROR_PARSING_ARGS.get(e.getMessage());
+            println(message);
+            return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
+        }
+
+        // Verifying provided informations.
+        try {
+            final LinkedHashSet<LocalizableMessage> errorMessages = new LinkedHashSet<LocalizableMessage>();
+            checkServerPassword(errorMessages);
+            checkProvidedPorts(errorMessages);
+            checkImportDataArguments(errorMessages);
+            checkSecurityArguments(errorMessages);
+            if (errorMessages.size() > 0) {
+                throw new ArgumentException(ERR_CANNOT_INITIALIZE_ARGS.get(getMessageFromCollection(errorMessages,
+                        LINE_SEPARATOR)));
+            }
+        } catch (final ArgumentException e) {
+            println(e.getMessageObject());
+            return ResultCode.CLIENT_SIDE_PARAM_ERROR.intValue();
+        }
+
+        // Starts setup process.
+
+        return ResultCode.SUCCESS.intValue();
+    }
+
+    private void initializeArguments() throws ArgumentException {
+
+        // Options.
+        acceptLicense = CommonArguments.getAcceptLicense();
+
+        testOnly = CommonArguments.getTestOnly();
+        cli = CommonArguments.getCLI();
+        baseDN = CommonArguments.getBaseDN();
+        addBaseEntry = CommonArguments.getAddBaseEntry();
+        importLDIF = CommonArguments.getImportLDIF();
+        rejectedImportFile = CommonArguments.getRejectedImportLdif();
+        skippedImportFile = CommonArguments.getSkippedImportFile();
+        sampleData = CommonArguments.getSampleData();
+        ldapPort = CommonArguments.getLDAPPort(389); // TODO
+        adminConnectorPort = CommonArguments.getAdminLDAPPort(1444); // TODO
+        jmxPort = CommonArguments.getJMXPort(1444); // TODO
+        skipPortCheck = CommonArguments.getSkipPortCheck();
+        directoryManagerDN = CommonArguments.getRootDN();
+        directoryManagerPwdString = CommonArguments.getRootDNPwd();
+        directoryManagerPwdFile = CommonArguments.getRootDNPwdFile();
+        enableWindowsService = CommonArguments.getEnableWindowsService();
+        doNotStart = CommonArguments.getDoNotStart();
+        enableStartTLS = CommonArguments.getEnableTLS();
+        ldapsPort = CommonArguments.getLDAPSPort(1636); // TODO
+        generateSelfSignedCertificate = CommonArguments.getGenerateSelfSigned();
+        hostName = CommonArguments.getHostName("TODO"); // TODO
+        usePkcs11 = CommonArguments.getUsePKCS11Keystore();
+        useJavaKeyStore = CommonArguments.getUseJavaKeyStore();
+        useJCEKS = CommonArguments.getUseJCEKS();
+        usePkcs12 = CommonArguments.getUsePKCS12KeyStore();
+        keyStorePassword = CommonArguments.getKeyStorePassword();
+        keyStorePasswordFile = CommonArguments.getKeyStorePasswordFile();
+        certNickname = CommonArguments.getCertNickName();
+
+        // Utility Input Output Options.
+        noPrompt = CommonArguments.getNoPrompt();
+        quietMode = CommonArguments.getQuiet();
+        verbose = CommonArguments.getVerbose();
+        propertiesFile = CommonArguments.getPropertiesFileArgument();
+        noPropertiesFile = CommonArguments.getNoPropertiesFileArgument();
+        showUsage = CommonArguments.getShowUsage();
+
+        // Register global arguments.
+        argParser.addArgument(testOnly);
+        argParser.addArgument(cli);
+        argParser.addArgument(baseDN);
+        argParser.addArgument(addBaseEntry);
+        argParser.addArgument(importLDIF);
+        argParser.addArgument(rejectedImportFile);
+        argParser.addArgument(skippedImportFile);
+        argParser.addArgument(sampleData);
+        argParser.addArgument(ldapPort);
+        argParser.addArgument(adminConnectorPort);
+        argParser.addArgument(jmxPort);
+        argParser.addArgument(skipPortCheck);
+        argParser.addArgument(directoryManagerDN);
+        argParser.addArgument(directoryManagerPwdString);
+        argParser.addArgument(directoryManagerPwdFile);
+        argParser.addArgument(enableWindowsService);
+        argParser.addArgument(doNotStart);
+        argParser.addArgument(enableStartTLS);
+        argParser.addArgument(ldapsPort);
+        argParser.addArgument(generateSelfSignedCertificate);
+        argParser.addArgument(hostName);
+        argParser.addArgument(usePkcs11);
+        argParser.addArgument(useJavaKeyStore);
+        argParser.addArgument(useJCEKS);
+        argParser.addArgument(usePkcs12);
+        argParser.addArgument(keyStorePassword);
+        argParser.addArgument(keyStorePasswordFile);
+        argParser.addArgument(certNickname);
+
+        // Register the global arguments.
+        argParser.addArgument(showUsage);
+        argParser.setUsageArgument(showUsage, getOutputStream());
+        argParser.addArgument(noPropertiesFile);
+        argParser.setNoPropertiesFileArgument(noPropertiesFile);
+        argParser.addArgument(propertiesFile);
+        argParser.setFilePropertiesArgument(propertiesFile);
+        argParser.addArgument(quietMode);
+        argParser.addArgument(verbose);
+        argParser.addArgument(noPrompt);
+        argParser.addArgument(acceptLicense);
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isInteractive() {
+        return !noPrompt.isPresent();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isQuiet() {
+        return quietMode.isPresent();
+    }
+
+    /**
+     * Automatically accepts the license if it's present.
+     *
+     * @return {@code true} if license is accepted by default.
+     */
+    private boolean isAcceptLicense() {
+        return acceptLicense.isPresent();
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public boolean isVerbose() {
+        return verbose.isPresent();
+    }
+
+    /**
+     * Returns whether the command was launched in CLI mode or not.
+     *
+     * @return <CODE>true</CODE> if the command was launched to use CLI mode and <CODE>false</CODE> otherwise.
+     */
+    public boolean isCli() {
+        return cli.isPresent();
+    }
+
+    /**
+     * Checks that there are no conflicts with the provided ports (like if the user provided the same port for different
+     * protocols).
+     *
+     * @param errorMessages
+     *            the list of messages to which we add the error messages describing the problems encountered during the
+     *            execution of the checking.
+     */
+    private void checkProvidedPorts(final Collection<LocalizableMessage> errorMessages) {
+        /**
+         * Check that the provided ports do not match.
+         */
+        try {
+            final Set<Integer> ports = new HashSet<Integer>();
+            ports.add(ldapPort.getIntValue());
+
+            if (ports.contains(adminConnectorPort.getIntValue())) {
+                errorMessages.add(ERR_PORT_ALREADY_SPECIFIED.get(adminConnectorPort.getIntValue()));
+            } else {
+                ports.add(adminConnectorPort.getIntValue());
+            }
+
+            if (jmxPort.isPresent()) {
+                if (ports.contains(jmxPort.getIntValue())) {
+                    errorMessages.add(ERR_PORT_ALREADY_SPECIFIED.get(jmxPort.getIntValue()));
+                } else {
+                    ports.add(jmxPort.getIntValue());
+                }
+            }
+            if (ldapsPort.isPresent()) {
+                if (ports.contains(ldapsPort.getIntValue())) {
+                    errorMessages.add(ERR_PORT_ALREADY_SPECIFIED.get(ldapsPort.getIntValue()));
+                } else {
+                    ports.add(ldapsPort.getIntValue());
+                }
+            }
+        } catch (ArgumentException ae) {
+            // TODO log that
+            /*
+             * logger.error(LocalizableMessage.raw("Unexpected error.  " +
+             * "Assuming that it is caused by a previous parsing issue: " + ae, ae));
+             */
+        }
+    }
+
+    /**
+     * Checks that there are no conflicts with the import data arguments.
+     *
+     * @param errorMessages
+     *            the list of messages to which we add the error messages describing the problems encountered during the
+     *            execution of the checking.
+     */
+    private void checkImportDataArguments(final Collection<LocalizableMessage> errorMessages) {
+        // Make sure that the user didn't provide conflicting arguments.
+        if (addBaseEntry.isPresent()) {
+            if (importLDIF.isPresent()) {
+                errorMessages.add(ERR_TOOL_CONFLICTING_ARGS.get(addBaseEntry.getLongIdentifier(),
+                        importLDIF.getLongIdentifier()));
+            } else if (sampleData.isPresent()) {
+                errorMessages.add(ERR_TOOL_CONFLICTING_ARGS.get(addBaseEntry.getLongIdentifier(),
+                        sampleData.getLongIdentifier()));
+            }
+        } else if (importLDIF.isPresent() && sampleData.isPresent()) {
+            errorMessages.add(ERR_TOOL_CONFLICTING_ARGS.get(importLDIF.getLongIdentifier(),
+                    sampleData.getLongIdentifier()));
+        }
+
+        if (rejectedImportFile.isPresent() && addBaseEntry.isPresent()) {
+            errorMessages.add(ERR_TOOL_CONFLICTING_ARGS.get(addBaseEntry.getLongIdentifier(),
+                    rejectedImportFile.getLongIdentifier()));
+        } else if (rejectedImportFile.isPresent() && sampleData.isPresent()) {
+            errorMessages.add(ERR_TOOL_CONFLICTING_ARGS.get(rejectedImportFile.getLongIdentifier(),
+                    sampleData.getLongIdentifier()));
+        }
+
+        if (skippedImportFile.isPresent() && addBaseEntry.isPresent()) {
+            errorMessages.add(ERR_TOOL_CONFLICTING_ARGS.get(addBaseEntry.getLongIdentifier(),
+                    skippedImportFile.getLongIdentifier()));
+        } else if (skippedImportFile.isPresent() && sampleData.isPresent()) {
+            errorMessages.add(ERR_TOOL_CONFLICTING_ARGS.get(skippedImportFile.getLongIdentifier(),
+                    sampleData.getLongIdentifier()));
+        }
+
+        if (noPrompt.isPresent() && !baseDN.isPresent() && baseDN.getDefaultValue() == null) {
+            final Argument[] args = { importLDIF, addBaseEntry, sampleData };
+            for (final Argument arg : args) {
+                if (arg.isPresent()) {
+                    errorMessages.add(ERR_ARGUMENT_NO_BASE_DN_SPECIFIED.get("--" + arg.getLongIdentifier()));
+                }
+            }
+        }
+    }
+
+    /**
+     * Checks that there are no conflicts with the security arguments. If we are in no prompt mode, check that all the
+     * information required has been provided (but not if this information is valid: we do not try to open the keystores
+     * or to check that the LDAPS port is in use).
+     *
+     * @param errorMessages
+     *            the list of messages to which we add the error messages describing the problems encountered during the
+     *            execution of the checking.
+     */
+    private void checkSecurityArguments(final Collection<LocalizableMessage> errorMessages) {
+        final boolean certificateRequired = ldapsPort.isPresent() || enableStartTLS.isPresent();
+
+        int certificateType = 0;
+        if (generateSelfSignedCertificate.isPresent()) {
+            certificateType++;
+        }
+        if (useJavaKeyStore.isPresent()) {
+            certificateType++;
+        }
+        if (useJCEKS.isPresent()) {
+            certificateType++;
+        }
+        if (usePkcs11.isPresent()) {
+            certificateType++;
+        }
+        if (usePkcs12.isPresent()) {
+            certificateType++;
+        }
+
+        if (certificateType > 1) {
+            errorMessages.add(ERR_SEVERAL_CERTIFICATE_TYPE_SPECIFIED.get());
+        }
+
+        if (certificateRequired && noPrompt.isPresent() && (certificateType == 0)) {
+            errorMessages.add(ERR_CERTIFICATE_REQUIRED_FOR_SSL_OR_STARTTLS.get());
+        }
+
+        if (certificateType == 1) {
+            if (!generateSelfSignedCertificate.isPresent()) {
+                // Check that we have only a password.
+                if (keyStorePassword.isPresent() && keyStorePasswordFile.isPresent()) {
+                    LocalizableMessage message = ERR_TWO_CONFLICTING_ARGUMENTS.get(
+                            keyStorePassword.getLongIdentifier(), keyStorePasswordFile.getLongIdentifier());
+                    errorMessages.add(message);
+                }
+
+                // Check that we have one password in no prompt mode.
+                if (noPrompt.isPresent() && !keyStorePassword.isPresent() && !keyStorePasswordFile.isPresent()) {
+                    LocalizableMessage message = ERR_NO_KEYSTORE_PASSWORD.get(keyStorePassword.getLongIdentifier(),
+                            keyStorePasswordFile.getLongIdentifier());
+                    errorMessages.add(message);
+                }
+            }
+            if (noPrompt.isPresent() && !ldapsPort.isPresent() && !enableStartTLS.isPresent()) {
+                LocalizableMessage message = ERR_SSL_OR_STARTTLS_REQUIRED.get(ldapsPort.getLongIdentifier(),
+                        enableStartTLS.getLongIdentifier());
+                errorMessages.add(message);
+            }
+        }
+    }
+
+    /**
+     * Checks that there are no conflicts with the directory manager passwords. If we are in no prompt mode, check that
+     * the password was provided.
+     *
+     * @param errorMessages
+     *            the list of messages to which we add the error messages describing the problems encountered during the
+     *            execution of the checking.
+     */
+    private void checkServerPassword(Collection<LocalizableMessage> errorMessages) {
+        if (directoryManagerPwdString.isPresent() && directoryManagerPwdFile.isPresent()) {
+            errorMessages.add(ERR_TWO_CONFLICTING_ARGUMENTS.get(
+                    directoryManagerPwdString.getLongIdentifier(), directoryManagerPwdFile.getLongIdentifier()));
+        }
+
+        if (noPrompt.isPresent() && !directoryManagerPwdString.isPresent()
+                && !directoryManagerPwdFile.isPresent()) {
+            errorMessages.add(ERR_NO_ROOT_PASSWORD.get(directoryManagerPwdString.getLongIdentifier(),
+                    directoryManagerPwdFile.getLongIdentifier()));
+        }
+    }
+
+
+    /**
+     * This is a helper method that gets a LocalizableMessage representation of the elements in the Collection of
+     * Messages. The LocalizableMessage will display the different elements separated by the separator String.
+     * TODO move this function.
+     * @param col
+     *            the collection containing the messages.
+     * @param separator
+     *            the separator String to be used.
+     * @return the message representation for the collection; LocalizableMessage.EMPTY if null.
+     */
+    private static LocalizableMessage getMessageFromCollection(final Collection<LocalizableMessage> col,
+            final String separator) {
+        if (col == null || col.isEmpty()) {
+            return LocalizableMessage.EMPTY;
+        } else {
+            LocalizableMessageBuilder mb = null;
+            for (final LocalizableMessage m : col) {
+                if (mb == null) {
+                    mb = new LocalizableMessageBuilder(m);
+                } else {
+                    mb.append(separator).append(m);
+                }
+            }
+            return mb.toMessage();
+        }
+    }
+}
diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/setup/cli/package-info.java b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/cli/package-info.java
new file mode 100644
index 0000000..4f63401
--- /dev/null
+++ b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/cli/package-info.java
@@ -0,0 +1,29 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+/**
+ * Contains API for the Opendj3 setup CLI.
+ */
+package org.forgerock.opendj.server.setup.cli;
diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/Certificate.java b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/Certificate.java
new file mode 100644
index 0000000..8e3a05e
--- /dev/null
+++ b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/Certificate.java
@@ -0,0 +1,171 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import java.io.File;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.config.server.ConfigException;
+
+/**
+ * This class is to create a certificate configuration.
+ */
+class Certificate {
+    public enum CertificateType {
+        /**
+         * Self-signed certificate.
+         */
+        SELF_SIGNED,
+        /**
+         * Java KeyStore.
+         */
+        JKS,
+        /**
+         * Java Cryptography Extension.
+         */
+        JCEKS,
+        /**
+         * Public-Key Cryptography Standards 12.
+         */
+        PKCS12,
+        /**
+         * Public-Key Cryptography Standards 11 token.
+         */
+        PKCS11
+    };
+
+    private CertificateType type;
+    private String certNickName;
+    private File keyStoreFile;
+    private String keyStorePin;
+
+    /**
+     * Default constructor.
+     */
+    Certificate() {
+        type = CertificateType.SELF_SIGNED;
+        certNickName = "";
+        keyStorePin = "";
+    }
+
+    /**
+     * Returns the certificate nickname.
+     *
+     * @return The certificate nickname.
+     */
+    public String getCertNickName() {
+        return certNickName;
+    }
+
+    /**
+     * Sets the certificate nickname.
+     *
+     * @param certNickName
+     *            The certificate nickname.
+     */
+    public void setCertNickName(String certNickName) {
+        this.certNickName = certNickName;
+    }
+
+
+    /**
+     * Returns the type of this certificate.
+     *
+     * @return The type of this certificate.
+     */
+    public CertificateType getType() {
+        return type;
+    }
+
+    /**
+     * Sets the type of this certificate.
+     *
+     * @param type
+     *            The type of this certificate (JKS, self-signed...)
+     */
+    public void setType(CertificateType type) {
+        this.type = type;
+    }
+
+    /**
+     * Returns the key store file.
+     *
+     * @return The key store file.
+     */
+    public File getKeyStoreFile() {
+        return keyStoreFile;
+    }
+
+    /**
+     * Sets the key store file.
+     *
+     * @param keyStoreFile
+     *            The key store file.
+     */
+    public void setKeyStoreFile(File keyStoreFile) {
+        this.keyStoreFile = keyStoreFile;
+    }
+
+    /**
+     * Returns the key store PIN.
+     *
+     * @return The key store PIN.
+     */
+    public String getKeyStorePin() {
+        return keyStorePin;
+    }
+
+    /**
+     * Sets the key store PIN.
+     *
+     * @param keyStorePin
+     *            The key store PIN.
+     */
+    public void setKeyStorePin(String keyStorePin) {
+        this.keyStorePin = keyStorePin;
+    }
+
+    /**
+     * Validates the actual configuration for this certificate.
+     *
+     * @throws ConfigException
+     *             If this certificate configuration is invalid.
+     */
+    public void validate() throws ConfigException {
+        if (type == CertificateType.JKS || type == CertificateType.JCEKS || type == CertificateType.PKCS12) {
+            if (keyStoreFile == null || !keyStoreFile.exists()) {
+                throw new ConfigException(LocalizableMessage.raw("Invalid keystore file"));
+            }
+            if (keyStorePin.isEmpty()) {
+                throw new ConfigException(LocalizableMessage.raw("Invalid key pin"));
+            }
+        } else if (type == CertificateType.PKCS11) {
+            if (keyStorePin.isEmpty()) {
+                throw new ConfigException(LocalizableMessage.raw("Invalid key pin"));
+            }
+        }
+    }
+}
diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/DataConfiguration.java b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/DataConfiguration.java
new file mode 100644
index 0000000..8404d57
--- /dev/null
+++ b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/DataConfiguration.java
@@ -0,0 +1,118 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import java.io.File;
+
+class DataConfiguration {
+
+    /**
+     * This enumeration is used to know what kind of data configuration we want to deploy.
+     */
+    public enum Type {
+        /**
+         * Base entry only.
+         */
+        BASE_ENTRY_ONLY,
+        /**
+         * Empty database.
+         */
+        EMPTY_DATABASE,
+        /**
+         * Import LDIF.
+         */
+        IMPORT_LDIF,
+        /**
+         * Automatically generated data entries.
+         */
+        AUTOMATICALLY_GENERATED
+    };
+
+    /** Default name of directory base DN. */
+    static final String DEFAULT_DIRECTORY_BASE_DN = "dc=example,dc=com";
+
+    /** Default value for the generated entries. */
+    static final int IMPORT_ENTRIES_DEFAULT_VALUE = 2000;
+
+    private String directoryBaseDN;
+    private Type type;
+    private File ldifImportDataPath;
+    private int numberOfUserEntries;
+
+    DataConfiguration() {
+        directoryBaseDN = DEFAULT_DIRECTORY_BASE_DN;
+        type = Type.AUTOMATICALLY_GENERATED;
+        numberOfUserEntries = IMPORT_ENTRIES_DEFAULT_VALUE;
+    }
+
+    public String getDirectoryBaseDN() {
+        return directoryBaseDN;
+    }
+
+    public void setDirectoryBaseDN(String directoryBaseDN) {
+        this.directoryBaseDN = directoryBaseDN;
+    }
+
+    public Type getType() {
+        return type;
+    }
+
+    public void setType(Type type) {
+        this.type = type;
+    }
+
+    public boolean isOnlyBaseEntry() {
+        return (type == Type.BASE_ENTRY_ONLY);
+    }
+
+    public boolean isEmptyDatabase() {
+        return (type == Type.EMPTY_DATABASE);
+    }
+
+    public boolean isImportLDIF() {
+        return (type == Type.IMPORT_LDIF);
+    }
+
+    public boolean isAutomaticallyImportGenerated() {
+        return (type == Type.AUTOMATICALLY_GENERATED);
+    }
+
+    public File getLdifImportDataPath() {
+        return ldifImportDataPath;
+    }
+
+    public void setLdifImportDataPath(File ldifImportDataPath) {
+        this.ldifImportDataPath = ldifImportDataPath;
+    }
+
+    public int getNumberOfUserEntries() {
+        return numberOfUserEntries;
+    }
+
+    public void setNumberOfUserEntries(int numberOfUserEntries) {
+        this.numberOfUserEntries = numberOfUserEntries;
+    }
+}
diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ListenerSettings.java b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ListenerSettings.java
new file mode 100644
index 0000000..ebf865f
--- /dev/null
+++ b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ListenerSettings.java
@@ -0,0 +1,272 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+
+import static org.forgerock.util.Utils.closeSilently;
+
+class ListenerSettings {
+
+    /** Default value for incrementing port number. */
+    static final int PORT_INCREMENT = 1000;
+
+    /** Default port number for the LDAP port. */
+    static final int DEFAULT_LDAP_PORT = 389;
+
+    /** Default port number for the LDAPS port. */
+    static final int DEFAULT_LDAPS_PORT = 1636;
+
+    /** Default port number for the administrator port. */
+    static final int DEFAULT_ADMIN_PORT = 1444;
+
+    /** Default port number for the SSL Connection. */
+    static final int DEFAULT_SSL_PORT = 636;
+
+    /** Default port number for the JMX Connection handler. */
+    static final int DEFAULT_JMX_PORT = 1689;
+
+    /** Default port number for the HTTP Connection handler. */
+    static final int DEFAULT_HTTP_PORT = 8080;
+
+    /** Default port number for the SNMP Connection handler. */
+    static final int DEFAULT_SNMP_PORT = 161;
+
+    /** Default name of root user DN. */
+    static final String DEFAULT_ROOT_USER_DN = "cn=Directory Manager";
+
+    private String hostName;
+    private int ldapPort;
+    private int ldapsPort;
+    private int adminPort;
+    private boolean isJMXConnectionHandlerEnbled;
+    private int jmxPort;
+    private boolean isHTTPConnectionHandlerEnabled;
+    private int httpPort;
+    private boolean isSNMPConnectionHandlerEnabled;
+    private int snmpPort;
+    private String rootUserDN;
+    private char[] password;
+    private File passwordFile;
+    private boolean isSSLEnabled;
+    private boolean isTLSEnabled;
+    private int sslPortNumber;
+    private Certificate certificate;
+
+    ListenerSettings() {
+        hostName = "";
+        ldapPort = DEFAULT_LDAP_PORT;
+        ldapsPort = DEFAULT_LDAPS_PORT;
+        adminPort = DEFAULT_ADMIN_PORT;
+        jmxPort = DEFAULT_JMX_PORT;
+        isJMXConnectionHandlerEnbled = false;
+        httpPort = DEFAULT_HTTP_PORT;
+        isHTTPConnectionHandlerEnabled = true;
+        snmpPort = DEFAULT_SNMP_PORT;
+        isSNMPConnectionHandlerEnabled = false;
+        rootUserDN = DEFAULT_ROOT_USER_DN;
+        isSSLEnabled = false;
+        isTLSEnabled = false;
+        sslPortNumber = DEFAULT_SSL_PORT;
+        certificate = null;
+    }
+
+    public String getHostName() {
+        return hostName;
+    }
+
+    public void setHostName(String hostName) {
+        this.hostName = hostName;
+    }
+
+    public int getLdapPort() {
+        return ldapPort;
+    }
+
+    public void setLdapPort(int ldapPort) {
+        this.ldapPort = ldapPort;
+    }
+
+    public int getLdapsPort() {
+        return ldapsPort;
+    }
+
+    public void setLdapsPort(int ldapsPort) {
+        this.ldapsPort = ldapsPort;
+    }
+
+    public int getAdminPort() {
+        return adminPort;
+    }
+
+    public void setAdminPort(int adminPort) {
+        this.adminPort = adminPort;
+    }
+
+    public int getJMXPort() {
+        return jmxPort;
+    }
+
+    public void setJMXPort(int jmxPort) {
+        this.jmxPort = jmxPort;
+    }
+
+    public boolean isJMXConnectionHandlerEnbled() {
+        return isJMXConnectionHandlerEnbled;
+    }
+
+    public void setJMXConnectionHandlerEnbled(boolean isJMXConnectionHandlerEnbled) {
+        this.isJMXConnectionHandlerEnbled = isJMXConnectionHandlerEnbled;
+    }
+
+    public int getHTTPPort() {
+        return httpPort;
+    }
+
+    public void setHTTPPort(int httpPort) {
+        this.httpPort = httpPort;
+    }
+
+    public boolean isHTTPConnectionHandlerEnabled() {
+        return isHTTPConnectionHandlerEnabled;
+    }
+
+    public void setHTTPConnectionHandlerEnabled(boolean isHTTPConnectionHandlerEnabled) {
+        this.isHTTPConnectionHandlerEnabled = isHTTPConnectionHandlerEnabled;
+    }
+
+    public int getSNMPPort() {
+        return snmpPort;
+    }
+
+    public void setSNMPPort(int snmpPort) {
+        this.snmpPort = snmpPort;
+    }
+
+    public boolean isSNMPConnectionHandlerEnabled() {
+        return isSNMPConnectionHandlerEnabled;
+    }
+
+    public void setSNMPConnectionHandlerEnabled(boolean isSNMPConnectionHandlerEnabled) {
+        this.isSNMPConnectionHandlerEnabled = isSNMPConnectionHandlerEnabled;
+    }
+
+    public String getRootUserDN() {
+        return rootUserDN;
+    }
+
+    public void setRootUserDN(String rootUserDN) {
+        this.rootUserDN = rootUserDN;
+    }
+
+    public String getPassword() {
+        if (password == null) {
+            return null;
+        }
+        return String.valueOf(password);
+    }
+
+    public void setPassword(String password) {
+        this.password = password.toCharArray();
+    }
+
+    public File getPasswordFile() {
+        return passwordFile;
+    }
+
+    public void setPasswordFile(File pwdFile) {
+        this.passwordFile = pwdFile;
+    }
+
+    public boolean isSSLEnabled() {
+        return isSSLEnabled;
+    }
+
+    public void setSSLEnabled(boolean isSSLEnabled) {
+        this.isSSLEnabled = isSSLEnabled;
+    }
+
+    public boolean isTLSEnabled() {
+        return isTLSEnabled;
+    }
+
+    public void setTLSEnabled(boolean isTLSEnabled) {
+        this.isTLSEnabled = isTLSEnabled;
+    }
+
+    public int getSSLPortNumber() {
+        return sslPortNumber;
+    }
+
+    public void setSSLPortNumber(int sslPortNumber) {
+        this.sslPortNumber = sslPortNumber;
+    }
+
+    public Certificate getCertificate() {
+        return certificate;
+    }
+
+    public void setCertificate(Certificate certificate) {
+        this.certificate = certificate;
+    }
+
+    static int getFreeSocketPort(int startPortNumber) {
+        return getFreeSocketPort(startPortNumber, new TestPortImpl());
+    }
+
+    private static int getFreeSocketPort(int startPortNumber, TestPort testPort) {
+        int port = startPortNumber;
+        while (port >= 0 && port <= 65535) {
+            try {
+                testPort.canBindToPort(port);
+                return port;
+            } catch (IOException e) {
+                port = port + PORT_INCREMENT;
+            }
+        }
+        throw new IllegalArgumentException("Invalid port.");
+    }
+
+    interface TestPort {
+        void canBindToPort(int portNumber) throws IOException;
+    }
+
+    static class TestPortImpl implements TestPort {
+        public void canBindToPort(int portNumber) throws IOException {
+            ServerSocket socket = null;
+            try {
+                socket = new ServerSocket();
+                socket.setReuseAddress(true);
+                socket.bind(new InetSocketAddress(portNumber));
+            } finally {
+                closeSilently(socket);
+            }
+        }
+    }
+}
diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/Model.java b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/Model.java
new file mode 100644
index 0000000..843b4ff
--- /dev/null
+++ b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/Model.java
@@ -0,0 +1,328 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.util.Reject;
+
+/**
+ * This class provides configuration's model for the OpenDJ3 setup.
+ */
+abstract class Model {
+
+    /**
+     * This enumeration is used to know what kind of server we want to set up.
+     */
+    public enum Type {
+        /**
+         * Stand alone server.
+         */
+        STANDALONE,
+        /**
+         * First server in topology.
+         */
+        FIRST_IN_TOPOLOGY,
+        /**
+         * Replicate the new suffix with existing server.
+         */
+        IN_EXISTING_TOPOLOGY
+    }
+
+    private Type type;
+    private boolean startingServerAfterSetup;
+    private boolean isService;
+    private String instancePath;
+    private String installationPath;
+
+    private String license;
+    private ListenerSettings settings;
+    private RuntimeOptions serverRuntimeSettings;
+    private RuntimeOptions importLdifRuntimeSettings;
+    private DataConfiguration dataConfiguration;
+
+    private ReplicationConfiguration replicationConfiguration = null;
+
+    /**
+     * Returns the listener settings.
+     *
+     * @return The listener settings.
+     */
+    public ListenerSettings getListenerSettings() {
+        return settings;
+    }
+
+    /**
+     * Sets the listener settings.
+     *
+     * @param lSettings
+     *            The listener settings to set.
+     */
+    public void setListenerSettings(final ListenerSettings lSettings) {
+        settings = lSettings;
+    }
+
+    /**
+     * Returns {@code true} if this configuration has a non-empty license.
+     *
+     * @return {@code true} if this configuration has a license.
+     */
+    public boolean hasLicense() {
+        return (this.license != null && !license.isEmpty());
+    }
+
+    /**
+     * Returns {@code true} if this configuration is stand alone data store.
+     *
+     * @return {@code true} if this configuration is stand alone data store.
+     */
+    boolean isStandAlone() {
+        return (type == Type.STANDALONE);
+    }
+
+    /**
+     * Returns {@code true} if this configuration is a first server in a replication topology.
+     *
+     * @return {@code true} if this configuration is a first server in a replication topology.
+     */
+    boolean isFirstInTopology() {
+        return (type == Type.FIRST_IN_TOPOLOGY);
+    }
+
+    /**
+     * Returns {@code true} if this configuration is part of a replication topology.
+     *
+     * @return {@code true} if this configuration is part of a replication topology.
+     */
+    boolean isPartOfReplicationTopology() {
+        return (type == Type.IN_EXISTING_TOPOLOGY);
+    }
+
+    /**
+     * Returns {@code true} if this configuration has a certificate linked to it.
+     * That generally means SSL and/or SSL are activated.
+     *
+     * @return {@code true} if this configuration has a certificate linked to it.
+     */
+    boolean isSecure() {
+        return (this.getListenerSettings() != null
+                && this.getListenerSettings().getCertificate() != null);
+    }
+
+    /**
+     * Sets this configuration as a stand alone data store.
+     */
+    void setStandAloneDS() {
+        setType(Type.STANDALONE);
+    }
+
+    /**
+     * Sets the type of this server as : replication activated
+     * and this is the first server in topology.
+     */
+    void setFirstInTopology() {
+        this.setType(Type.FIRST_IN_TOPOLOGY);
+    }
+
+    /**
+     * Sets the type of this server as : replication activated
+     * and this is a server in an existing topology.
+     */
+    void setInExistingTopology() {
+        this.setType(Type.IN_EXISTING_TOPOLOGY);
+    }
+
+    /**
+     * Returns the type of this configuration.
+     *
+     * @return The type of this configuration.
+     */
+    public Type getType() {
+        return type;
+    }
+
+    /**
+     * Sets the type of this configuration.
+     *
+     * @param mtype
+     *            The type of this configuration (standalone, etc...)
+     */
+    public void setType(Type mtype) {
+        type = mtype;
+    }
+
+    /**
+     * Returns {@code true} if the server must start after the installation.
+     *
+     * @return {@code true} if the server must start after the installation.
+     */
+    public boolean isStartingServerAfterSetup() {
+        return startingServerAfterSetup;
+    }
+
+    /**
+     * Sets if the server should start after its installation.
+     *
+     * @param startServerAfterSetup
+     *            {@code true} if the server must start after the installation.
+     */
+    public void setStartingServerAfterSetup(boolean startServerAfterSetup) {
+        startingServerAfterSetup = startServerAfterSetup;
+    }
+
+    public boolean isService() {
+        return isService;
+    }
+
+    public void setService(boolean isAService) {
+        isService = isAService;
+    }
+
+    public String getInstancePath() {
+        return instancePath;
+    }
+
+    public void setInstancePath(String iPath) {
+        instancePath = iPath;
+    }
+
+    public String getLicense() {
+        return license;
+    }
+
+    public void setLicense(String theLicense) {
+        license = theLicense;
+    }
+
+    public RuntimeOptions getServerRuntimeSettings() {
+        return serverRuntimeSettings;
+    }
+
+    public void setServerRuntimeOptions(RuntimeOptions settings) {
+        serverRuntimeSettings = settings;
+    }
+
+    public RuntimeOptions getImportLdifRuntimeOptions() {
+        return importLdifRuntimeSettings;
+    }
+
+    public void setImportLdifRuntimeOptions(RuntimeOptions settings) {
+        importLdifRuntimeSettings = settings;
+    }
+
+    public DataConfiguration getDataConfiguration() {
+        return dataConfiguration;
+    }
+
+    public void setDataConfiguration(DataConfiguration dConfiguration) {
+        dataConfiguration = dConfiguration;
+    }
+
+    public ReplicationConfiguration getReplicationConfiguration() {
+        return replicationConfiguration;
+    }
+
+    public void setReplicationConfiguration(ReplicationConfiguration replicationConfiguration) {
+        this.replicationConfiguration = replicationConfiguration;
+    }
+
+
+
+    public String getInstallationPath() {
+        return installationPath;
+    }
+
+    public void setInstallationPath(String installationPath) {
+        this.installationPath = installationPath;
+    }
+
+    void checkJavaVersion() throws ConfigException {
+        final String version = System.getProperty("java.specification.version");
+        if (!(Float.valueOf(version) >= 1.6)) {
+            // TODO change exception : original was IncompatibleVersionException
+            throw new ConfigException(LocalizableMessage.raw("invalid java version" + version));
+        }
+    }
+
+    /**
+     * Creates a basic data store model configuration for setup.
+     */
+    static class DataStoreModel extends Model {
+        DataStoreModel() {
+            setStandAloneDS();
+            setDataConfiguration(new DataConfiguration());
+            setListenerSettings(new ListenerSettings());
+            setServerRuntimeOptions(RuntimeOptions.getDefault());
+            setImportLdifRuntimeOptions(RuntimeOptions.getDefault());
+            setStartingServerAfterSetup(true);
+        }
+    }
+
+    /**
+     * Checks the validity of the current setup configuration.
+     *
+     * @throws ConfigException
+     *             If this configuration is invalid.
+     */
+    void validate() throws ConfigException {
+        if (isFirstInTopology() || isPartOfReplicationTopology()) {
+            if (this.getReplicationConfiguration() == null) {
+                throw new ConfigException(LocalizableMessage.raw("No replication configuration found"));
+            }
+            if (isPartOfReplicationTopology()) {
+                Reject.ifNull(this.getReplicationConfiguration().getAdministrator(),
+                        "Administrator name should not be null");
+                Reject.ifNull(this.getReplicationConfiguration().getPassword(),
+                        "Admin password should not be null");
+                Reject.ifNull(this.getReplicationConfiguration().getGlobalAdministrator(),
+                        "Global administrator should not be null");
+                Reject.ifNull(this.getReplicationConfiguration().getGlobalAdministratorPassword(),
+                        "Global administrator should not be null");
+                if (getReplicationConfiguration().getSuffixes() == null
+                        || getReplicationConfiguration().getSuffixes().size() == 0) {
+                    throw new ConfigException(
+                            LocalizableMessage.raw(
+                                    "At least one base DN should be selected to replicate content with"));
+                }
+            }
+        }
+        if (getListenerSettings() == null) {
+            throw new ConfigException(LocalizableMessage.raw("Invalid settings"));
+        }
+        if (getDataConfiguration() == null) {
+            throw new ConfigException(LocalizableMessage.raw("Invalid data configuration"));
+        }
+        if (getDataConfiguration().isImportLDIF()) {
+            if (getDataConfiguration().getLdifImportDataPath() == null) {
+                throw new ConfigException(LocalizableMessage.raw("Invalid import ldif file."));
+            }
+        }
+        if (getListenerSettings().getPasswordFile() == null && getListenerSettings().getPassword() == null) {
+            throw new ConfigException(LocalizableMessage.raw("A password must be set for the root DN."));
+        }
+    }
+
+}
diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ModelUtils.java b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ModelUtils.java
new file mode 100644
index 0000000..dda2697
--- /dev/null
+++ b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ModelUtils.java
@@ -0,0 +1,274 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+
+package org.forgerock.opendj.server.setup.model;
+
+import java.util.ArrayList;
+
+
+/**
+ * This class contains utilities for the OpenDJ3 setup.
+ */
+final class ModelUtils {
+
+    static final String OBFUSCATED_VALUE = "******";
+    /*void original() {
+
+        ArrayList<String> cmdLine = new ArrayList<String>();
+        String setupFile;
+        if (Utils.isWindows())
+        {
+          setupFile = Installation.WINDOWS_SETUP_FILE_NAME;
+        }
+        else
+        {
+          setupFile = Installation.UNIX_SETUP_FILE_NAME;
+        }
+        cmdLine.add(getInstallDir(userData) + setupFile);
+        cmdLine.add("--cli");
+
+        for (String baseDN : getBaseDNs(userData))
+        {
+          cmdLine.add("--baseDN");
+          cmdLine.add(baseDN);
+        }
+
+        switch (userData.getNewSuffixOptions().getType())
+        {
+        case CREATE_BASE_ENTRY:
+          cmdLine.add("--addBaseEntry");
+          break;
+        case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+          cmdLine.add("--sampleData");
+          cmdLine.add(String.valueOf(
+              userData.getNewSuffixOptions().getNumberEntries()));
+          break;
+        case IMPORT_FROM_LDIF_FILE:
+          for (String ldifFile : userData.getNewSuffixOptions().getLDIFPaths())
+          {
+            cmdLine.add("--ldifFile");
+            cmdLine.add(ldifFile);
+          }
+          String rejectFile = userData.getNewSuffixOptions().getRejectedFile();
+          if (rejectFile != null)
+          {
+            cmdLine.add("--rejectFile");
+            cmdLine.add(rejectFile);
+          }
+          String skipFile = userData.getNewSuffixOptions().getSkippedFile();
+          if (skipFile != null)
+          {
+            cmdLine.add("--skipFile");
+            cmdLine.add(skipFile);
+          }
+          break;
+        }
+
+        cmdLine.add("--ldapPort");
+        cmdLine.add(String.valueOf(userData.getServerPort()));
+        cmdLine.add("--adminConnectorPort");
+        cmdLine.add(String.valueOf(userData.getAdminConnectorPort()));
+        if (userData.getServerJMXPort() != -1)
+        {
+          cmdLine.add("--jmxPort");
+          cmdLine.add(String.valueOf(userData.getServerJMXPort()));
+        }
+        cmdLine.add("--rootUserDN");
+        cmdLine.add(userData.getDirectoryManagerDn());
+        cmdLine.add("--rootUserPassword");
+        cmdLine.add(OBFUSCATED_VALUE);
+
+        if (Utils.isWindows() && userData.getEnableWindowsService())
+        {
+          cmdLine.add("--enableWindowsService");
+        }
+        if (userData.getReplicationOptions().getType() ==
+          DataReplicationOptions.Type.STANDALONE &&
+          !userData.getStartServer())
+        {
+          cmdLine.add("--doNotStart");
+        }
+
+        if (userData.getSecurityOptions().getEnableStartTLS())
+        {
+          cmdLine.add("--enableStartTLS");
+        }
+        if (userData.getSecurityOptions().getEnableSSL())
+        {
+          cmdLine.add("--ldapsPort");
+          cmdLine.add(String.valueOf(userData.getSecurityOptions().getSslPort()));
+        }
+        switch (userData.getSecurityOptions().getCertificateType())
+        {
+        case SELF_SIGNED_CERTIFICATE:
+          cmdLine.add("--generateSelfSignedCertificate");
+          cmdLine.add("--hostName");
+          cmdLine.add(userData.getHostName());
+          break;
+        case JKS:
+          cmdLine.add("--useJavaKeystore");
+          cmdLine.add(userData.getSecurityOptions().getKeystorePath());
+          if (userData.getSecurityOptions().getKeystorePassword() != null)
+          {
+            cmdLine.add("--keyStorePassword");
+            cmdLine.add(OBFUSCATED_VALUE);
+          }
+          if (userData.getSecurityOptions().getAliasToUse() != null)
+          {
+            cmdLine.add("--certNickname");
+            cmdLine.add(userData.getSecurityOptions().getAliasToUse());
+          }
+          break;
+        case JCEKS:
+          cmdLine.add("--useJCEKS");
+          cmdLine.add(userData.getSecurityOptions().getKeystorePath());
+          if (userData.getSecurityOptions().getKeystorePassword() != null)
+          {
+            cmdLine.add("--keyStorePassword");
+            cmdLine.add(OBFUSCATED_VALUE);
+          }
+          if (userData.getSecurityOptions().getAliasToUse() != null)
+          {
+            cmdLine.add("--certNickname");
+            cmdLine.add(userData.getSecurityOptions().getAliasToUse());
+          }
+          break;
+        case PKCS12:
+          cmdLine.add("--usePkcs12keyStore");
+          cmdLine.add(userData.getSecurityOptions().getKeystorePath());
+          if (userData.getSecurityOptions().getKeystorePassword() != null)
+          {
+            cmdLine.add("--keyStorePassword");
+            cmdLine.add(OBFUSCATED_VALUE);
+          }
+          if (userData.getSecurityOptions().getAliasToUse() != null)
+          {
+            cmdLine.add("--certNickname");
+            cmdLine.add(userData.getSecurityOptions().getAliasToUse());
+          }
+          break;
+        case PKCS11:
+          cmdLine.add("--usePkcs11Keystore");
+          if (userData.getSecurityOptions().getKeystorePassword() != null)
+          {
+            cmdLine.add("--keyStorePassword");
+            cmdLine.add(OBFUSCATED_VALUE);
+          }
+          if (userData.getSecurityOptions().getAliasToUse() != null)
+          {
+            cmdLine.add("--certNickname");
+            cmdLine.add(userData.getSecurityOptions().getAliasToUse());
+          }
+          break;
+        }
+
+        cmdLine.add("--no-prompt");
+        cmdLine.add("--noPropertiesFile");
+        return cmdLine;
+
+    }*/
+
+    ArrayList<String> getSetupEquivalentCommandLine(final Model configuration) {
+        final ArrayList<String> cmdLines = new ArrayList<String>();
+        final ListenerSettings settings = configuration.getListenerSettings();
+
+        // Starts the server ?
+        if (configuration.getType() == Model.Type.STANDALONE
+                && !configuration.isStartingServerAfterSetup()) {
+            cmdLines.add("--doNotStart");
+        }
+        // Secure ?
+        if (configuration.isSecure()) {
+            if (settings.isTLSEnabled()) {
+                cmdLines.add("--enableStartTLS");
+            }
+            if (settings.isSSLEnabled()) {
+                cmdLines.add("--ldapsPort");
+                cmdLines.add(String.valueOf(settings.getSSLPortNumber()));
+            }
+            // Certificate section.
+            final Certificate certificate = settings.getCertificate();
+
+            switch (certificate.getType()) {
+            case SELF_SIGNED:
+                cmdLines.add("--generateSelfSignedCertificate");
+                cmdLines.add("--hostName");
+                cmdLines.add(settings.getHostName());
+                break;
+            case JKS:
+                cmdLines.add("--useJavaKeystore");
+                cmdLines.add(certificate.getKeyStoreFile().getAbsolutePath());
+                if (certificate.getKeyStorePin() != null) {
+                    cmdLines.add("--keyStorePassword");
+                    cmdLines.add(OBFUSCATED_VALUE);
+                }
+                if (!certificate.getCertNickName().isEmpty()) {
+                    cmdLines.add("--certNickname");
+                    cmdLines.add(certificate.getCertNickName());
+                }
+                break;
+            case JCEKS:
+                cmdLines.add("--useJCEKS");
+                cmdLines.add(certificate.getKeyStoreFile().getAbsolutePath());
+                if (certificate.getKeyStorePin() != null) {
+                    cmdLines.add("--keyStorePassword");
+                    cmdLines.add(OBFUSCATED_VALUE);
+                }
+                if (!certificate.getCertNickName().isEmpty()) {
+                    cmdLines.add("--certNickname");
+                    cmdLines.add(certificate.getCertNickName());
+                }
+                break;
+            case PKCS12:
+                cmdLines.add("--usePkcs12keyStore");
+                cmdLines.add(certificate.getKeyStoreFile().getAbsolutePath());
+                if (certificate.getKeyStorePin() != null) {
+                    cmdLines.add("--keyStorePassword");
+                    cmdLines.add(OBFUSCATED_VALUE);
+                }
+                if (!certificate.getCertNickName().isEmpty()) {
+                    cmdLines.add("--certNickname");
+                    cmdLines.add(certificate.getCertNickName());
+                }
+                break;
+            case PKCS11:
+                cmdLines.add("--usePkcs11Keystore");
+                if (certificate.getKeyStorePin() != null) {
+                    cmdLines.add("--keyStorePassword");
+                    cmdLines.add(OBFUSCATED_VALUE);
+                }
+                if (!certificate.getCertNickName().isEmpty()) {
+                    cmdLines.add("--certNickname");
+                    cmdLines.add(certificate.getCertNickName());
+                }
+                break;
+            }
+        }
+        cmdLines.add("--no-prompt");
+        cmdLines.add("--noPropertiesFile");
+        return cmdLines;
+    }
+}
diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ReplicationConfiguration.java b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ReplicationConfiguration.java
new file mode 100644
index 0000000..e71955a
--- /dev/null
+++ b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/ReplicationConfiguration.java
@@ -0,0 +1,248 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import java.util.List;
+
+/**
+ * This class provides the model of the replication configuration.
+ */
+class ReplicationConfiguration {
+
+    /** Default port number for the replication port. */
+    static final int DEFAULT_REPLICATION_PORT = 389;
+
+    // First in topology
+    private int replicationPort;
+    private boolean isSecure;
+
+    // Part of topology
+    private String hostName;
+    private int hostPort;
+    private String administrator;
+    private char[] password;
+    private List<String> suffixes;
+    private boolean createGlobalAdministrator;
+    private String globalAdministrator;
+    private char[] globalAdministratorPassword;
+
+    ReplicationConfiguration() {
+        replicationPort = DEFAULT_REPLICATION_PORT;
+        isSecure = false;
+        createGlobalAdministrator = false;
+    }
+
+    /**
+     * Returns the replication port.
+     *
+     * @return The replication port.
+     */
+    public int getReplicationPort() {
+        return replicationPort;
+    }
+
+    /**
+     * Sets the port used in replication.
+     *
+     * @param port
+     *            The replication port.
+     */
+    public void setReplicationPort(int port) {
+        replicationPort = port;
+    }
+
+    /**
+     * Returns {@code true} if this connection should be secure.
+     *
+     * @return {@code true} if this is a secure connection.
+     */
+    public boolean isSecure() {
+        return isSecure;
+    }
+
+    /**
+     * Sets this connection to secure if needed.
+     *
+     * @param secure
+     *            {@code true} if the connection needs to be secure.
+     */
+    public void setSecure(boolean secure) {
+        isSecure = secure;
+    }
+
+    /**
+     * Returns the host name.
+     *
+     * @return The host name.
+     */
+    public String getHostName() {
+        return hostName;
+    }
+
+    /**
+     * Sets the host name.
+     *
+     * @param hName
+     *            The host name.
+     */
+    public void setHostName(String hName) {
+        hostName = hName;
+    }
+
+    /**
+     * Returns the host port.
+     *
+     * @return The host port.
+     */
+    public int getHostPort() {
+        return hostPort;
+    }
+
+    /**
+     * Sets the host port.
+     *
+     * @param hPort
+     *            The host port to set.
+     */
+    public void setHostPort(int hPort) {
+        hostPort = hPort;
+    }
+
+    /**
+     * Returns the administrator name.
+     *
+     * @return The administrator name.
+     */
+    public String getAdministrator() {
+        return administrator;
+    }
+
+    /**
+     * Sets the administrator name.
+     *
+     * @param adminName
+     *            The administrator name to set.
+     */
+    public void setAdministrator(String adminName) {
+        administrator = adminName;
+    }
+
+    /**
+     * Returns the password.
+     *
+     * @return The password.
+     */
+    public char[] getPassword() {
+        return password;
+    }
+
+    /**
+     * Sets the password linked to the administrator name.
+     *
+     * @param adminPassword
+     *            The password linked to this administrator name.
+     */
+    public void setPassword(char[] adminPassword) {
+        password = adminPassword;
+    }
+
+    /**
+     * Returns a list of the suffixes.
+     *
+     * @return A list of suffixes.
+     */
+    public List<String> getSuffixes() {
+        return suffixes;
+    }
+
+    /**
+     * Sets the list of the suffixes.
+     *
+     * @param lSuffixes
+     *            The list of the existing suffixes.
+     */
+    public void setSuffixes(List<String> lSuffixes) {
+        suffixes = lSuffixes;
+    }
+
+    /**
+     * Returns the need to create the global administrator.
+     *
+     * @return {@code true} if the global administrator creation is needed.
+     */
+    public boolean isCreateGlobalAdministrator() {
+        return createGlobalAdministrator;
+    }
+
+    /**
+     * Sets the global administrator creation.
+     *
+     * @param createGlobalAdministrator
+     *            {@code true} if the global administrator creation is required.
+     */
+    public void setCreateGlobalAdministrator(boolean createGlobalAdministrator) {
+        this.createGlobalAdministrator = createGlobalAdministrator;
+    }
+
+    /**
+     * Returns the UID of the global administrator.
+     *
+     * @return The UID of the global administrator.
+     */
+    public String getGlobalAdministrator() {
+        return globalAdministrator;
+    }
+
+    /**
+     * Sets the UID of the global administrator.
+     *
+     * @param globalAdministratorUID
+     *            The UID of the global administrator.
+     */
+    public void setGlobalAdministratorUID(String globalAdministratorUID) {
+        this.globalAdministrator = globalAdministratorUID;
+    }
+
+    /**
+     * Returns the password of the global administrator.
+     *
+     * @return The password of the global administrator.
+     */
+    public String getGlobalAdministratorPassword() {
+        return String.valueOf(globalAdministratorPassword);
+    }
+
+    /**
+     * Sets the password of the global administrator.
+     *
+     * @param globalAdministratorPwd
+     *            The password of the global administrator.
+     */
+    public void setGlobalAdministratorPassword(char[] globalAdministratorPwd) {
+        this.globalAdministratorPassword = globalAdministratorPwd;
+    }
+
+}
diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/RuntimeOptions.java b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/RuntimeOptions.java
new file mode 100644
index 0000000..ad7b531
--- /dev/null
+++ b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/RuntimeOptions.java
@@ -0,0 +1,186 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+/**
+ * This class provides the model of the runtime options which can be used
+ * for the server settings or for the import LDIF settings.
+ */
+class RuntimeOptions {
+
+    static final int INITIAL_MEMORY = 128;
+    static final int MAXIMUM_MEMORY = 256;
+
+    private int initialMemory = -1;
+    private int maximumMemory = -1;
+    private String[] additionalArguments = {};
+
+    RuntimeOptions() {
+        // Nothing to do.
+    }
+
+    static RuntimeOptions getDefault() {
+        final RuntimeOptions ro = new RuntimeOptions();
+        ro.initialMemory = 128;
+        ro.maximumMemory = 256;
+        ro.additionalArguments = new String[] { "-client" };
+        return ro;
+    }
+
+    /**
+     * Returns the initial memory allowed to execute the command-line.
+     *
+     * @return the initial memory allowed to execute the command-line.
+     */
+    public int getInitialMemory() {
+        return initialMemory;
+    }
+
+    /**
+     * Sets the initial memory allowed to execute the command-line.
+     *
+     * @param initialMemory
+     *            the initial memory allowed to execute the command-line.
+     */
+    public void setInitialMemory(int initialMemory) {
+        this.initialMemory = initialMemory;
+    }
+
+    /**
+     * Returns the maximum memory allowed to execute the command-line.
+     *
+     * @return the maximum memory allowed to execute the command-line.
+     */
+    public int getMaximumMemory() {
+        return maximumMemory;
+    }
+
+    public void setMaximumMemory(int maximumMemory) {
+        this.maximumMemory = maximumMemory;
+    }
+
+    /**
+     * Returns the additional arguments to be used when executing the command-line.
+     *
+     * @return the additional arguments to be used when executing the command-line.
+     */
+    public String[] getAdditionalArguments() {
+        return additionalArguments;
+    }
+
+    /**
+     * Sets the additional arguments to be used when executing the command-line.
+     *
+     * @param additionalArguments
+     *            the additional arguments to be used when executing the command-line. It cannot be null.
+     */
+    public void setAdditionalArguments(String... additionalArguments) {
+        if (additionalArguments == null) {
+            throw new IllegalArgumentException("additionalArguments cannot be null.");
+        }
+        this.additionalArguments = additionalArguments;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override()
+    public boolean equals(Object o) {
+        boolean equals = o == this;
+        if (!equals) {
+            equals = o instanceof RuntimeOptions;
+            if (equals) {
+                equals = initialMemory == ((RuntimeOptions) o).initialMemory;
+            }
+            if (equals) {
+                equals = maximumMemory == ((RuntimeOptions) o).maximumMemory;
+            }
+            if (equals) {
+                equals = additionalArguments.length == ((RuntimeOptions) o).additionalArguments.length;
+            }
+            if (equals) {
+                String[] args = ((RuntimeOptions) o).additionalArguments;
+                for (int i = 0; i < args.length; i++) {
+                    if (!args[i].equals(additionalArguments[i])) {
+                        equals = false;
+                        break;
+                    }
+                }
+            }
+        }
+        return equals;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override()
+    public int hashCode() {
+        int hashCode = 44 + initialMemory + maximumMemory;
+        for (String arg : additionalArguments) {
+            hashCode += arg.hashCode();
+        }
+        return hashCode;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override()
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("Initial Memory: ").append(initialMemory).append("  Max Memory: ").append(maximumMemory);
+        int i = 1;
+        for (final String arg : additionalArguments) {
+            sb.append(" arg ").append(i).append(": ").append(arg);
+            i++;
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Returns the java argument to specify the initial memory to be used.
+     *
+     * @param value
+     *            the value in megabytes to be specified.
+     * @return the java argument to specify the initial memory to be used.
+     */
+    public static String getInitialMemoryArgument(int value) {
+        return "-Xms" + value + "m";
+    }
+
+    /**
+     * Returns the java argument to specify the maximum memory that can be used.
+     *
+     * @param value
+     *            the value in megabytes to be specified.
+     * @return the java argument to specify the maximum memory that can be used.
+     */
+    public static String getMaxMemoryArgument(int value) {
+        return "-Xmx" + value + "m";
+    }
+
+}
diff --git a/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/package-info.java b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/package-info.java
new file mode 100644
index 0000000..8d1eed9
--- /dev/null
+++ b/opendj-server/src/main/java/org/forgerock/opendj/server/setup/model/package-info.java
@@ -0,0 +1,29 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+/**
+ * Contains API for the Opendj3 setup.
+ */
+package org.forgerock.opendj.server.setup.model;
diff --git a/opendj-server/src/main/java/org/opends/server/types/NullOutputStream.java b/opendj-server/src/main/java/org/opends/server/types/NullOutputStream.java
new file mode 100644
index 0000000..8d7ee37
--- /dev/null
+++ b/opendj-server/src/main/java/org/opends/server/types/NullOutputStream.java
@@ -0,0 +1,137 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2013-2014 ForgeRock AS
+ */
+package org.opends.server.types;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+
+/**
+ * This class defines a custom output stream that simply discards any data written to it.
+ */
+public final class NullOutputStream extends OutputStream {
+    /**
+     * The singleton instance for this class.
+     */
+    private static final NullOutputStream INSTANCE = new NullOutputStream();
+
+    /**
+     * The singleton print stream tied to the null output stream.
+     */
+    private static final PrintStream PRINTSTREAM = new PrintStream(INSTANCE);
+
+    /**
+     * Retrieves an instance of this null output stream.
+     *
+     * @return An instance of this null output stream.
+     */
+    public static NullOutputStream instance() {
+        return INSTANCE;
+    }
+
+    /**
+     * Retrieves a print stream using this null output stream.
+     *
+     * @return A print stream using this null output stream.
+     */
+    public static PrintStream printStream() {
+        return PRINTSTREAM;
+    }
+
+    /**
+     * Returns s wrapped into a {@link PrintStream} if is not null, {@link NullOutputStream#printStream()} otherwise.
+     *
+     * @param s
+     *            the OutputStream to wrap into a {@link PrintStream}. Can be null.
+     * @return a PrintStream wrapping s if not null, {@link NullOutputStream#printStream()} otherwise.
+     */
+    public static PrintStream wrapOrNullStream(OutputStream s) {
+        if (s != null) {
+            return new PrintStream(s);
+        }
+        return NullOutputStream.printStream();
+    }
+
+    /**
+     * Creates a new instance of this null output stream.
+     */
+    private NullOutputStream() {
+        // No implementation is required.
+    }
+
+    /**
+     * Closes the output stream. This has no effect.
+     */
+    @Override
+    public void close() {
+        // No implementation is required.
+    }
+
+    /**
+     * Flushes the output stream. This has no effect.
+     */
+    @Override
+    public void flush() {
+        // No implementation is required.
+    }
+
+    /**
+     * Writes the provided data to this output stream. This has no effect.
+     *
+     * @param b
+     *            The byte array containing the data to be written.
+     */
+    @Override
+    public void write(byte[] b) {
+        // No implementation is required.
+    }
+
+    /**
+     * Writes the provided data to this output stream. This has no effect.
+     *
+     * @param b
+     *            The byte array containing the data to be written.
+     * @param off
+     *            The offset at which the real data begins.
+     * @param len
+     *            The number of bytes to be written.
+     */
+    @Override
+    public void write(byte[] b, int off, int len) {
+        // No implementation is required.
+    }
+
+    /**
+     * Writes the provided byte to this output stream. This has no effect.
+     *
+     * @param b
+     *            The byte to be written.
+     */
+    @Override
+    public void write(int b) {
+        // No implementation is required.
+    }
+}
diff --git a/opendj-server/src/main/java/org/opends/server/types/OperatingSystem.java b/opendj-server/src/main/java/org/opends/server/types/OperatingSystem.java
new file mode 100644
index 0000000..fddf3ca
--- /dev/null
+++ b/opendj-server/src/main/java/org/opends/server/types/OperatingSystem.java
@@ -0,0 +1,266 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2006-2008 Sun Microsystems, Inc.
+ *      Portions Copyright 2014 ForgeRock AS
+ */
+package org.opends.server.types;
+
+/**
+ * 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"),
+
+    /**
+     * The value indicating the FreeBSD operating system.
+     */
+    FREEBSD("FreeBSD"),
+
+    /**
+     * The value indicating the HP-UX operating system.
+     */
+    HPUX("HP-UX"),
+
+    /**
+     * The value indicating the Linux operating system.
+     */
+    LINUX("Linux"),
+
+    /**
+     * The value indicating the Mac OS X operating system.
+     */
+    MACOS("Mac OS X"),
+
+    /**
+     * The value indicating the Solaris operating system.
+     */
+    SOLARIS("Solaris"),
+
+    /**
+     * The value indicating the Windows operating system.
+     */
+    WINDOWS("Windows"),
+
+    /**
+     * The value indicating the z/OS operating system.
+     */
+    ZOS("z/OS"),
+
+    /**
+     * The value indicating an unknown operating system.
+     */
+    UNKNOWN("Unknown");
+
+    // The human-readable name for this operating system.
+    private String osName;
+
+    private static boolean isWindows = false;
+    private static boolean isVista = false;
+    private static boolean isWindows2008 = false;
+    private static boolean isWindows7 = false;
+    private static boolean isMacOS = false;
+    private static boolean isUnix = false;
+    private static boolean isUnixBased = false;
+
+    /**
+     * Creates a new operating system value with the provided name.
+     *
+     * @param osName
+     *            The human-readable name for the operating system.
+     */
+    private OperatingSystem(String osName) {
+        this.osName = osName;
+    }
+
+    /**
+     * Retrieves the human-readable name of this operating system.
+     *
+     * @return The human-readable name for this operating system.
+     */
+    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.indexOf("solaris") >= 0) || (lowerName.indexOf("sunos") >= 0)) {
+            isUnix = true;
+            isUnixBased = true;
+            return SOLARIS;
+        } else if (lowerName.indexOf("linux") >= 0) {
+            isUnix = true;
+            isUnixBased = true;
+            return LINUX;
+        } else if ((lowerName.indexOf("hp-ux") >= 0) || (lowerName.indexOf("hp ux") >= 0)
+                || (lowerName.indexOf("hpux") >= 0)) {
+            isUnix = true;
+            isUnixBased = true;
+            return HPUX;
+        } else if (lowerName.indexOf("aix") >= 0) {
+            isUnix = true;
+            isUnixBased = true;
+            return AIX;
+        } else if (lowerName.indexOf("windows") >= 0) {
+            isWindows = true;
+            if (lowerName.toString().indexOf("windows 7") != -1) {
+                isWindows7 = true;
+            } else if (lowerName.indexOf("vista") != -1) {
+                isVista = true;
+            } else if (lowerName.indexOf("server 2008") != -1) {
+                isWindows2008 = true;
+            }
+            return WINDOWS;
+        } else if ((lowerName.indexOf("freebsd") >= 0) || (lowerName.indexOf("free bsd") >= 0)) {
+            isUnix = true;
+            isUnixBased = true;
+            return FREEBSD;
+        } else if ((lowerName.indexOf("macos") >= 0) || (lowerName.indexOf("mac os") >= 0)) {
+            isMacOS = true;
+            isUnixBased = true;
+            return MACOS;
+        } else if (lowerName.indexOf("z/os") >= 0) {
+            return ZOS;
+        } else {
+            return UNKNOWN;
+        }
+    }
+
+    /**
+     * Indicates whether the provided operating system is UNIX-based. UNIX-based operating systems include Solaris,
+     * Linux, HP-UX, AIX, FreeBSD, and Mac OS X.
+     *
+     * @param os
+     *            The operating system for which to make the determination.
+     * @return <CODE>true</CODE> if the provided operating system is UNIX-based, or <CODE>false</CODE> if not.
+     */
+    public static boolean isUNIXBased(OperatingSystem os) {
+        switch (os) {
+        case SOLARIS:
+        case LINUX:
+        case HPUX:
+        case AIX:
+        case FREEBSD:
+        case MACOS:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    /**
+     * 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 OperatingSystem.forName(System.getProperty("os.name"));
+    }
+
+    /**
+     * 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 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 isVista;
+    }
+
+    /**
+     * 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 isWindows2008;
+    }
+
+    /**
+     * 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 isWindows7;
+    }
+
+    /**
+     * 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 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 isUnix;
+    }
+
+    /**
+     * Returns {@code true} if the OS is Unix based.
+     *
+     * @return {@code true} if the OS is Unix based.
+     */
+    public static boolean isUnixBased() {
+        return isUnixBased;
+    }
+
+    /**
+     * 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();
+    }
+}
diff --git a/opendj-server/src/main/java/org/opends/server/types/package-info.java b/opendj-server/src/main/java/org/opends/server/types/package-info.java
new file mode 100644
index 0000000..9691195
--- /dev/null
+++ b/opendj-server/src/main/java/org/opends/server/types/package-info.java
@@ -0,0 +1,30 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+/**
+ * This package contains certain classes needed by the server module. They are just copied not
+ * svn cp ! Please, move them from the server and then delete them here.
+ */
+package org.opends.server.types;
diff --git a/opendj-server/src/test/java/org/forgerock/opendj/server/setup/cli/AbstractSetupCliTestCase.java b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/cli/AbstractSetupCliTestCase.java
new file mode 100644
index 0000000..0573f55
--- /dev/null
+++ b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/cli/AbstractSetupCliTestCase.java
@@ -0,0 +1,37 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.cli;
+
+import org.forgerock.opendj.ldap.SdkTestCase;
+import org.testng.annotations.Test;
+
+/**
+ * An abstract class that all setup CLI unit tests should extend.
+ */
+@Test(groups = { "precommit", "types", "sdk" })
+public abstract class AbstractSetupCliTestCase extends SdkTestCase {
+
+}
diff --git a/opendj-server/src/test/java/org/forgerock/opendj/server/setup/cli/SetupCliTestCase.java b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/cli/SetupCliTestCase.java
new file mode 100644
index 0000000..b13dd2f
--- /dev/null
+++ b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/cli/SetupCliTestCase.java
@@ -0,0 +1,166 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.cli;
+
+import static com.forgerock.opendj.cli.Utils.MAX_LINE_WIDTH;
+import static com.forgerock.opendj.cli.Utils.wrapText;
+import static com.forgerock.opendj.cli.CliMessages.*;
+import static org.fest.assertions.Assertions.assertThat;
+import static org.forgerock.util.Utils.closeSilently;
+import static org.testng.Assert.assertTrue;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.UnsupportedEncodingException;
+
+import org.forgerock.i18n.LocalizableMessage;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Test;
+
+import com.forgerock.opendj.cli.Utils;
+
+/**
+ * This class tests the setup CLI functionality.
+ */
+public class SetupCliTestCase extends AbstractSetupCliTestCase {
+
+    // @formatter:off
+    @DataProvider(name = "validArguments")
+    Object[][] createValidArguments() throws Exception {
+        Object[][] data = new Object[][] {
+            { args("--help"),
+              expectedErrOutput(LocalizableMessage.raw("Command options:")) }, };
+        return data;
+    }
+
+    @DataProvider(name = "invalidArguments")
+    Object[][] createInValidArguments() throws Exception {
+        Object[][] data = new Object[][] {
+            { args("-c"),
+                expectedErrOutput(
+                        ERR_ERROR_PARSING_ARGS.get(ERR_ARGPARSER_NO_ARGUMENT_WITH_SHORT_ID.get("c"))) },
+            { args("-N"), expectedErrOutput(ERR_ERROR_PARSING_ARGS.get(
+                    ERR_ARGPARSER_NO_VALUE_FOR_ARGUMENT_WITH_SHORT_ID.get("N"))) },
+        };
+        return data;
+    }
+
+    @DataProvider(name = "validPorts")
+    Object[][] createValidPorts() throws Exception {
+        Object[][] data = new Object[][] {
+            { args("--cli", "--doNotStart", "--ldapPort", "1389", "--adminConnectorPort", "4444",
+                    "-D", "cn=Directory Manager", "-w", "password", "-b", "dc=example,dc=com",
+                    "-a"),
+                expectedErrOutput(LocalizableMessage.EMPTY) },
+        };
+        return data;
+    }
+
+    @DataProvider(name = "invalidPorts")
+    Object[][] createInValidPorts() throws Exception {
+        Object[][] data = new Object[][] {
+            { args("--cli", "--doNotStart", "--ldapPort", "1389", "--adminConnectorPort", "4444",
+                    "-D", "cn=Directory Manager", "-w", "password", "-b", "dc=example,dc=com",
+                    "-a", "--jmxPort", "1389"),
+                expectedErrOutput(
+                        ERR_CANNOT_INITIALIZE_ARGS.get(ERR_PORT_ALREADY_SPECIFIED.get("1389"))) },
+            { args("--cli", "--doNotStart", "--ldapPort", "1389", "--adminConnectorPort", "4444",
+                    "-D", "cn=Directory Manager", "-w", "password", "-b", "dc=example,dc=com",
+                    "-a", "--ldapsPort", "1389"),
+                expectedErrOutput(
+                        ERR_CANNOT_INITIALIZE_ARGS.get(ERR_PORT_ALREADY_SPECIFIED.get("1389"))) },
+            { args("--cli", "--doNotStart", "--ldapPort", "70000", "--adminConnectorPort", "4444",
+                    "-D", "cn=Directory Manager", "-w", "password", "-b", "dc=example,dc=com",
+                    "-a"),
+                expectedErrOutput(ERR_ERROR_PARSING_ARGS.get(
+                        ERR_ARGPARSER_VALUE_UNACCEPTABLE_FOR_LONG_ID.get(70000, "ldapPort",
+                        ERR_INTARG_VALUE_ABOVE_UPPER_BOUND.get("ldapPort", 70000, 65535)))) },
+            { args("--cli", "--doNotStart", "--ldapPort", "-1", "--adminConnectorPort", "4444",
+                    "-D", "cn=Directory Manager", "-w", "password", "-b", "dc=example,dc=com",
+                    "-a"),
+                expectedErrOutput(ERR_ERROR_PARSING_ARGS.get(
+                        ERR_ARGPARSER_VALUE_UNACCEPTABLE_FOR_LONG_ID.get(-1, "ldapPort",
+                                ERR_INTARG_VALUE_BELOW_LOWER_BOUND.get("ldapPort", -1, 1)))) },
+        };
+        return data;
+    }
+    // @formatter:on
+
+    /*@Test(dataProvider = "validArguments")
+    public void testRunValidArguments(String[] arguments, LocalizableMessage expectedErrOutput) throws Exception {
+        run(arguments, true, expectedErrOutput);
+    }
+
+    @Test(dataProvider = "invalidArguments")
+    public void testRunInvalidArguments(String[] arguments, LocalizableMessage expectedErrOutput) throws Exception {
+        run(arguments, false, expectedErrOutput);
+    }*/
+
+    @Test(dataProvider = "invalidPorts")
+    public void testcheckProvidedPorts(String[] arguments, LocalizableMessage expectedErrOutput) throws Exception {
+        run(arguments, false, expectedErrOutput);
+    }
+
+    private void run(String[] arguments, boolean expectsResults, LocalizableMessage expectedErrOutput)
+            throws UnsupportedEncodingException {
+        PrintStream outStream = null;
+        PrintStream errStream = null;
+        try {
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            outStream = new PrintStream(out);
+            ByteArrayOutputStream err = new ByteArrayOutputStream();
+            errStream = new PrintStream(err);
+
+            final SetupCli setup = new SetupCli(outStream, errStream);
+            setup.run(arguments);
+
+            if (expectsResults) {
+                assertThat(out.size()).isGreaterThan(0);
+                assertThat(out.toString("UTF-8")).contains(wrapText(expectedErrOutput, MAX_LINE_WIDTH));
+            } else {
+                assertThat(out.size()).isEqualTo(0);
+                assertThat(err.size()).isGreaterThan(0);
+                final String errorMsg = err.toString("UTF-8").replaceAll(Utils.LINE_SEPARATOR, " ");
+                final String expectedMsg = expectedErrOutput.toString().replaceAll(Utils.LINE_SEPARATOR, " ");
+                assertTrue(errorMsg.contains(expectedMsg), errorMsg + "\n >---< \n" + expectedMsg);
+            }
+
+        } finally {
+            closeSilently(outStream, errStream);
+        }
+    }
+
+    /** Arguments passed to the command */
+    private String[] args(String... arguments) {
+        return arguments;
+    }
+
+    /** A message the error output is expected to contain. */
+    private LocalizableMessage expectedErrOutput(LocalizableMessage val) {
+        return val;
+    }
+
+}
diff --git a/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/AbstractSetupTestCase.java b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/AbstractSetupTestCase.java
new file mode 100644
index 0000000..93cad86
--- /dev/null
+++ b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/AbstractSetupTestCase.java
@@ -0,0 +1,41 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import org.forgerock.opendj.ldap.SdkTestCase;
+import org.testng.annotations.Test;
+
+/**
+ * An abstract class that all setup unit tests should extend.
+ */
+@Test(groups = { "precommit", "types", "sdk" })
+public abstract class AbstractSetupTestCase extends SdkTestCase {
+
+}
+
+
+
+
diff --git a/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/CertificateTestCase.java b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/CertificateTestCase.java
new file mode 100644
index 0000000..e180b77
--- /dev/null
+++ b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/CertificateTestCase.java
@@ -0,0 +1,131 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import static org.fest.assertions.Assertions.assertThat;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.server.setup.model.Certificate.CertificateType;
+import org.testng.annotations.Test;
+
+public class CertificateTestCase extends AbstractSetupTestCase {
+
+    /**
+     * Default is a self-signed certificate.
+     */
+    @Test()
+    public void testGetDefault() {
+        final Certificate cert = new Certificate();
+        assertThat(cert.getType()).isEqualTo(CertificateType.SELF_SIGNED);
+        assertThat(cert.getKeyStoreFile()).isNull();
+        assertThat(cert.getKeyStorePin()).isEmpty();
+    }
+
+    @Test()
+    public void testValidateDefaultCertificate() throws ConfigException {
+        final Certificate cert = new Certificate();
+        cert.validate();
+    }
+
+    /**
+     * Certificates which are not self-signed should fail when no key store is provided.
+     *
+     * @throws ConfigException
+     */
+    @Test(expectedExceptions = ConfigException.class)
+    public void testValidateCertificateFailsWhenNoKeystoreProvided() throws ConfigException {
+        final Certificate cert = new Certificate();
+        cert.setType(CertificateType.JKS);
+        cert.validate();
+    }
+
+    /**
+     * Certificates which are not self-signed should fail when no key store is provided.
+     *
+     * @throws ConfigException
+     */
+    @Test(expectedExceptions = ConfigException.class)
+    public void testValidatePKCS11CertificateFailsWhenNoKeyPinProvided() throws ConfigException {
+        final Certificate cert = new Certificate();
+        cert.setType(CertificateType.PKCS11);
+        cert.validate();
+    }
+
+    /**
+     * Certificates which are not self-signed should fail when no key pin is provided.
+     *
+     * @throws ConfigException
+     *             Occurs if this configuration is invalid.
+     * @throws IOException
+     *             If an exception occurs when creating the keystore.
+     */
+    @Test(expectedExceptions = ConfigException.class)
+    public void testValidateCertificateFailsWhenNoKeyPinProvided() throws ConfigException, IOException {
+        final Certificate cert = new Certificate();
+        cert.setType(CertificateType.JKS);
+        File keystore = null;
+        try {
+            keystore = File.createTempFile("keystore", ".keystore");
+            cert.setKeyStoreFile(keystore);
+            cert.validate();
+        } catch (IOException e) {
+            throw e;
+        } finally {
+            if (keystore != null) {
+                keystore.delete();
+            }
+        }
+    }
+
+    /**
+     * Builds a new JKS certificate.
+     *
+     * @throws ConfigException
+     *             Occurs if this configuration is invalid.
+     * @throws IOException
+     *             If an exception occurs when creating the temp keystore.
+     */
+    @Test()
+    public void testValidateJKSCertificate() throws ConfigException, IOException {
+        final Certificate cert = new Certificate();
+        cert.setType(CertificateType.JKS);
+        File keystore = null;
+        try {
+            keystore = File.createTempFile("keystore", ".keystore");
+            cert.setKeyStoreFile(keystore);
+            cert.setKeyStorePin("key pin");
+            cert.validate();
+        } finally {
+            if (keystore != null) {
+                keystore.delete();
+            }
+        }
+    }
+
+}
diff --git a/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/DataConfigurationTestCase.java b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/DataConfigurationTestCase.java
new file mode 100644
index 0000000..b0b4e80
--- /dev/null
+++ b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/DataConfigurationTestCase.java
@@ -0,0 +1,127 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.forgerock.opendj.server.setup.model.DataConfiguration.Type;
+import org.testng.annotations.Test;
+
+/**
+ * This class tests the data store functionality.
+ */
+public class DataConfigurationTestCase extends AbstractSetupTestCase {
+
+    /**
+     * Creates a default data configuration.
+     */
+    @Test()
+    public void testGetDefaultDataConfiguration() {
+        final DataConfiguration data = new DataConfiguration();
+        assertThat(data.getDirectoryBaseDN()).isEqualTo(DataConfiguration.DEFAULT_DIRECTORY_BASE_DN);
+        assertFalse(data.isEmptyDatabase());
+        assertFalse(data.isImportLDIF());
+        assertFalse(data.isOnlyBaseEntry());
+        assertTrue(data.isAutomaticallyImportGenerated());
+
+        assertThat(data.getLdifImportDataPath()).isNull();
+        assertThat(data.getNumberOfUserEntries()).isEqualTo(DataConfiguration.IMPORT_ENTRIES_DEFAULT_VALUE);
+    }
+
+    /**
+     * Creates a custom data configuration.
+     *
+     * @throws IOException
+     */
+    @Test()
+    public void testCustomDataConfiguration() throws IOException {
+        final DataConfiguration data = new DataConfiguration();
+        final int userEntries = 300;
+        data.setNumberOfUserEntries(userEntries);
+        assertThat(data.getNumberOfUserEntries()).isEqualTo(userEntries);
+        assertTrue(data.isAutomaticallyImportGenerated());
+        assertFalse(data.isImportLDIF());
+        assertFalse(data.isEmptyDatabase());
+        assertFalse(data.isOnlyBaseEntry());
+        // Set another config
+        data.setType(Type.IMPORT_LDIF);
+        File importLdifFile = null;
+        try {
+            importLdifFile = File.createTempFile("import_ldif_file", ".ldif");
+            data.setLdifImportDataPath(importLdifFile);
+            assertTrue(data.isImportLDIF());
+            assertThat(data.getLdifImportDataPath().exists());
+            // Return to previous config.
+            data.setType(Type.AUTOMATICALLY_GENERATED);
+            assertThat(data.getNumberOfUserEntries()).isEqualTo(userEntries);
+            assertTrue(data.isAutomaticallyImportGenerated());
+            assertFalse(data.isImportLDIF());
+        } finally {
+            if (importLdifFile != null) {
+                importLdifFile.delete();
+            }
+        }
+    }
+
+    /**
+     * Tests the type of the data configuration to make sure the boolean types are correctly assigned.
+     */
+    @Test()
+    public void testDataConfigurationType() {
+        final DataConfiguration data = new DataConfiguration();
+        assertTrue(data.isAutomaticallyImportGenerated());
+        assertFalse(data.isImportLDIF());
+        assertFalse(data.isEmptyDatabase());
+        assertFalse(data.isOnlyBaseEntry());
+        assertThat(data.getType() == Type.AUTOMATICALLY_GENERATED);
+        // Import LDIF
+        data.setType(Type.IMPORT_LDIF);
+        assertTrue(data.isImportLDIF());
+        assertFalse(data.isAutomaticallyImportGenerated());
+        assertFalse(data.isEmptyDatabase());
+        assertFalse(data.isOnlyBaseEntry());
+        assertThat(data.getType() == Type.IMPORT_LDIF);
+        // Empty database
+        data.setType(Type.EMPTY_DATABASE);
+        assertFalse(data.isAutomaticallyImportGenerated());
+        assertFalse(data.isImportLDIF());
+        assertTrue(data.isEmptyDatabase());
+        assertFalse(data.isOnlyBaseEntry());
+        assertThat(data.getType() == Type.EMPTY_DATABASE);
+        // Only base entry
+        data.setType(Type.BASE_ENTRY_ONLY);
+        assertTrue(data.isOnlyBaseEntry());
+        assertFalse(data.isAutomaticallyImportGenerated());
+        assertFalse(data.isImportLDIF());
+        assertFalse(data.isEmptyDatabase());
+        assertThat(data.getType() == Type.BASE_ENTRY_ONLY);
+    }
+}
diff --git a/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/ListenerSettingsTestCase.java b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/ListenerSettingsTestCase.java
new file mode 100644
index 0000000..b50ad3d
--- /dev/null
+++ b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/ListenerSettingsTestCase.java
@@ -0,0 +1,103 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import org.forgerock.opendj.ldap.TestCaseUtils;
+import org.testng.annotations.Test;
+
+public class ListenerSettingsTestCase extends AbstractSetupTestCase {
+
+    /**
+     * Retrieves default settings.
+     */
+    @Test()
+    public void testGetDefault() {
+        final ListenerSettings dsSettings = new ListenerSettings();
+        assertThat(dsSettings.getAdminPort()).isEqualTo(ListenerSettings.DEFAULT_ADMIN_PORT);
+        assertThat(dsSettings.getHTTPPort()).isEqualTo(ListenerSettings.DEFAULT_HTTP_PORT);
+        assertThat(dsSettings.getJMXPort()).isEqualTo(ListenerSettings.DEFAULT_JMX_PORT);
+        assertThat(dsSettings.getLdapPort()).isEqualTo(ListenerSettings.DEFAULT_LDAP_PORT);
+        assertThat(dsSettings.getLdapsPort()).isEqualTo(ListenerSettings.DEFAULT_LDAPS_PORT);
+        assertThat(dsSettings.getSNMPPort()).isEqualTo(ListenerSettings.DEFAULT_SNMP_PORT);
+        assertThat(dsSettings.getSSLPortNumber()).isEqualTo(ListenerSettings.DEFAULT_SSL_PORT);
+
+        assertThat(dsSettings.getHostName()).isEmpty();
+        assertThat(dsSettings.getRootUserDN()).isEqualTo(ListenerSettings.DEFAULT_ROOT_USER_DN);
+        assertThat(dsSettings.getPassword()).isNull();
+        assertFalse(dsSettings.isSSLEnabled());
+        assertThat(dsSettings.getCertificate()).isNull();
+        assertFalse(dsSettings.isTLSEnabled());
+        assertFalse(dsSettings.isJMXConnectionHandlerEnbled());
+        assertFalse(dsSettings.isSNMPConnectionHandlerEnabled());
+        assertTrue(dsSettings.isHTTPConnectionHandlerEnabled());
+    }
+
+    /**
+     * Tries to retrieve a free port number.
+     *
+     * @throws Exception
+     */
+    @Test()
+    public void testGetFreePort() throws Exception {
+        // Finds a free socket
+        final InetSocketAddress isa = TestCaseUtils.findFreeSocketAddress();
+        // Bound the free socket
+        final int port = isa.getPort();
+        final ServerSocket boundSocket = new ServerSocket(port);
+        // Verify the new port number is different from the free socket and verify it's free.
+        final int newPort = ListenerSettings.getFreeSocketPort(port);
+        assertThat(newPort).isNotEqualTo(port);
+        assertThat(newPort).isEqualTo(port + ListenerSettings.PORT_INCREMENT);
+        boundSocket.close();
+    }
+
+    /**
+     * Port number is invalid when inferior to 0 or superior to 65535.
+     *
+     * @throws Exception
+     */
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testInvalidPort() throws Exception {
+        ListenerSettings.getFreeSocketPort(65536);
+    }
+
+    /**
+     * Port number is invalid when inferior to 0 or superior to 65535.
+     *
+     * @throws Exception
+     */
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testInvalidNegativePort() throws Exception {
+        ListenerSettings.getFreeSocketPort(-1);
+    }
+}
diff --git a/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/ModelTestCase.java b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/ModelTestCase.java
new file mode 100644
index 0000000..649b612
--- /dev/null
+++ b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/ModelTestCase.java
@@ -0,0 +1,430 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.LinkedList;
+
+import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.server.setup.model.Certificate.CertificateType;
+import org.forgerock.opendj.server.setup.model.Model.DataStoreModel;
+import org.forgerock.opendj.server.setup.model.Model.Type;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * This class tests the model functionality.
+ */
+public class ModelTestCase extends AbstractSetupTestCase {
+
+    /**
+     * Generates a model and verifies if the configuration is valid.
+     *
+     * @throws ConfigException
+     */
+    @Test()
+    public void testCreateDefaultDS() throws ConfigException {
+        final Model ds = new DataStoreModel();
+
+        Assert.assertTrue(ds.isStandAlone());
+
+        final ListenerSettings dsSettings = ds.getListenerSettings();
+
+        // Verify connection handler by default
+        assertTrue(dsSettings.isHTTPConnectionHandlerEnabled());
+        assertFalse(dsSettings.isSSLEnabled());
+        assertFalse(dsSettings.isTLSEnabled());
+        assertFalse(dsSettings.isJMXConnectionHandlerEnbled());
+        ds.getListenerSettings().setPassword("password");
+
+        // Verify ports
+        assertThat(dsSettings.getAdminPort()).isEqualTo(ListenerSettings.DEFAULT_ADMIN_PORT);
+        assertThat(dsSettings.getHTTPPort()).isEqualTo(ListenerSettings.DEFAULT_HTTP_PORT);
+        assertThat(dsSettings.getJMXPort()).isEqualTo(ListenerSettings.DEFAULT_JMX_PORT);
+        assertThat(dsSettings.getLdapPort()).isEqualTo(ListenerSettings.DEFAULT_LDAP_PORT);
+        assertThat(dsSettings.getLdapsPort()).isEqualTo(ListenerSettings.DEFAULT_LDAPS_PORT);
+        assertThat(dsSettings.getSNMPPort()).isEqualTo(ListenerSettings.DEFAULT_SNMP_PORT);
+        assertThat(dsSettings.getSSLPortNumber()).isEqualTo(ListenerSettings.DEFAULT_SSL_PORT);
+
+        assertFalse(ds.isService());
+        assertTrue(ds.isStartingServerAfterSetup());
+        assertFalse(ds.isPartOfReplicationTopology());
+        assertTrue(ds.isStartingServerAfterSetup());
+
+        assertThat(ds.getDataConfiguration()).isNotNull();
+        assertThat(ds.getServerRuntimeSettings()).isEqualTo(RuntimeOptions.getDefault());
+        assertFalse(ds.hasLicense());
+
+        assertThat(ds.getType()).isEqualTo(Type.STANDALONE);
+        assertFalse(ds.isSecure());
+
+        ds.validate();
+
+    }
+
+    /**
+     * Configure a DS with null listener settings should fail.
+     *
+     * @throws ConfigException
+     *             If this configuration is invalid.
+     */
+    @Test(expectedExceptions = ConfigException.class,
+            expectedExceptionsMessageRegExp = "Invalid settings")
+    public void testIsValidDSDoesNotAllowNullListenerSettings() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        ds.setListenerSettings(null);
+        ds.validate();
+    }
+
+    /**
+     * Configure a DS with null data configuration should fail.
+     *
+     * @throws ConfigException
+     *             If this configuration is invalid.
+     */
+    @Test(expectedExceptions = ConfigException.class,
+            expectedExceptionsMessageRegExp = "Invalid data configuration")
+    public void testIsValidDSDoesNotAllowNullDataConfiguration() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        ds.setDataConfiguration(null);
+        ds.validate();
+    }
+
+    /**
+     * Configure a DS - import LDIF data with no path configured for the import LDIF.
+     *
+     * @throws ConfigException
+     *             If this configuration is invalid.
+     */
+    @Test(expectedExceptions = ConfigException.class,
+            expectedExceptionsMessageRegExp = "Invalid import ldif file.")
+    public void testIsValidDSImportLDIFDoesNotAllowNullImportLDIFPath() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        ds.getDataConfiguration().setType(DataConfiguration.Type.IMPORT_LDIF);
+
+        ds.validate();
+    }
+
+    /**
+     * Configure a DS - A password must be set for the root DN (password or password file).
+     *
+     * @throws ConfigException
+     *             If this configuration is invalid.
+     */
+    @Test(expectedExceptions = ConfigException.class,
+            expectedExceptionsMessageRegExp = "A password must be set for the root DN.")
+    public void testIsValidDSDoesNotAllowNullPassword() throws ConfigException {
+        final Model ds = new DataStoreModel();
+
+        ds.validate();
+    }
+
+    /**
+     * Configure a DS - A password must be set for the root DN (password or password file).
+     *
+     * @throws ConfigException
+     *             If this configuration is invalid.
+     */
+    @Test(expectedExceptions = ConfigException.class,
+            expectedExceptionsMessageRegExp = "A password must be set for the root DN.")
+    public void testIsValidDSDoesNotAllowNullPasswordFile() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        ds.getListenerSettings().setPasswordFile(null);
+        ds.validate();
+    }
+
+    /**
+     * Configure a DS - A password must be set for the root DN (password or password file).
+     *
+     * @throws ConfigException
+     *             If this configuration is invalid.
+     * @throws IOException
+     *             If an error occurred when the temporary file is created.
+     */
+    @Test()
+    public void testIsValidDSAllowsPasswordFile() throws ConfigException, IOException {
+        final Model ds = new DataStoreModel();
+        File passwordFile = null;
+
+        try {
+            passwordFile = File.createTempFile("passwordFile", ".pwd");
+            ds.getListenerSettings().setPasswordFile(passwordFile);
+        } catch (IOException e) {
+            throw e;
+        } finally {
+            if (passwordFile != null) {
+                passwordFile.delete();
+            }
+        }
+
+        ds.validate();
+    }
+
+    @Test()
+    public void testCreateDSAllowsNullCertificate() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        ds.getListenerSettings().setCertificate(null);
+        assertFalse(ds.isSecure());
+    }
+
+    @Test()
+    public void testCreateSecureDS() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        final Certificate cert = new Certificate();
+        cert.setType(CertificateType.SELF_SIGNED);
+        ds.getListenerSettings().setCertificate(cert);
+
+        assertTrue(ds.isSecure());
+    }
+
+
+    /**
+     * Configure a DS - replication enabled with null replication configuration should fail.
+     *
+     * @throws ConfigException
+     *             If this configuration is invalid.
+     */
+    @Test(expectedExceptions = ConfigException.class,
+            expectedExceptionsMessageRegExp = "No replication configuration found")
+    public void testCreateDSFirstInTopologyDoesNotAllowEmptyReplicationConfiguration() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        ds.setType(Type.FIRST_IN_TOPOLOGY);
+        assertTrue(ds.isFirstInTopology());
+        assertThat(ds.getReplicationConfiguration()).isNull();
+
+        ds.validate();
+    }
+
+    /**
+     * The replication configuration doesn't set a valid administrator name.
+     *
+     * @throws NullPointerException
+     *             If the administrator's name is null.
+     */
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testCreateDefaultDSExistingTopologyDoesNotAllowNullAdministrator() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        ReplicationConfiguration rConfig = new ReplicationConfiguration();
+        ds.setReplicationConfiguration(rConfig);
+        ds.setType(Type.IN_EXISTING_TOPOLOGY);
+        assertTrue(ds.isPartOfReplicationTopology());
+        assertThat(ds.getReplicationConfiguration()).isNotNull();
+
+        ds.validate();
+    }
+
+    /**
+     * The replication configuration doesn't allow null password.
+     *
+     * @throws NullPointerException
+     *             If the password is null.
+     */
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testCreateDefaultDSExistingTopologyDoesNotAllowNullPassword() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        final ReplicationConfiguration rConfig = new ReplicationConfiguration();
+        rConfig.setAdministrator("admin");
+
+        ds.setReplicationConfiguration(rConfig);
+        ds.setInExistingTopology();
+        assertTrue(ds.isPartOfReplicationTopology());
+        assertThat(ds.getReplicationConfiguration()).isNotNull();
+
+        ds.validate();
+    }
+
+
+    /**
+     * The replication configuration doesn't set a valid administrator name.
+     *
+     * @throws NullPointerException
+     *             If the administrator's name is null.
+     */
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testCreateDefaultDSExistingTopologyDoesNotAllowNullGlobalAdministrator() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        ReplicationConfiguration rConfig = new ReplicationConfiguration();
+        rConfig.setAdministrator("admin");
+        rConfig.setPassword("password".toCharArray());
+        ds.setReplicationConfiguration(rConfig);
+        ds.setType(Type.IN_EXISTING_TOPOLOGY);
+        assertTrue(ds.isPartOfReplicationTopology());
+        assertThat(ds.getReplicationConfiguration()).isNotNull();
+
+        ds.validate();
+    }
+
+    /**
+     * The replication configuration doesn't allow null password for the global administrator.
+     *
+     * @throws NullPointerException
+     *             If the password is null.
+     */
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testCreateDefaultDSExistingTopologyDoesNotAllowNullPasswordForGlobalAdministrator()
+            throws ConfigException {
+        final Model ds = new DataStoreModel();
+        final ReplicationConfiguration rConfig = new ReplicationConfiguration();
+        rConfig.setAdministrator("admin");
+        rConfig.setPassword("password".toCharArray());
+        rConfig.setGlobalAdministratorUID("GlobalAdmin");
+        ds.setReplicationConfiguration(rConfig);
+        ds.setInExistingTopology();
+        assertTrue(ds.isPartOfReplicationTopology());
+        assertThat(ds.getReplicationConfiguration()).isNotNull();
+
+        ds.validate();
+    }
+
+    /**
+     * The replication configuration doesn't allow null suffixes.
+     *
+     * @throws ConfigException
+     *             If the password is null.
+     */
+    @Test(expectedExceptions = ConfigException.class)
+    public void testCreateDefaultDSExistingTopologyDoesNotAllowNullSuffixes() throws ConfigException {
+        final Model ds = new DataStoreModel();
+
+        final ReplicationConfiguration rConfig = new ReplicationConfiguration();
+        rConfig.setAdministrator("admin");
+        rConfig.setPassword("password".toCharArray());
+        rConfig.setGlobalAdministratorUID("GlobalAdmin");
+        rConfig.setGlobalAdministratorPassword("password2".toCharArray());
+
+        ds.setReplicationConfiguration(rConfig);
+        ds.setInExistingTopology();
+        assertTrue(ds.isPartOfReplicationTopology());
+        assertThat(ds.getReplicationConfiguration()).isNotNull();
+
+        ds.validate();
+    }
+
+    /**
+     * The replication configuration doesn't allow empty suffixes.
+     *
+     * @throws ConfigException
+     *             If the password is null.
+     */
+    @Test(expectedExceptions = ConfigException.class)
+    public void testCreateDefaultDSExistingTopologyDoesNotAllowEmptySuffixes() throws ConfigException {
+        final Model ds = new DataStoreModel();
+
+        final ReplicationConfiguration rConfig = new ReplicationConfiguration();
+        rConfig.setAdministrator("admin");
+        rConfig.setPassword("password".toCharArray());
+
+        rConfig.setGlobalAdministratorUID("GlobalAdmin");
+        rConfig.setGlobalAdministratorPassword("password2".toCharArray());
+        rConfig.setSuffixes(new LinkedList<String>());
+
+        ds.setReplicationConfiguration(rConfig);
+        ds.setInExistingTopology();
+        assertTrue(ds.isPartOfReplicationTopology());
+        assertThat(ds.getReplicationConfiguration()).isNotNull();
+
+        ds.validate();
+    }
+
+    /**
+     * Creates a valid first DS in topology.
+     *
+     * @throws ConfigException
+     *             If a configuration exception occurs.
+     */
+    @Test()
+    public void testCreateDSFirstInTopology() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        ds.getListenerSettings().setPassword("password");
+        ds.setFirstInTopology();
+        assertTrue(ds.isFirstInTopology());
+        assertThat(ds.getReplicationConfiguration()).isNull();
+
+        // Sets the replication configuration
+        final ReplicationConfiguration rconf = new ReplicationConfiguration();
+        rconf.setAdministrator("admin");
+        rconf.setPassword("password".toCharArray());
+        ds.setReplicationConfiguration(rconf);
+
+        assertThat(ds.getReplicationConfiguration().getReplicationPort()).isEqualTo(
+                ReplicationConfiguration.DEFAULT_REPLICATION_PORT);
+        assertFalse(ds.getReplicationConfiguration().isSecure());
+
+        ds.validate();
+    }
+
+    /**
+     * Demonstrates how to set the license for a DS.
+     *
+     * @throws ConfigException
+     *             If a configuration exception occurs.
+     */
+    @Test()
+    public void testCreateDefaultDSWithLicense() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        final String license = "This is a CDDL License";
+        ds.setLicense(license);
+        ds.getListenerSettings().setPassword("password");
+        assertTrue(ds.hasLicense());
+        ds.validate();
+    }
+
+    /**
+     * Performs security checks.
+     *
+     * @throws ConfigException
+     *             If a configuration exception occurs.
+     */
+    @Test()
+    public void testCheckJavaVersion() throws ConfigException {
+        final Model ds = new DataStoreModel();
+        ds.checkJavaVersion();
+    }
+
+    /**
+     * Performs security checks. In this case, java version is invalid.
+     *
+     * @throws ConfigException
+     *             If a configuration exception occurs.
+     */
+    @Test(expectedExceptions = Exception.class)
+    public void testInvalidJavaVersion() throws Exception {
+        final Model ds = new DataStoreModel();
+        final String original = System.getProperty("java.specification.version");
+        System.setProperty("java.specification.version", "1.5");
+        try {
+            ds.checkJavaVersion();
+        } finally {
+            System.setProperty("java.specification.version", original);
+        }
+
+    }
+}
diff --git a/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/RuntimeOptionsTestCase.java b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/RuntimeOptionsTestCase.java
new file mode 100644
index 0000000..fae17a5
--- /dev/null
+++ b/opendj-server/src/test/java/org/forgerock/opendj/server/setup/model/RuntimeOptionsTestCase.java
@@ -0,0 +1,97 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.forgerock.opendj.server.setup.model;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.forgerock.opendj.server.setup.model.RuntimeOptions.INITIAL_MEMORY;
+import static org.forgerock.opendj.server.setup.model.RuntimeOptions.MAXIMUM_MEMORY;
+
+import org.testng.annotations.Test;
+
+/**
+ * This class contains some tests to demonstrate the use of the runtime options in the setup.
+ */
+public class RuntimeOptionsTestCase  extends AbstractSetupTestCase {
+
+    @Test()
+    public void testGetDefault() {
+        final RuntimeOptions options = RuntimeOptions.getDefault();
+        assertThat(options.getInitialMemory()).isEqualTo(INITIAL_MEMORY);
+        assertThat(options.getMaximumMemory()).isEqualTo(MAXIMUM_MEMORY);
+        assertThat(options.getAdditionalArguments()).contains("-client");
+    }
+
+    @Test(expectedExceptions = IllegalArgumentException.class)
+    public void testRuntimeOptionsDoesNotAllowNullAdditionalArguments() {
+        final RuntimeOptions options = new RuntimeOptions();
+        options.setInitialMemory(INITIAL_MEMORY);
+        options.setMaximumMemory(MAXIMUM_MEMORY);
+        options.setAdditionalArguments((String[]) null);
+    }
+
+    @Test()
+    public void testEqualitySucceed() {
+        final RuntimeOptions options = RuntimeOptions.getDefault();
+        assertThat(options.getInitialMemory()).isEqualTo(INITIAL_MEMORY);
+        assertThat(options.getMaximumMemory()).isEqualTo(MAXIMUM_MEMORY);
+        assertThat(options.getAdditionalArguments()).contains("-client");
+
+        final RuntimeOptions options2 = new RuntimeOptions();
+        options2.setInitialMemory(INITIAL_MEMORY);
+        options2.setMaximumMemory(MAXIMUM_MEMORY);
+        options2.setAdditionalArguments(new String[] { "-client" });
+
+        assertThat(options).isEqualTo(options2);
+    }
+
+    @Test()
+    public void testEqualityFails() {
+        final RuntimeOptions options = RuntimeOptions.getDefault();
+        assertThat(options.getInitialMemory()).isEqualTo(INITIAL_MEMORY);
+        assertThat(options.getMaximumMemory()).isEqualTo(MAXIMUM_MEMORY);
+        assertThat(options.getAdditionalArguments()).contains("-client");
+
+        final RuntimeOptions options2 = new RuntimeOptions();
+        options2.setInitialMemory(INITIAL_MEMORY);
+        options2.setMaximumMemory(MAXIMUM_MEMORY);
+        options2.setAdditionalArguments(new String[] { "" });
+
+        assertThat(options).isNotEqualTo(options2);
+    }
+
+    @Test()
+    public void testRuntimeOptionsToString() {
+
+        final RuntimeOptions options = new RuntimeOptions();
+        options.setInitialMemory(INITIAL_MEMORY);
+        options.setMaximumMemory(MAXIMUM_MEMORY);
+        options.setAdditionalArguments(new String[] { "-client" });
+
+        assertThat(options.toString()).contains(String.valueOf(INITIAL_MEMORY));
+        assertThat(options.toString()).contains(String.valueOf(MAXIMUM_MEMORY));
+        assertThat(options.toString()).contains("-client");
+    }
+}
diff --git a/opendj-server/src/test/java/org/opends/server/types/AbstractTypesTestCase.java b/opendj-server/src/test/java/org/opends/server/types/AbstractTypesTestCase.java
new file mode 100644
index 0000000..926cb1f
--- /dev/null
+++ b/opendj-server/src/test/java/org/opends/server/types/AbstractTypesTestCase.java
@@ -0,0 +1,37 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.opends.server.types;
+
+import org.forgerock.opendj.ldap.SdkTestCase;
+import org.testng.annotations.Test;
+
+/**
+ * An abstract class that all setup unit tests should extend.
+ */
+@Test(groups = { "precommit", "types", "sdk" })
+public abstract class AbstractTypesTestCase extends SdkTestCase {
+
+}
diff --git a/opendj-server/src/test/java/org/opends/server/types/OperatingSystemTestCase.java b/opendj-server/src/test/java/org/opends/server/types/OperatingSystemTestCase.java
new file mode 100644
index 0000000..bbc8de7
--- /dev/null
+++ b/opendj-server/src/test/java/org/opends/server/types/OperatingSystemTestCase.java
@@ -0,0 +1,76 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt
+ * or http://forgerock.org/license/CDDLv1.0.html.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at legal-notices/CDDLv1_0.txt.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2014 ForgeRock AS.
+ */
+package org.opends.server.types;
+
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+import org.testng.annotations.Test;
+
+/**
+ * This class tests the model functionality.
+ */
+public class OperatingSystemTestCase extends AbstractTypesTestCase {
+
+    @Test()
+    public void testGetOperatingSystem() {
+        final OperatingSystem os = OperatingSystem.getOperatingSystem();
+        if (os.toString().toLowerCase().indexOf("windows") != -1) {
+            assertTrue(OperatingSystem.isWindows());
+            if (os.toString().toLowerCase().indexOf("windows 7") != -1) {
+                assertTrue(OperatingSystem.isWindows7());
+                assertFalse(OperatingSystem.isVista());
+                assertFalse(OperatingSystem.isWindows2008());
+            } else if (os.toString().toLowerCase().indexOf("vista") != -1) {
+                assertTrue(OperatingSystem.isVista());
+                assertFalse(OperatingSystem.isWindows7());
+                assertFalse(OperatingSystem.isWindows2008());
+            } else if (os.toString().toLowerCase().indexOf("server 2008") != -1) {
+                assertTrue(OperatingSystem.isWindows2008());
+                assertFalse(OperatingSystem.isWindows7());
+                assertFalse(OperatingSystem.isVista());
+            }
+            assertFalse(OperatingSystem.isMacOS());
+            assertFalse(OperatingSystem.isUnix());
+            assertFalse(OperatingSystem.isUnixBased());
+
+        } else if (os.toString().toLowerCase().indexOf("solaris") != -1
+                || os.toString().toLowerCase().indexOf("linux") != -1
+                || os.toString().toLowerCase().indexOf("hp-ux") != -1
+                || os.toString().toLowerCase().indexOf("hpux") != -1
+                || os.toString().toLowerCase().indexOf("aix") != -1
+                || os.toString().toLowerCase().indexOf("freebsd") != -1) {
+            assertTrue(OperatingSystem.isUnix());
+            assertFalse(OperatingSystem.isMacOS());
+            assertFalse(OperatingSystem.isWindows());
+            assertTrue(OperatingSystem.isUnixBased());
+        } else if (os.toString().toLowerCase().indexOf("macos") != -1) {
+            assertTrue(OperatingSystem.isMacOS());
+            assertFalse(OperatingSystem.isUnix());
+            assertTrue(OperatingSystem.isUnixBased());
+        }
+
+    }
+}

--
Gitblit v1.10.0