org.fcrepo.utilities.install.FedoraHome Maven / Gradle / Ivy
/* 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 = " ";
} else if (line.indexOf("/tmp/datastreamStore") != -1) {
line = " ";
}
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)", "");
}
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)", "$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() });
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy