All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.fcrepo.utilities.install.InstallOptions Maven / Gradle / Ivy

There is a newer version: 3.8.1
Show newest version
/* The contents of this file are subject to the license and copyright terms
 * detailed in the license directory at the root of the source tree (also
 * available online at http://fedora-commons.org/license/).
 */
package org.fcrepo.utilities.install;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

public class InstallOptions {

    public static final String INSTALL_TYPE = "install.type";

    public static final String FEDORA_HOME = "fedora.home";

    public static final String FEDORA_SERVERHOST = "fedora.serverHost";

    public static final String FEDORA_APP_SERVER_CONTEXT = "fedora.serverContext";

    public static final String APIA_AUTH_REQUIRED = "apia.auth.required";

    public static final String UPSTREAM_AUTH_ENABLED = "upstream.auth.enabled";
    
    public static final String SSL_AVAILABLE = "ssl.available";

    public static final String APIA_SSL_REQUIRED = "apia.ssl.required";

    public static final String APIM_SSL_REQUIRED = "apim.ssl.required";

    public static final String SERVLET_ENGINE = "servlet.engine";

    public static final String TOMCAT_HOME = "tomcat.home";

    public static final String FEDORA_ADMIN_PASS = "fedora.admin.pass";

    public static final String TOMCAT_SHUTDOWN_PORT = "tomcat.shutdown.port";

    public static final String TOMCAT_HTTP_PORT = "tomcat.http.port";

    public static final String TOMCAT_SSL_PORT = "tomcat.ssl.port";

    public static final String KEYSTORE_FILE = "keystore.file";

    public static final String KEYSTORE_PASSWORD = "keystore.password";

    public static final String KEYSTORE_TYPE = "keystore.type";

    public static final String DATABASE = "database";

    public static final String DATABASE_DRIVER = "database.driver";

    public static final String DATABASE_JDBCURL = "database.jdbcURL";

    public static final String DATABASE_DRIVERCLASS =
            "database.jdbcDriverClass";

    public static final String EMBEDDED_DATABASE_DRIVERCLASSNAME =
            "org.apache.derby.jdbc.EmbeddedDriver";

    public static final String DATABASE_USERNAME = "database.username";

    public static final String DATABASE_PASSWORD = "database.password";

    public static final String XACML_ENABLED = "xacml.enabled";

    public static final String FESL_AUTHN_ENABLED = "fesl.authn.enabled";

    public static final String FESL_AUTHZ_ENABLED = "fesl.authz.enabled";

    public static final String LLSTORE_TYPE = "llstore.type";

    public static final String RI_ENABLED = "ri.enabled";

    public static final String MESSAGING_ENABLED = "messaging.enabled";

    public static final String MESSAGING_URI = "messaging.uri";

    public static final String DEPLOY_LOCAL_SERVICES = "deploy.local.services";

    public static final String TEST_SPRING_CONFIGS = "test.spring.configs";

    public static final String UNATTENDED = "unattended";

    public static final String DATABASE_UPDATE = "database.update";

    public static final String DEFAULT = "default";

    public static final String INSTALL_QUICK = "quick";

    public static final String INSTALL_CLIENT = "client";

    public static final String INCLUDED = "included";

    public static final String DERBY = "derby";

    public static final String MYSQL = "mysql";

    public static final String ORACLE = "oracle";

    public static final String POSTGRESQL = "postgresql";

    public static final String OTHER = "other";

    public static final String EXISTING_TOMCAT = "existingTomcat";

    private final Map _map;

    private final Distribution _dist;

    /**
     * Initialize options from the given map of String values, keyed by option
     * id.
     */
    public InstallOptions(Distribution dist, Map map)
            throws OptionValidationException {
        _dist = dist;
        _map = map;

        applyDefaults();
        validateAll();
    }

    /**
     * Initialize options interactively, via input from the console.
     */
    public InstallOptions(Distribution dist)
            throws InstallationCancelledException {
        _dist = dist;
        _map = new HashMap();

        System.out.println();
        System.out.println("***********************");
        System.out.println("  Fedora Installation ");
        System.out.println("***********************");
        checkJavaVersion();
        System.out.println();
        System.out.println("To install Fedora, please answer the following questions.");
        System.out.println("Enter CANCEL at any time to abort the installation.");
        System.out.println("Detailed installation instructions are available online:\n");
        System.out.println("            https://wiki.duraspace.org/display/FEDORA/All+Documentation\n");

        inputOption(INSTALL_TYPE);
        inputOption(FEDORA_HOME);

        if (getValue(INSTALL_TYPE).equals(INSTALL_CLIENT)) {
            return;
        }

        inputOption(FEDORA_ADMIN_PASS);

        String fedoraHome =
                new File(getValue(InstallOptions.FEDORA_HOME))
                        .getAbsolutePath();
        String includedJDBCURL =
                "jdbc:derby:" + fedoraHome + File.separator
                        + "derby/fedora3;create=true";

        if (getValue(INSTALL_TYPE).equals(INSTALL_QUICK)) {
            // See the defaultValues defined in OptionDefinition.properties
            // for the null values below
            _map.put(FEDORA_SERVERHOST, null); // localhost
            _map.put(FEDORA_APP_SERVER_CONTEXT, null);
            _map.put(APIA_AUTH_REQUIRED, null); // false
            _map.put(SSL_AVAILABLE, Boolean.toString(false));
            _map.put(APIM_SSL_REQUIRED, Boolean.toString(false));
            _map.put(SERVLET_ENGINE, null); // included
            _map.put(TOMCAT_HOME, fedoraHome + File.separator + "tomcat");
            _map.put(TOMCAT_HTTP_PORT, null); // 8080
            _map.put(TOMCAT_SHUTDOWN_PORT, null); // 8005
            _map.put(DATABASE, INCLUDED);
            _map.put(DATABASE_DRIVER, INCLUDED);
            _map.put(DATABASE_USERNAME, "fedoraAdmin");
            _map.put(DATABASE_PASSWORD, "fedoraAdmin");
            _map.put(DATABASE_JDBCURL, includedJDBCURL);
            _map.put(DATABASE_DRIVERCLASS, EMBEDDED_DATABASE_DRIVERCLASSNAME);
            _map.put(XACML_ENABLED, Boolean.toString(false));
            _map.put(UPSTREAM_AUTH_ENABLED, Boolean.toString(false));
            _map.put(FESL_AUTHN_ENABLED, Boolean.toString(true));
            _map.put(FESL_AUTHZ_ENABLED, Boolean.toString(false));
            _map.put(LLSTORE_TYPE, null); // akubra-fs
            _map.put(RI_ENABLED, null); // false
            _map.put(MESSAGING_ENABLED, null); // false
            _map.put(DEPLOY_LOCAL_SERVICES, null); // true
            applyDefaults();
            return;
        }

        inputOption(FEDORA_SERVERHOST);
        inputOption(FEDORA_APP_SERVER_CONTEXT);
        inputOption(APIA_AUTH_REQUIRED);
        inputOption(SSL_AVAILABLE);

        boolean sslAvailable = getBooleanValue(SSL_AVAILABLE, true);
        if (sslAvailable) {
            inputOption(APIA_SSL_REQUIRED);
            inputOption(APIM_SSL_REQUIRED);
        }
        inputOption(SERVLET_ENGINE);
        if (!getValue(SERVLET_ENGINE).equals(OTHER)) {
            inputOption(TOMCAT_HOME);
            inputOption(TOMCAT_HTTP_PORT);
            inputOption(TOMCAT_SHUTDOWN_PORT);
            if (sslAvailable) {
                inputOption(TOMCAT_SSL_PORT);
                if (getValue(SERVLET_ENGINE).equals(INCLUDED)
                        || getValue(SERVLET_ENGINE).equals(EXISTING_TOMCAT)) {
                    inputOption(KEYSTORE_FILE);
                    if (!getValue(KEYSTORE_FILE).equals(INCLUDED)) {
                        inputOption(KEYSTORE_PASSWORD);
                        inputOption(KEYSTORE_TYPE);
                    }
                }
            }
        }

        // Database selection
        // Ultimately we want to provide the following properties:
        //   database, database.username, database.password,
        //   database.driver, database.jdbcURL, database.jdbcDriverClass
        inputOption(DATABASE);

        String db = DATABASE + "." + getValue(DATABASE);

        // The following lets us use the database-specific OptionDefinition.properties
        // for the user prompts and defaults
        String driver = db + ".driver";
        String jdbcURL = db + ".jdbcURL";
        String jdbcDriverClass = db + ".jdbcDriverClass";

        if (getValue(DATABASE).equals(INCLUDED)) {
            _map.put(DATABASE_USERNAME, "fedoraAdmin");
            _map.put(DATABASE_PASSWORD, "fedoraAdmin");
            _map.put(DATABASE_DRIVER, INCLUDED);
            _map.put(DATABASE_JDBCURL, includedJDBCURL);
            _map.put(DATABASE_DRIVERCLASS, EMBEDDED_DATABASE_DRIVERCLASSNAME);
        } else {
            boolean dbValidated = false;
            while (!dbValidated) {
                inputOption(driver);
                _map.put(DATABASE_DRIVER, getValue(driver));
                inputOption(DATABASE_USERNAME);
                inputOption(DATABASE_PASSWORD);
                inputOption(jdbcURL);
                _map.put(DATABASE_JDBCURL, getValue(jdbcURL));
                inputOption(jdbcDriverClass);
                _map.put(DATABASE_DRIVERCLASS, getValue(jdbcDriverClass));
                dbValidated = validateDatabaseConnection();
            }
        }
        inputOption(UPSTREAM_AUTH_ENABLED);
        if (getBooleanValue(UPSTREAM_AUTH_ENABLED,false)) {
        		// disable FESL authN if upstream authN is enabled
        		_map.put(FESL_AUTHN_ENABLED, Boolean.toString(false));
        }
        inputOption(FESL_AUTHZ_ENABLED);
        if (getValue(FESL_AUTHZ_ENABLED).equals(Boolean.toString(true))) {
            // Disable legacy authz if FeSL is enabled
            _map.put(XACML_ENABLED, Boolean.toString(false));
        } else {
        	inputOption(XACML_ENABLED);
        }

        inputOption(LLSTORE_TYPE);
        inputOption(RI_ENABLED);
        inputOption(MESSAGING_ENABLED);
        if (getValue(MESSAGING_ENABLED).equals(Boolean.toString(true))) {
            inputOption(MESSAGING_URI);
        }

        inputOption(DEPLOY_LOCAL_SERVICES);
    }

    private static void checkJavaVersion() throws InstallationCancelledException {
        String v = System.getProperty("java.version");
        if (v.startsWith("1.3") || v.startsWith("1.4") || v.startsWith("1.5")) {
            System.err.println("ERROR: Java " + v + " is too old; This version"
                    + " of Fedora requires Java 1.6 or above.");
            throw new InstallationCancelledException();
        }
    }

    private String dashes(int len) {
        StringBuffer out = new StringBuffer();
        for (int i = 0; i < len; i++) {
            out.append('-');
        }
        return out.toString();
    }

    /**
     * Get the indicated option from the console. Continue prompting until the
     * value is valid, or the user has indicated they want to cancel the
     * installation.
     */
    private void inputOption(String optionId)
            throws InstallationCancelledException {

        OptionDefinition opt = OptionDefinition.get(optionId, this);

        if (opt.getLabel() == null || opt.getLabel().length() == 0) {
            throw new InstallationCancelledException(optionId
                    + " is missing label (check OptionDefinition.properties?)");
        }
        System.out.println(opt.getLabel());
        System.out.println(dashes(opt.getLabel().length()));
        System.out.println(opt.getDescription());

        System.out.println();

        String[] valids = opt.getValidValues();
        if (valids != null) {
            System.out.print("Options : ");
            for (int i = 0; i < valids.length; i++) {
                if (i > 0) {
                    System.out.print(", ");
                }
                System.out.print(valids[i]);
            }
            System.out.println();
        }

        String defaultVal = opt.getDefaultValue();
        if (valids != null || defaultVal != null) {
            System.out.println();
        }

        boolean gotValidValue = false;

        while (!gotValidValue) {

            System.out.print("Enter a value ");
            if (defaultVal != null) {
                System.out.print("[default is " + defaultVal + "] ");
            }
            System.out.print("==> ");

            String value = readLine().trim();
            if (value.length() == 0 && defaultVal != null) {
                value = defaultVal;
            }
            System.out.println();
            if (value.equalsIgnoreCase("cancel")) {
                throw new InstallationCancelledException("Cancelled by user.");
            }

            try {
                opt.validateValue(value);
                gotValidValue = true;
                _map.put(optionId, value);
                System.out.println();
            } catch (OptionValidationException e) {
                System.out.println("Error: " + e.getMessage());
            }
        }
    }

    private String readLine() {
        try {
            BufferedReader reader =
                    new BufferedReader(new InputStreamReader(System.in));
            return reader.readLine();
        } catch (Exception e) {
            throw new RuntimeException("Error: Unable to read from STDIN");
        }
    }

    /**
     * Dump all options (including any defaults that were applied) to the given
     * stream, in java properties file format. The output stream remains open
     * after this method returns.
     */
    public void dump(OutputStream out) throws IOException {

        Properties props = new Properties();
        Iterator iter = _map.keySet().iterator();
        while (iter.hasNext()) {
            String key = iter.next();
            props.setProperty(key, getValue(key));
        }

        props.store(out, "Install Options");
    }

    /**
     * Get the value of the given option, or null if it doesn't
     * exist.
     */
    public String getValue(String name) {
        return System.getProperty(name, _map.get(name));
    }

    public String getValue(String name, String defaultVal) {
        String value = getValue(name);


        if (value == null) {
            return defaultVal;
        } else {
            return value;
        }

    }

    /**
     * Get the value of the given option as an integer, or the given default
     * value if unspecified.
     *
     * @throws NumberFormatException
     *         if the value is specified, but cannot be parsed as an integer.
     */
    public int getIntValue(String name, int defaultValue)
            throws NumberFormatException {

        String value = getValue(name);

        if (value == null) {
            return defaultValue;
        } else {
            return Integer.parseInt(value);
        }
    }

    /**
     * Get the value of the given option as a boolean, or the given default
     * value if unspecified. If specified, the value is assumed to be
     * true if given as "true", regardless of case. All other
     * values are assumed to be false.
     */
    public boolean getBooleanValue(String name, boolean defaultValue) {

        String value = getValue(name);

        if (value == null) {
            return defaultValue;
        } else {
            return value.equals("true");
        }
    }

    /**
     * Get an iterator of the names of all specified options.
     */
    public Collection getOptionNames() {
    	return _map.keySet();
    }

    /**
     * Apply defaults to the options, where possible.
     */
    private void applyDefaults() {
        for (String name : getOptionNames()) {
        	String val = _map.get(name);
        	if (val == null || val.length() == 0) {
                OptionDefinition opt = OptionDefinition.get(name, this);
                _map.put(name, opt.getDefaultValue());
            }
        }
    }

    /**
     * Validate the options, assuming defaults have already been applied.
     * Validation for a given option might entail more than a syntax check. It
     * might check whether a given directory exists, for example.
     *
     */
    private void validateAll() throws OptionValidationException {
        boolean unattended = getBooleanValue(UNATTENDED, false);
        for (String optionId : getOptionNames()) {
            OptionDefinition opt = OptionDefinition.get(optionId, this);
            if (opt == null) {
                throw new OptionValidationException("Option is not defined", optionId);
            }
            opt.validateValue(getValue(optionId), unattended);
        }
    }

    private boolean validateDatabaseConnection() {
        String database = getValue(DATABASE);
        if (database.equals(InstallOptions.INCLUDED)) {
            return true;
        }

        Database db = new Database(_dist, this);

        try {
            // validate the user input by attempting a database connection
            System.out.print("Validating database connection...");
            db.test();
            // check if we need to update old table
            if (db.usesDOTable()) {
                inputOption(DATABASE_UPDATE);
            }

            db.close();
            System.out.println("OK\n");
            return true;
        } catch (Exception e) {
            System.out.println("FAILED\n");
            e.printStackTrace();
            System.out.println(e.getClass().getName() + ": " + e.getMessage() + "\n");
            System.out.println("ERROR validating database connection; see above.\n");
            return false;
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy