Package org.fcrepo.utilities.install

Source Code of org.fcrepo.utilities.install.FedoraHome

/* 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.BufferedWriter;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.fcrepo.server.config.ModuleConfiguration;
import org.fcrepo.server.config.ServerConfiguration;
import org.fcrepo.server.config.ServerConfigurationParser;
import org.fcrepo.server.resourceIndex.ResourceIndex;
import org.fcrepo.server.security.BESecurityConfig;
import org.fcrepo.server.security.DefaultRoleConfig;
import org.fcrepo.server.security.servletfilters.xmluserfile.FedoraUsers;
import org.fcrepo.server.security.servletfilters.xmluserfile.User;
import org.fcrepo.utilities.ExecUtility;
import org.fcrepo.utilities.FileUtils;
import org.fcrepo.utilities.Zip;

public class FedoraHome {

  private final Distribution _dist;

  private final InstallOptions _opts;

  private final File _installDir;

  private final boolean _clientOnlyInstall;

  private InetAddress _host;

  private LLStoreType _usingAkubra;

  public FedoraHome(Distribution dist, InstallOptions opts) {
    _dist = dist;
    _opts = opts;
    _installDir = new File(_opts.getValue(InstallOptions.FEDORA_HOME));
    _clientOnlyInstall = _opts.getValue(InstallOptions.INSTALL_TYPE)
        .equals(InstallOptions.INSTALL_CLIENT);
  }

  public void install() throws InstallationFailedException {
    unpack();

    if (!_clientOnlyInstall) {
      configure();
    }
  }

  /**
   * Unpacks the contents of the FEDORA_HOME directory from the Distribution.
   *
   * @throws InstallationFailedException
   */
  private void unpack() throws InstallationFailedException {
    System.out.println("Preparing FEDORA_HOME...");

    if (!_installDir.exists() && !_installDir.mkdirs()) {
      throw new InstallationFailedException(
          "Unable to create FEDORA_HOME: "
              + _installDir.getAbsolutePath());
    }
    if (!_installDir.isDirectory()) {
      throw new InstallationFailedException(_installDir.getAbsolutePath()
          + " is not a directory");
    }
    try {
      Zip.unzip(_dist.get(Distribution.FEDORA_HOME), _installDir);
      setScriptsExecutable(new File(_installDir, "client"
          + File.separator + "bin"));

      File serverDir = new File(_installDir, "server");
      if (_clientOnlyInstall) {
        FileUtils.delete(serverDir);
      } else {
        setScriptsExecutable(new File(serverDir, "bin"));
      }
    } catch (IOException e) {
      throw new InstallationFailedException(e.getMessage(), e);
    }
  }

  /**
   * Sets various configuration files based on InstallOptions
   *
   * @throws InstallationFailedException
   */
  private void configure() throws InstallationFailedException {
    configureFCFG();
        configureAkubra();
    configureSpringProperties();
    configureSpringAuth();
    configureFedoraUsers();
    configureBeSecurity();
    configureSpringTestConfigs();
  }

  private void configureFCFG() throws InstallationFailedException {
    System.out.println("\tConfiguring fedora.fcfg");
    File fcfgBase = new File(_installDir,
        "server/fedora-internal-use/config/fedora-base.fcfg");
    File fcfg = new File(_installDir, "server/config/fedora.fcfg");

    Properties props = new Properties();
    if (_opts.getValue(InstallOptions.TOMCAT_HTTP_PORT) != null) {
      props.put("server:fedoraServerPort",
          _opts.getValue(InstallOptions.TOMCAT_HTTP_PORT));
    }
    if (_opts.getValue(InstallOptions.TOMCAT_SHUTDOWN_PORT) != null) {
      props.put("server:fedoraShutdownPort",
          _opts.getValue(InstallOptions.TOMCAT_SHUTDOWN_PORT));
    }
    if (_opts.getValue(InstallOptions.TOMCAT_SSL_PORT) != null) {
      props.put("server:fedoraRedirectPort",
          _opts.getValue(InstallOptions.TOMCAT_SSL_PORT));
    }
    if (_opts.getValue(InstallOptions.FEDORA_SERVERHOST) != null) {
      props.put("server:fedoraServerHost",
          _opts.getValue(InstallOptions.FEDORA_SERVERHOST));
    }

    if (_opts.getValue(InstallOptions.FEDORA_APP_SERVER_CONTEXT) != null) {
      props.put("server:fedoraAppServerContext",
          _opts.getValue(InstallOptions.FEDORA_APP_SERVER_CONTEXT));
    }

    String database = _opts.getValue(InstallOptions.DATABASE);
    String dbPoolName = "";
    String backslashIsEscape = "true";
    if (database.equals(InstallOptions.DERBY)
        || database.equals(InstallOptions.INCLUDED)) {
      dbPoolName = "localDerbyPool";
      backslashIsEscape = "false";
    } else if (database.equals(InstallOptions.MYSQL)) {
      dbPoolName = "localMySQLPool";
    } else if (database.equals(InstallOptions.ORACLE)) {
      dbPoolName = "localOraclePool";
      backslashIsEscape = "false";
    } else if (database.equals(InstallOptions.POSTGRESQL)) {
      dbPoolName = "localPostgreSQLPool";
    } else {
      throw new InstallationFailedException(
          "unable to configure for unknown database: " + database);
    }
    props.put("module.org.fcrepo.server.storage.DOManager:storagePool",
        dbPoolName);
    props.put("module.org.fcrepo.server.search.FieldSearch:connectionPool",
        dbPoolName);
    props.put(
        "module.org.fcrepo.server.storage.ConnectionPoolManager:poolNames",
        dbPoolName);
    props.put(
        "module.org.fcrepo.server.storage.ConnectionPoolManager:defaultPoolName",
        dbPoolName);
    props.put(
        "module.org.fcrepo.server.storage.lowlevel.ILowlevelStorage:backslash_is_escape",
        backslashIsEscape);
    props.put("datastore." + dbPoolName + ":jdbcURL",
        _opts.getValue(InstallOptions.DATABASE_JDBCURL));
    props.put("datastore." + dbPoolName + ":dbUsername",
        _opts.getValue(InstallOptions.DATABASE_USERNAME));
    props.put("datastore." + dbPoolName + ":dbPassword",
        _opts.getValue(InstallOptions.DATABASE_PASSWORD));
    props.put("datastore." + dbPoolName + ":jdbcDriverClass",
        _opts.getValue(InstallOptions.DATABASE_DRIVERCLASS));

    if (_opts.getBooleanValue(InstallOptions.XACML_ENABLED, true)) {
      props.put(
          "module.org.fcrepo.server.security.Authorization:ENFORCE-MODE",
          "enforce-policies");
    } else {
      props.put(
          "module.org.fcrepo.server.security.Authorization:ENFORCE-MODE",
          "permit-all-requests");
    }

    if (_opts.getBooleanValue(InstallOptions.RI_ENABLED, true)) {
      props.put(
          "module.org.fcrepo.server.resourceIndex.ResourceIndex:level",
          String.valueOf(ResourceIndex.INDEX_LEVEL_ON));
    } else {
      props.put(
          "module.org.fcrepo.server.resourceIndex.ResourceIndex:level",
          String.valueOf(ResourceIndex.INDEX_LEVEL_OFF));
    }

    if (_opts.getBooleanValue(InstallOptions.MESSAGING_ENABLED, false)) {
      props.put("module.org.fcrepo.server.messaging.Messaging:enabled",
          String.valueOf(true));
      props.put(
          "module.org.fcrepo.server.messaging.Messaging:java.naming.provider.url",
          _opts.getValue(InstallOptions.MESSAGING_URI));
    } else {
      props.put("module.org.fcrepo.server.messaging.Messaging:enabled",
          String.valueOf(false));
    }

    props.put(
        "module.org.fcrepo.server.access.Access:doMediateDatastreams",
        _opts.getValue(InstallOptions.APIA_AUTH_REQUIRED));

    // FeSL AuthZ needs a management decorator for syncing the policy cache
    // with policies in objects
    if (_opts.getBooleanValue(InstallOptions.FESL_AUTHZ_ENABLED, false)) {
      // NOTE: assumes messaging decorator only is present in
      // fedora-base.fcfg as decorator1
      props.put(
          "module.org.fcrepo.server.management.Management:decorator2",
          "org.fcrepo.server.security.xacml.pdp.decorator.PolicyIndexInvocationHandler");
    }

    try {
      FileInputStream fis = new FileInputStream(fcfgBase);
      ServerConfiguration config = new ServerConfigurationParser(fis)
          .parse();
      config.applyProperties(props);

      // If using akubra-fs, set the class of the module and clear params.
      if (usingAkubra()) {
        ModuleConfiguration mConfig = config
            .getModuleConfiguration("org.fcrepo.server.storage.lowlevel.ILowlevelStorage");
        config.getModuleConfigurations().remove(mConfig);
      }

      config.serialize(new FileOutputStream(fcfg));
    } catch (IOException e) {
      throw new InstallationFailedException(e.getMessage(), e);
    }
  }

  private void configureAkubra() throws InstallationFailedException {
      if (usingAkubra()) {
        // Rewrite server/config/akubra-llstore.xml replacing the
        // /tmp/[object|datastream]Store constructor-arg values
        // with $FEDORA_HOME/data/[object|datastream]Store
        BufferedReader reader = null;
        PrintWriter writer = null;
        try {
          File file = new File(_installDir,
              "server/config/spring/akubra-llstore.xml");
          reader = new BufferedReader(new InputStreamReader(
              new FileInputStream(file), "UTF-8"));
   
          File dataDir = new File(_installDir, "data");
          String oPath = dataDir.getPath() + File.separator + "objectStore";
          String dPath = dataDir.getPath() + File.separator
              + "datastreamStore";
          StringBuilder xml = new StringBuilder();
   
          String line = reader.readLine();
          while (line != null) {
            if (line.indexOf("/tmp/objectStore") != -1) {
              line = "    <constructor-arg value=\"" + oPath + "\"/>";
            } else if (line.indexOf("/tmp/datastreamStore") != -1) {
              line = "    <constructor-arg value=\"" + dPath + "\"/>";
            }
            xml.append(line + "\n");
            line = reader.readLine();
          }
          reader.close();
   
          writer = new PrintWriter(new OutputStreamWriter(
              new FileOutputStream(file), "UTF-8"));
          writer.print(xml.toString());
          writer.close();
        } catch (IOException e) {
          IOUtils.closeQuietly(reader);
          IOUtils.closeQuietly(writer);
          throw new InstallationFailedException(e.getClass().getName() + ":"
              + e.getMessage());
        }
      } else {
          // remove the stub akubra configuration
            File file = new File(_installDir,
                    "server/config/spring/akubra-llstore.xml");
            file.delete();
            if (file.exists()){
                throw new InstallationFailedException("Could not remove a conflicting config: akubra-llstore.xml");
            }
      }
  }

  private void configureSpringProperties() throws InstallationFailedException {
    Properties springProps = new Properties();

    /* Set up ssl configuration */
    springProps.put("fedora.port",
        _opts.getValue(InstallOptions.TOMCAT_HTTP_PORT, "8080"));
    if (_opts.getBooleanValue(InstallOptions.SSL_AVAILABLE, false)) {
      springProps.put("fedora.port.secure",
          _opts.getValue(InstallOptions.TOMCAT_SSL_PORT, "8443"));
    } else {
      springProps.put("fedora.port.secure",
          _opts.getValue(InstallOptions.TOMCAT_HTTP_PORT, "8080"));
    }

    springProps
        .put("security.ssl.api.access",
            _opts.getBooleanValue(InstallOptions.APIA_SSL_REQUIRED,
                false) ? "REQUIRES_SECURE_CHANNEL"
                : "ANY_CHANNEL");
    springProps
        .put("security.ssl.api.management",
            _opts.getBooleanValue(InstallOptions.APIM_SSL_REQUIRED,
                false) ? "REQUIRES_SECURE_CHANNEL"
                : "ANY_CHANNEL");
    springProps.put("security.ssl.api.default", "ANY_CHANNEL");

    springProps.put("security.fesl.authN.jaas.apia.enabled",
        _opts.getValue(InstallOptions.APIA_AUTH_REQUIRED, "false"));

    springProps.put("security.fesl.authZ.enabled",
        _opts.getValue(InstallOptions.FESL_AUTHZ_ENABLED, "false"));

    /* Set up authN, authZ filter configuration */
    StringBuilder filters = new StringBuilder();
        if (_opts.getBooleanValue(InstallOptions.FESL_AUTHN_ENABLED, true)) {
      filters.append("AuthFilterJAAS");
    } else {
      filters.append("SetupFilter,XmlUserfileFilter,EnforceAuthnFilter,FinalizeFilter");
    }

    if (_opts.getBooleanValue(InstallOptions.FESL_AUTHZ_ENABLED, false)) {
      filters.append(",PEPFilter");
    }

    springProps.put("security.auth.filters", filters.toString());

    FileOutputStream out = null;
    try {
      out = new FileOutputStream(new File(_installDir,
          "server/config/spring/web/web.properties"));
      springProps.store(out, "Spring override properties");
    } catch (IOException e) {
      throw new InstallationFailedException(e.getMessage(), e);
    } finally {
      IOUtils.closeQuietly(out);
    }
  }

  /*
   * This is an ugly workaround for the fact that spring security namespace
   * config does not support property substitution into lists of beans. It is
   * also ugly because
   */
  private void configureSpringAuth() throws InstallationFailedException {
    String PATTERN = "${security.auth.filters}";
    String PATTERN_APIA = "${security.auth.filters.apia}";
    String PATTERN_REST = "${security.auth.filters.rest}";

    boolean fesl_authn_enabled = _opts.getBooleanValue(
InstallOptions.FESL_AUTHN_ENABLED, true);
    boolean apia_auth_required = _opts.getBooleanValue(
        InstallOptions.APIA_AUTH_REQUIRED, false);
    boolean upstream_auth_enabled = _opts.getBooleanValue(
        InstallOptions.UPSTREAM_AUTH_ENABLED, false);

    StringBuilder filters = new StringBuilder();
    StringBuilder filters_apia = new StringBuilder();
    StringBuilder filters_rest = new StringBuilder();

    boolean needsbugFix = false;

    if (fesl_authn_enabled) {
      filters.append("AuthFilterJAAS");
      filters_apia.append("AuthFilterJAAS");
      filters_rest.append("AuthFilterJAAS");
    } else if (upstream_auth_enabled) {
      // use upstream auth filter and nothing else
      String upstreamAuthFilter = "UpstreamAuthFilter";
      filters.append(upstreamAuthFilter);
      filters_apia.append(upstreamAuthFilter);
      filters_rest.append(upstreamAuthFilter);
    }
    else {
      filters.append("SetupFilter,XmlUserfileFilter,EnforceAuthnFilter,FinalizeFilter");
      if (apia_auth_required) {
        filters_apia
            .append("SetupFilter,XmlUserfileFilter,EnforceAuthnFilter,FinalizeFilter");
        filters_rest
            .append("SetupFilter,XmlUserfileFilter,EnforceAuthnFilter,FinalizeFilter");
      } else {
        filters_apia.append("");
        filters_rest
            .append("SetupFilter,XmlUserfileFilter,RestApiAuthnFilter,FinalizeFilter");
      }

      needsbugFix = true;
    }

    if (_opts.getBooleanValue(InstallOptions.FESL_AUTHZ_ENABLED, false)) {
      filters.append(",PEPFilter");
      filters_apia.append(",PEPFilter");
      filters_rest.append(",PEPFilter");
      copyFESLConfigs();
    }

    FileInputStream springConfig = null;
    PrintWriter writer = null;
    try {
      File xmlFile = new File(_installDir,
          "server/config/spring/web/security.xml");
      springConfig = new FileInputStream(xmlFile);
      String content = IOUtils.toString(springConfig)
          .replace(PATTERN, filters)
          .replace(PATTERN_APIA, filters_apia)
          .replace(PATTERN_REST, filters_rest);

      if (!needsbugFix) {
        /* Delete classic authN bugfix when not applicable */
        content = content.replaceFirst("(?s)<!-- BUG.+?/BUG -->", "");
      }

      springConfig.close();

      writer = new PrintWriter(new OutputStreamWriter(
          new FileOutputStream(xmlFile), "UTF-8"));
      writer.print(content);
      writer.close();
    } catch (Exception e) {
      IOUtils.closeQuietly(springConfig);
      IOUtils.closeQuietly(writer);
      throw new InstallationFailedException(e.getMessage(), e);
    }
  }

  private void copyFESLConfigs() throws InstallationFailedException {
    File feslWebDir = new File(_installDir, "server/config/spring/fesl/web");
    File feslModuleDir = new File(_installDir,
        "server/config/spring/fesl/module");
    File webDir = new File(_installDir, "server/config/spring/web");
    File moduleDir = new File(_installDir, "server/config/spring");

    for (File beanDef : feslWebDir.listFiles()) {
      if (beanDef.isFile()) {
        FileReader reader = null;
        FileWriter writer = null;
        try {
          File copy = new File(webDir, beanDef.getName());
          reader = new FileReader(beanDef);
          writer = new FileWriter(copy);
          IOUtils.copy(reader, writer);
          writer.flush();
        } catch (Exception e) {
          throw new InstallationFailedException(e.getMessage(), e);
        } finally {
          IOUtils.closeQuietly(writer);
          IOUtils.closeQuietly(reader);
        }
      }
    }
    for (File beanDef : feslModuleDir.listFiles()) {
      if (beanDef.isFile()) {
        FileReader reader = null;
        FileWriter writer = null;
        try {
          File copy = new File(moduleDir, beanDef.getName());
          reader = new FileReader(beanDef);
          writer = new FileWriter(copy);
          IOUtils.copy(reader, writer);
          writer.flush();
        } catch (Exception e) {
          throw new InstallationFailedException(e.getMessage(), e);
        } finally {
          IOUtils.closeQuietly(writer);
          IOUtils.closeQuietly(reader);
        }
      }
    }
  }

  private void configureSpringTestConfigs()
      throws InstallationFailedException {
    if (_opts.getBooleanValue(InstallOptions.TEST_SPRING_CONFIGS, false)) {
      FileInputStream springConfig = null;
      PrintWriter writer = null;
      try {
        File springDir = new File(_installDir, "server/config/spring");
        for (File file : springDir.listFiles()) {
          if (file.isFile()) {
            springConfig = new FileInputStream(file);
            String content = IOUtils.toString(springConfig);
            content = content.replaceAll(
                "(?s)<!-- TESTONLY(.+?)/TESTONLY -->", "$1");
            springConfig.close();

            writer = new PrintWriter(new OutputStreamWriter(
                new FileOutputStream(file), "UTF-8"));
            writer.print(content);
            writer.close();
          }
        }
      } catch (Exception e) {
        IOUtils.closeQuietly(springConfig);
        IOUtils.closeQuietly(writer);
        throw new InstallationFailedException(e.getMessage(), e);
      }
    }
  }

  private void configureFedoraUsers() throws InstallationFailedException {
    FedoraUsers fu = FedoraUsers.getInstance();
    for (User user : fu.getUsers()) {
      if (user.getName().equals("fedoraAdmin")) {
        user.setPassword(_opts
            .getValue(InstallOptions.FEDORA_ADMIN_PASS));
      }
    }

    try {
      Writer outputWriter = new BufferedWriter(new FileWriter(
          FedoraUsers.fedoraUsersXML));
      fu.write(outputWriter);
      outputWriter.close();
    } catch (IOException e) {
      throw new InstallationFailedException(e.getMessage(), e);
    }
  }

  private void configureBeSecurity() throws InstallationFailedException {
    System.out.println("\tInstalling beSecurity");
    File beSecurity = new File(_installDir, "/server/config/beSecurity.xml");
    boolean apiaAuth = _opts.getBooleanValue(
        InstallOptions.APIA_AUTH_REQUIRED, false);
    boolean apiaSSL = _opts.getBooleanValue(
        InstallOptions.APIA_SSL_REQUIRED, false);
    // boolean apimSSL =
    // _opts.getBooleanValue(InstallOptions.APIM_SSL_REQUIRED, false);

    String[] ipList;
    String host = _opts.getValue(InstallOptions.FEDORA_SERVERHOST);
    if (host != null && host.length() != 0
        && !(host.equals("localhost") || host.equals("127.0.01"))) {
      ipList = new String[] { "127.0.0.1", getHost() };
    } else {
      ipList = new String[] { "127.0.0.1" };
    }

    PrintWriter pwriter;
    try {
      pwriter = new PrintWriter(new FileOutputStream(beSecurity));
    } catch (FileNotFoundException e) {
      throw new InstallationFailedException(e.getMessage(), e);
    }
    BESecurityConfig becfg = new BESecurityConfig();

    becfg.setDefaultConfig(new DefaultRoleConfig());
    becfg.setInternalBasicAuth(new Boolean(apiaAuth));
    becfg.setInternalIPList(ipList);
    becfg.setInternalPassword("changeme");
    becfg.setInternalSSL(new Boolean(apiaSSL));
    becfg.setInternalUsername("fedoraIntCallUser");
    becfg.write(true, true, pwriter);
    pwriter.close();
  }

  private String getHost() throws InstallationFailedException {
    if (_host == null) {
      String host = _opts.getValue(InstallOptions.FEDORA_SERVERHOST);
      try {
        _host = InetAddress.getByName(host);
      } catch (UnknownHostException e) {
        throw new InstallationFailedException(e.getMessage(), e);
      }
    }
    return _host.getHostAddress();
  }
 
  private boolean usingAkubra() {
      if (_usingAkubra == null) {
            String llStoreType = _opts.getValue(InstallOptions.LLSTORE_TYPE);
            if (llStoreType == null || llStoreType.equals("akubra-fs")) {
                _usingAkubra = LLStoreType.akubra_fs;
            } else {
                _usingAkubra = LLStoreType.legacy_fs;
            }
      }
      return LLStoreType.akubra_fs == _usingAkubra;
  }

  /**
   * Make scripts (ending with .sh) executable on *nix systems.
   */
  public static void setScriptsExecutable(File dir) {
    String os = System.getProperty("os.name");
    if (os != null && !os.startsWith("Windows")) {
      FileFilter filter = FileUtils.getSuffixFileFilter(".sh");
      setExecutable(dir, filter);
    }
  }

  private static void setExecutable(File dir, FileFilter filter) {
    File[] files;
    if (filter != null) {
      files = dir.listFiles(filter);
    } else {
      files = dir.listFiles();
    }
    for (File element : files) {
      ExecUtility.exec(new String[] { "chmod", "+x",
          element.getAbsolutePath() });
    }
  }
}
TOP

Related Classes of org.fcrepo.utilities.install.FedoraHome

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.